我正在寻找 C++/Rcpp/Eigen 或 Armadillo 中 R 函数 rowsum
的快速替代方案。
目的是根据一个分组 vector b
得到一个 vector a
中的元素之和。例如:
> a
[1] 2 2 2 2 2 2 2 2 2 2
> b
[1] 1 1 1 1 1 2 2 2 2 2
> rowsum(a,b)
[,1]
1 10
2 10
在 Rcpp
中编写一个简单的 for 循环非常慢,但也许我的代码效率低下。
我也尝试在 Rcpp
中调用函数 rowsum
,但是,rowsum
不是很快。
为了补充 Martin 的代码,这里有一些基于 Rcpp
的版本。
int increment_maybe(int value, double vec_i){
return vec_i == 0 ? value : ( value +1 ) ;
}
// [[Rcpp::export]]
NumericVector cpprowsum2(NumericVector x, IntegerVector f){
std::vector<double> vec(10) ;
vec.reserve(1000);
int n=x.size();
for( int i=0; i<n; i++){
int index=f[i];
while( index >= vec.size() ){
vec.resize( vec.size() * 2 ) ;
}
vec[ index ] += x[i] ;
}
// count the number of non zeros
int s = std::accumulate( vec.begin(), vec.end(), 0, increment_maybe) ;
NumericVector result(s) ;
CharacterVector names(s) ;
std::vector<double>::iterator it = vec.begin() ;
for( int i=0, j=0 ; j<s; j++ ,++it, ++i ){
// move until the next non zero value
while( ! *it ){ i++ ; ++it ;}
result[j] = *it ;
names[j] = i ;
}
result.attr( "dim" ) = IntegerVector::create(s, 1) ;
result.attr( "dimnames" ) = List::create(names, R_NilValue) ;
return result ;
}
C++ 代码处理一切,包括格式化为 rowsum
给出的矩阵格式,并显示出(稍微)更好的性能(至少在示例中)。
# from Martin's answer
> system.time(r1 <- rowsum1(x, f))
user system elapsed
0.014 0.001 0.015
> system.time(r3 <- cpprowsum2(x, f))
user system elapsed
0.011 0.001 0.013
> identical(r1, r3)
[1] TRUE