我在R代码中使用"%within[]%" <- function(x,y){x>=y[1] & x<=y[2]}
(意思是x
在紧凑集y
中),但我很确定它非常慢。你有更快的东西吗?它需要适用于定义>
的所有内容。
编辑:x
可以是一个向量,y
一个2元素向量按升序排列......
EDIT2:奇怪的是,没有人(据我所知)编写了一个包rOperator
来实现快速C
运算符,例如%w/i[]%, %w/i[[%, ...
EDIT3:我意识到我的问题过于笼统,因为x,y
上的假设会修改任何结果,我想我们应该关闭它,谢谢你的意见。
答案 0 :(得分:6)
"%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
这可能是Rcpp的工作。
答案 1 :(得分:3)
通过简单的Rcpp实现,您可以获得较小的性能提升:
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))
)
C ++版本在我的电脑上快了大约4倍。如果你想使用更多的Rcpp技巧,你可能会进一步调整它,但这似乎已经很快了。即使R版本需要在它可能成为瓶颈之前被频繁调用。
# 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
答案 2 :(得分:1)
嗯,我不知道这是否会被认为是缓慢的,但这里有一些基准:
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
因此,如Konrad Rudolph所建议的那样省略return
似乎加速了一些事情。但是不写函数要快得多。
答案 3 :(得分:1)