R 到 C++:Rcpp - 组合示例

R into C++: Rcpp - Combinatorial example

我有这个计算量大的例子。我想使用 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,则应将结果保持为 matrixdata.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 慢一点,因为我猜它需要一点时间来重新组织矩阵中的结果。