给定一个包含多列的data.frame,使用rcpp计算列中值的组合的最快方法是什么,而不仅仅是R以确保更好的性能?
例如,考虑以下data.frame,称为df,列为A,B,C,D,E
A B C D E
1 1 1 1 1 2
2 1 1 1 1 2
3 2 2 2 2 3
4 2 2 2 2 3
5 3 3 3 3 1
预期输出如下:
A B C D E count
1 1 1 1 1 2 2
2 2 2 2 2 3 2
3 3 3 3 3 1 1
在R中,可以通过创建一个新列来组合现有列并使用表来查找计数,即:
df$combine <- do.call(paste, c(df, sep = "-"))
tab <- as.data.frame(table(df$combine))
因为数据按摩的性能和R中的表命令有点慢,有没有人知道并且快速的方式在Rcpp中做同样的事情?
答案 0 :(得分:0)
好的,这是我能想到的一种方式。
首先,我们真的不能在Rcpp::DataFrame
中使用Rcpp
对象类型,因为它实际上是一个松散的向量列表。因此,我通过创建与采样数据匹配的Rcpp::NumericMatrix
来降低此问题的阈值。从这里开始,可以使用std::map
来计算唯一行。这是简化的,因为Rcpp::NumericMatrix
具有逐行启用.row()
属性。因此,每行都会转换为std::vector<T>
,用作地图的关键字。然后,我们将每个std::vector<T>
添加到std::map
并增加其计数值。最后,我们将std::map
导出为所需的矩阵格式。
#include <Rcpp.h>
// [[Rcpp::export]]
Rcpp::NumericMatrix unique_rows( Rcpp::NumericMatrix & v)
{
// Initialize a map
std::map<std::vector<double>, int> count_rows;
// Clear map
count_rows.clear();
// Count each element
for (int i = 0; i != v.nrow(); ++i) {
// Pop from R Matrix
Rcpp::NumericVector a = v.row(i);
// Convert R vector to STD vector
std::vector<double> b = Rcpp::as< std::vector<double> >(a);
// Add to map
count_rows[ b ] += 1;
}
// Make output matrix
Rcpp::NumericMatrix o(count_rows.size(), v.ncol()+1);
// Hold count iteration
unsigned int count = 0;
// Start at the 1st element and move to the last element in the map.
for( std::map<std::vector<double>,int>::iterator it = count_rows.begin();
it != count_rows.end(); ++it )
{
// Grab the key of the matrix
std::vector<double> temp_o = it->first;
// Tack on the vector, probably can be speed up.
temp_o.push_back(it->second);
// Convert from std::vector to Rcpp::NumericVector
Rcpp::NumericVector mm = Rcpp::wrap(temp_o);
// Store in a NumericMatrix
o.row(count) = mm;
count++;
}
return o;
}
然后我们选择:
a = matrix(c(1, 1, 1, 1, 2,
1, 1, 1, 1, 2,
2, 2, 2, 2, 3,
2, 2, 2, 2, 3,
3, 3, 3, 3, 1), ncol = 5, byrow = T)
unique_rows(a)
,并提供:
[,1] [,2] [,3] [,4] [,5] [,6]
[1,] 1 1 1 1 2 2
[2,] 2 2 2 2 3 2
[3,] 3 3 3 3 1 1