Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/r/80.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
最快的R实现_R_Optimization_Operators - Fatal编程技术网

最快的R实现

最快的R实现,r,optimization,operators,R,Optimization,Operators,我使用[]%内的”=y[1]&x定义了 编辑:x可以是一个向量,y可以是一个按升序排列的2元素向量 编辑2:奇怪的是,据我所知,没有人编写一个包rOperator来实现快速C操作符,比如%w/i[]%,%w/i[%,… EDIT3:我意识到我的问题太笼统了,因为假设x,y会修改任何结果,我认为我们应该关闭它,谢谢你的输入。嗯,我不知道这是否可以被认为是缓慢的,但这里有一点基准: R> within <- function(x,y){return(x>=y[1] & x&

我使用[]%内的
”=y[1]&x定义了

编辑:
x
可以是一个向量,
y
可以是一个按升序排列的2元素向量

编辑2:奇怪的是,据我所知,没有人编写一个包
rOperator
来实现快速
C
操作符,比如
%w/i[]%,%w/i[%,…


EDIT3:我意识到我的问题太笼统了,因为假设
x,y
会修改任何结果,我认为我们应该关闭它,谢谢你的输入。

嗯,我不知道这是否可以被认为是缓慢的,但这里有一点基准:

R> within <- function(x,y){return(x>=y[1] & x<=y[2])}
R> microbenchmark(within(2,c(1,5)))
Unit: microseconds
               expr   min     lq median    uq    max neval
 within(2, c(1, 5)) 2.667 2.8305 2.9045 2.969 15.818   100

R> within2 <- function(x,y) x>=y[1] & x<=y[2]
R> microbenchmark(within2(2,c(1,5)))
Unit: microseconds
                expr   min     lq median    uq    max neval
 within2(2, c(1, 5)) 2.266 2.3205  2.398 2.483 12.472   100

R> microbenchmark(2>=1 & 2<=5)
Unit: nanoseconds
            expr min    lq median  uq  max neval
 2 >= 1 & 2 <= 5 781 821.5    850 911 5701   100
R>within=y[1]&x微基准(within(2,c(1,5)))
单位:微秒
expr最小lq中值uq最大neval
在(2,c(1,5))2.6672.83052.90452.96915.818100范围内
R> within2=y[1]&x微基准(within2(2,c(1,5)))
单位:微秒
expr最小lq中值uq最大neval
其中in2(2,c(1,5))2.2662.32052.3982.48312.472100

R> 如果
x
包含许多值,则基于树的microbenchmark(2>=1&2=1&2结构可以提供更好的性能。如果您可以将要求限制为数值,则有两个选项

可在Bioconductor软件包中找到整数区间树的实现


默认情况下,RSQLite正在编译启用的嵌入式SQLite库。这可以与任何数值一起使用。

%within[]%”=y[1]&x通过简单的Rcpp实现,您可以获得较小的性能改进:

"%within[]%" <- function(x,y){x>=y[1] & x<=y[2]}

x <- 1:10
y <- c(3,5)

x %within[]% y
"%within[]2%" <- function(x,y) findInterval(x,y,rightmost.closed=TRUE)==1
x %within[]2% y

library(microbenchmark)

microbenchmark(x %within[]% y,x %within[]2% y)

Unit: microseconds
             expr   min    lq median    uq    max
1  x %within[]% y 1.849 2.465 2.6185 2.773 11.395
2 x %within[]2% y 4.928 5.544 5.8520 6.160 37.265

x <- 1:1e6
microbenchmark(x %within[]% y,x %within[]2% y)

Unit: milliseconds
             expr      min       lq   median       uq      max
1  x %within[]% y 27.81535 29.60647 31.25193 56.68517 88.16961
2 x %within[]2% y 20.75496 23.07100 24.37369 43.15691 69.62122
library(Rcpp)
library(microbenchmark)

withinR <- function(x,y) x >= y[1] & x <= y[2]
cppFunction("LogicalVector withinCpp(const NumericVector& x, const NumericVector& y) {
  double min = y[0], max = y[1];

  int n = x.size();
  LogicalVector out(n);

  for(int i = 0; i < n; ++i) {
    double val = x[i];
    if (NumericVector::is_na(val)) {
      out[i] = NA_LOGICAL;
    } else {
      out[i] = val >= min & val <= max;
    }

  }
  return out;
}")

x <- sample(100, 1e5, rep = T)

stopifnot(all.equal(withinR(x, c(25, 50)), withinCpp(x, c(25, 50))))

microbenchmark(
  withinR(x, c(25, 50)),
  withinCpp(x, c(25, 50))
)

你的意思是说
y
总是一个两元素向量,带有
y[1]
函数(…){return(…)}
=>
函数(…)…
你可能想要
&
而不是
&
&
似乎比
&
快一点,而且你似乎不需要向量运算,除非x是向量。我的建议实际上不是关于性能,而是关于风格(这里的
返回
函数调用只是多余的)是的,对这些结果并不感到惊讶。&&只比较向量的第一个元素:1:4<4&&1:4>2给出FALSE和not(FALSE,FALSE,TRUE,FALSE)@JanvanderLaan是的,我知道,但是如果你不想要矢量化的操作,
&
会快一点。@juba:我编辑了矢量,因为我的用例更可能是矢量化的。@statquant好的,相应地更新了我的答案。我意识到这比我想象的要复杂,理想情况下这应该与数字一起工作(所以一切都像date,POSIXct…)还有字符(按字典顺序)。将日期转换为整数(从纪元开始的毫秒数)很简单(您的笔名表明您没有使用历史日期或历史前日期)。字符串没有什么特殊性,如何转换需要您做出设计决定(前缀匹配?后缀匹配?完全相同的长度?)是的,甚至不确定是否需要转换,因为POSIXct和Date在内部存储为双精度(奇怪的是Date)。对于字符串理解…+1,直到如何正确使用
微基准
# Unit: microseconds
#                      expr  min   lq median   uq  max
# 1 withinCpp(x, c(25, 50))  635  659    678 1012 27385
# 2   withinR(x, c(25, 50)) 1969 2031   2573 2954 4082