R 进入C++:Rcpp - 组合示例

R into C++: Rcpp - Combinatorial example

本文关键字:组合 Rcpp 进入 C++      更新时间:2023-10-16

我有这个计算昂贵的例子。我想使用 Rcpp(c++)转换为编译代码。

# Data frame 5 columns / 20 rows
a<-data.frame(A=rnorm(20),B=rnorm(20),C=rnorm(20),D=rnorm(20))
# Combinations of 2 slots of the columns names
b<- t(combn(names(a),2))
# create a list where each element has the names of the columns combination as a vector
c<-lapply(1:nrow(b),function(y) {as.vector(b[y,])})
# Resulting new data.frame where each column is the mean of the columns in the original data frame
# that are a particular combination
d<-as.data.frame(do.call(cbind,lapply(1:length(c),function(x) {apply(a[,unlist(c[x])],1,mean)})))

关于如何做到这一点的任何建议。我发现当集合中的元素数量 (N) 和子集的数量 (K) 发生变化时,C++预先设置矩阵真的很复杂。

感谢您的任何建议!

重复到CC++应该是加速代码的最后一个资源。我想一个好的做法是尝试在 R 中做得更好。从R的角度来看,您的代码效率非常低,我建议以下方法可以加快速度。注意:几乎可以肯定的是,C(++)解决方案仍然(要快得多),但也许您会对此感到满意。尝试:

#you can obtain the `c` object of your example simply like this.
c<-combn(names(a),2,simplify=FALSE)
res<-vapply(c,function(x) rowMeans(a[x]),numeric(nrow(a)))

你最终会得到一个matrix,你可以强迫一个data.frame来获得d。另请注意,如果每一列都numeric,则应将结果保留为 matrix 。 如果每列可以是不同的类型,则应使用data.frame。一些基准:

set.seed(1)
a<-data.frame(A=rnorm(200000),B=rnorm(200000),C=rnorm(200000),D=rnorm(200000))
system.time(x<-do.call(cbind,lapply(1:length(c),function(x) {apply(a[,unlist(c[x])],1,mean)})))
# user  system elapsed 
#7.612   0.036   7.655  
system.time(x1<-vapply(c,function(x) rowMeans(a[x]),numeric(nrow(a))))
# user  system elapsed 
# 0.02    0.00    0.02
all.equal(x,x1)
#[1] TRUE

感谢@user20650提供非常优雅的解决方案:

combn(a, 2, simplify=T, rowMeans)

上面的内容比vapply的要慢一些,因为我想在矩阵中重新组织结果需要一点时间。