c++ - 匹配逻辑语句的 Rcpp 矩阵的子集

标签 c++ r rcpp

在 R 中,如果我们有一个数据矩阵,比如一个 100 x 10 的矩阵 X,和一个 100 元素的 vector t,它的可能值是 (0, 1, 2, 3),我们可以很容易地找到 X 的子矩阵 y使用简单的语法:

y = X[t == 1, ]

但是,问题是,如何使用 Rcpp 的 NumericMatrix 做到这一点?
(或者,更一般地说,我怎样才能在 C++ 的任何容器中做到这一点?)

多亏德克的提示,看来

NumericMatrix X(dataX);
IntegerVector T(dataT);
mat Xmat(X.begin(), X.nrow(), X.ncol(), false);
vec tIdx(T.begin(), T.size(), false); 
mat y = X.rows(find(tIdx == 1));

可以做我想做的事,但这似乎太冗长了。

最佳答案

我很乐意将其视为糖。不幸的是,我没有资格实现它。这里仍然是我玩过的许多不同的解决方案。

首先,我必须对 Gong-Yi Liao 代码进行一些修改才能使其正常工作(colvec 而不是 vec for tIdxXmat.rows(... 而不是 X.rows(...:

mat Xmat(X.begin(), X.nrow(), X.ncol(), false);
colvec tIdx(T.begin(), T.size(), false); 
mat y = Xmat.rows(find(tIdx == 1));

其次,这里有三个带有基准的函数,所有子集矩阵都基于一个逻辑语句。这些函数采用 arma 或 rcpp 参数并返回值 两个是基于 Gong-Yi Liao 的解决方案,一个是简单的基于循环的解决方案。

n(rows)=100, p(T==1)=0.3

                expr   min     lq median     uq    max
1  submat_arma(X, T) 5.009 5.3955 5.8250 6.2250 28.320
2 submat_arma2(X, T) 4.859 5.2995 5.6895 6.1685 45.122
3  submat_rcpp(X, T) 5.831 6.3690 6.7465 7.3825 20.876
4        X[T == 1, ] 3.411 3.9380 4.1475 4.5345 27.981

n(rows)=10000, p(T==1)=0.3

                expr     min       lq   median       uq      max
1  submat_arma(X, T) 107.070 113.4000 125.5455 141.3700 1468.539
2 submat_arma2(X, T)  76.179  80.4295  88.2890 100.7525 1153.810
3  submat_rcpp(X, T) 244.242 247.3120 276.6385 309.2710 1934.126
4        X[T == 1, ] 229.884 236.1445 263.5240 289.2370 1876.980

submat.cpp

#include <RcppArmadillo.h>
// [[Rcpp::depends(RcppArmadillo)]]

using namespace Rcpp;
using namespace arma;

// arma in; arma out
// [[Rcpp::export]]
mat submat_arma(arma::mat X, arma::colvec T) {
    mat y = X.rows(find(T == 1));
    return y;
}

// rcpp in; arma out
// [[Rcpp::export]]
mat submat_arma2(NumericMatrix X, NumericVector T) {
    mat Xmat(X.begin(), X.nrow(), X.ncol(), false);
    colvec tIdx(T.begin(), T.size(), false); 
    mat y = Xmat.rows(find(tIdx == 1));
    return y;
}

// rcpp in; rcpp out
// [[Rcpp::export]]
NumericMatrix submat_rcpp(NumericMatrix X, LogicalVector condition) { 
    int n=X.nrow(), k=X.ncol();
    NumericMatrix out(sum(condition),k);
    for (int i = 0, j = 0; i < n; i++) {
        if(condition[i]) {
            out(j,_) = X(i,_);
            j = j+1;
        }
    }
    return(out);
}


/*** R
library("microbenchmark")

# simulate data
n=100
p=0.3
T=rbinom(n,1,p)
X=as.matrix(cbind(rnorm(n),rnorm(n)))

# compare output
identical(X[T==1,],submat_arma(X,T))
identical(X[T==1,],submat_arma2(X,T))
identical(X[T==1,],submat_rcpp(X,T))

# benchmark
microbenchmark(X[T==1,],submat_arma(X,T),submat_arma2(X,T),submat_rcpp(X,T),times=500)

# increase n
n=10000
p=0.3
T=rbinom(n,1,p)
X=as.matrix(cbind(rnorm(n),rnorm(n)))
# benchmark
microbenchmark(X[T==1,],submat_arma(X,T),submat_arma2(X,T),submat_rcpp(X,T),times=500)

*/

关于c++ - 匹配逻辑语句的 Rcpp 矩阵的子集,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13038256/

相关文章:

c++ - C++ 和 MQ 的网络硬件优先级

c++ - C++ vector 使用错误 : No matching member function for call to 'push_back'

r - R中如何求某列的最小值?

r - 选择第一个正面事件

r - 如何从 R 中的 4 个单独的音频文件中创建一个 4 channel 的音频文件?

c++ - 将 rcpp 变量转换为标准 C++ 变量

c++ - 更好的模仿?

c++ - 为什么在返回对象 Mat 时堆损坏?

rcpp - __result 未在此范围内声明

c++ - Rcpp:按照另一个 vector 的顺序重新排列一个 vector