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++ 中预先设置矩阵非常复杂。
感谢任何建议!
循环到C
或C++
应该是最后一个加速代码的资源了。我想一个很好的做法是尝试在 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
慢一点,因为我猜它需要一点时间来重新组织矩阵中的结果。
我有这个计算量大的例子。我想使用 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++ 中预先设置矩阵非常复杂。
感谢任何建议!
循环到C
或C++
应该是最后一个加速代码的资源了。我想一个很好的做法是尝试在 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
慢一点,因为我猜它需要一点时间来重新组织矩阵中的结果。