R中%in%运算符的C ++版本 [英] A C++ version of the %in% operator in R
问题描述
C ++中是否有任何功能等效于R中的%in%
运算符?考虑以下R中的命令:
Is there any function in C++ equivalent to %in%
operator in R? Consider the command below in R:
which(y %in% x)
我试图在C ++中找到等效的东西(特别是在Armadillo中),但找不到任何东西.然后,我编写了自己的函数,该函数与上面的R命令相比非常慢.
I tried to find something equivalent in C++ (specifically in Armadillo) and I couldn't find anything. I then wrote my own function which is very slow compared to the R command above.
这是我写的:
#include <RcppArmadillo.h>
// [[Rcpp::depends("RcppArmadillo")]]
// [[Rcpp::export]]
arma::uvec myInOperator(arma::vec myBigVec, arma::vec mySmallVec ){
arma::uvec rslt = find(myBigVec == mySmallVec[0]);
for (int i = 1; i < mySmallVec.size(); i++){
arma::uvec rslt_tmp = find(myBigVec == mySmallVec[i]);
rslt = arma::unique(join_cols( rslt, rslt_tmp ));
}
return rslt;
}
现在,在采购完上面的代码之后,我们有了:
Now after sourcing in the code above, we have:
x <- 1:4
y <- 1:10
res <- benchmark(myInOperator(y, x), which(y %in% x), columns = c("test",
"replications", "elapsed", "relative", "user.self", "sys.self"),
order = "relative")
结果如下:
test replications elapsed relative user.self sys.self
2 which(y %in% x) 100 0.001 1 0.001 0
1 myInOperator(y, x) 100 0.002 2 0.001 0
有人能指导我寻找与哪个代码(y%in%x)相对应的C ++代码,或者使我的代码更高效吗?这两个功能的经过时间已经很小.从编程的角度以及我对问题的思考方式和所使用的命令是否有效,我想效率的含义更多.
Could anyone guide me either on finding a C++ code corresponding to which(y %in% x) or on making my code more efficient? The elapsed time is already very small for both functions. I guess what I meant by efficiency is more from programming perspective and on whether the way I thought about the problem and the commands I used are efficient.
感谢您的帮助.
推荐答案
感谢@MatthewLundberg和@Yakk捕获了我的愚蠢错误.
Thanks to @MatthewLundberg and @Yakk for catching my silly errors.
如果您真正想要的只是快速匹配,则应查看Simon Urbanek的快速匹配一个>包.但是,实际上 Rcpp
确实有一个糖 in
函数,可以在这里使用它. in
使用了 fastmatch
包中的一些想法,并将其合并到 Rcpp
中.我还在这里比较@hadley的解决方案.
If what you really want is just faster matching, you should check out Simon Urbanek's fastmatch package. However, Rcpp
does in fact have a sugar in
function which can be used here. in
uses some of the ideas from the fastmatch
package and incorporates them into Rcpp
. I also compare @hadley's solution here.
// [[Rcpp::plugins("cpp11")]]
#include <Rcpp.h>
using namespace Rcpp;
// [[Rcpp::export]]
std::vector<int> sugar_in(IntegerVector x, IntegerVector y) {
LogicalVector ind = in(x, y);
int n = ind.size();
std::vector<int> output;
output.reserve(n);
for (int i=0; i < n; ++i) {
if (ind[i]) output.push_back(i+1);
}
return output;
}
// [[Rcpp::export]]
std::vector<int> which_in(IntegerVector x, IntegerVector y) {
int nx = x.size();
std::unordered_set<int> z(y.begin(), y.end());
std::vector<int> output;
output.reserve(nx);
for (int i=0; i < nx; ++i) {
if (z.find( x[i] ) != z.end() ) {
output.push_back(i+1);
}
}
return output;
}
// [[Rcpp::export]]
std::vector<int> which_in2(IntegerVector x, IntegerVector y) {
std::vector<int> y_sort(y.size());
std::partial_sort_copy (y.begin(), y.end(), y_sort.begin(), y_sort.end());
int nx = x.size();
std::vector<int> out;
for (int i = 0; i < nx; ++i) {
std::vector<int>::iterator found =
lower_bound(y_sort.begin(), y_sort.end(), x[i]);
if (found != y_sort.end()) {
out.push_back(i + 1);
}
}
return out;
}
/*** R
set.seed(123)
library(microbenchmark)
x <- sample(1:100)
y <- sample(1:10000, 1000)
identical( sugar_in(y, x), which(y %in% x) )
identical( which_in(y, x), which(y %in% x) )
identical( which_in2(y, x), which(y %in% x) )
microbenchmark(
sugar_in(y, x),
which_in(y, x),
which_in2(y, x),
which(y %in% x)
)
*/
在基准上调用 sourceCpp
会给我
Unit: microseconds
expr min lq median uq max neval
sugar_in(y, x) 7.590 10.0795 11.4825 14.3630 32.753 100
which_in(y, x) 40.757 42.4460 43.4400 46.8240 63.690 100
which_in2(y, x) 14.325 15.2365 16.7005 17.2620 30.580 100
which(y %in% x) 17.070 21.6145 23.7070 29.0105 78.009 100
这篇关于R中%in%运算符的C ++版本的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!