Rcpp - 从矩阵/数据帧列表中提取行
Rcpp - extracting rows from list of matrices / dataframes
作为这个问题的后续,我决定沿着 Rcpp 与 R 中复杂语法的路线走下去。我认为这将提供更好的可读性(也可能更快)。
假设我有一个data.frame
的列表(我可以通过as
轻松转换为矩阵)。考虑到先前的 answe -r -s,这似乎是最好的方法。
# input data
my_list <- vector("list", length= 10)
set.seed(65L)
for (i in 1:10) {
my_list[[i]] <- data.frame(matrix(rnorm(10000),ncol=10))
# alternatively
# my_list[[i]] <- matrix(rnorm(10000),ncol=10)
}
从矩阵中提取行的适当方法是什么?目标是创建一个列表,每个列表元素都包含一个列表,其中包含每个原始列表的 data.frame 的第 nr
行的列表。我尝试了几种不同的语法,但不断收到错误:
#include <Rcpp.h>
using namespace Rcpp;
using namespace std:
List foo(const List& my_list, const int& n_geo) {
int n_list = my_list.size();
std::vector<std::vector<double> > list2(n_geo);
// needed code....
return wrap(list2);
}
选项
for (int i = 0; i < n_list; i++) {
for (int nr = 0; nr < n_geo; nr++) {
list2[nr][i] = my_list[i].row(nr);
// or list2[nr].push_back(my_list[i].row(nr));
// or list2[nr].push_back(as<double>(my_list[i].row(nr)));
// or list2[nr].push_back(as<double>(my_list[i](nr, _)));
}
}
// or:
NumericMatrix a = my_list[1]
...
NumericMatrix j = my_list[10]
for (int nr = 0; nr < n_geo; nr++) {
list2[nr][1] = // as above
}
这些都不适合我。我做错了什么?以下是我从上述语法选择中收到的错误。
错误:调用 'as(Rcpp::Matrix<14>::Row)' 时没有匹配函数
或
错误:无法在赋值中将"Rcpp::Matrix<14>::Row {aka Rcpp::MatrixRow<14>}"转换为"double"
这里有一种方法可以做到这一点:
#include <Rcpp.h>
// x[[nx]][ny,] -> y[[ny]][[nx]]
// [[Rcpp::export]]
Rcpp::List Transform(Rcpp::List x) {
R_xlen_t nx = x.size(), ny = Rcpp::as<Rcpp::NumericMatrix>(x[0]).nrow();
Rcpp::List y(ny);
for (R_xlen_t iy = 0; iy < ny; iy++) {
Rcpp::List tmp(nx);
for (R_xlen_t ix = 0; ix < nx; ix++) {
Rcpp::NumericMatrix mtmp = Rcpp::as<Rcpp::NumericMatrix>(x[ix]);
tmp[ix] = mtmp.row(iy);
}
y[iy] = tmp;
}
return y;
}
/*** R
L1 <- lapply(1:10, function(x) {
matrix(rnorm(20), ncol = 5)
})
L2 <- lapply(1:nrow(L1[[1]]), function(x) {
lapply(L1, function(y) unlist(y[x,]))
})
all.equal(L2, Transform(L1))
#[1] TRUE
microbenchmark::microbenchmark(
"R" = lapply(1:nrow(L1[[1]]), function(x) {
lapply(L1, function(y) unlist(y[x,]))
}),
"Cpp" = Transform(L1),
times = 200L)
#Unit: microseconds
#expr min lq mean median uq max neval
# R 254.660 316.627 383.92739 347.547 392.7705 1909.097 200
#Cpp 18.314 26.007 71.58795 30.230 38.8650 945.167 200
*/
我不确定这将如何扩展;我认为这只是一种本质上效率低下的转型。根据我在源顶部的评论,您似乎只是在进行一种坐标交换——输入列表第 nx
个元素的第 ny
行成为输出列表第 ny
个元素的第nx
个元素:
x[[nx]][ny,] -> y[[ny]][[nx]]
为了解决您遇到的错误,Rcpp::List
是一个通用对象 - 技术上是一个Rcpp::Vector<VECSXP>
- 所以当你尝试这样做时,例如
my_list[i].row(nr)
编译器不知道my_list[i]
是一个NumericMatrix
。因此,您必须使用 Rcpp::as<>
进行显式强制转换,
Rcpp::NumericMatrix mtmp = Rcpp::as<Rcpp::NumericMatrix>(x[ix]);
tmp[ix] = mtmp.row(iy);
我只是在示例数据中使用matrix
元素来简化事情。在实践中,强制data.frame
直接在 R 中matrix
对象可能比尝试在 C++ 中执行此操作更好;它会简单得多,而且最有可能的是,强制只是调用底层 C 代码,所以尝试这样做实际上没有任何收获。
我还应该指出,如果您使用的是同质类型的Rcpp::List
,则可以使用 Rcpp::ListOf<type>
挤出更多的性能。这将允许您跳过上面完成的Rcpp::as<type>
转换:
typedef Rcpp::ListOf<Rcpp::NumericMatrix> MatList;
// [[Rcpp::export]]
Rcpp::List Transform2(MatList x) {
R_xlen_t nx = x.size(), ny = x[0].nrow();
Rcpp::List y(ny);
for (R_xlen_t iy = 0; iy < ny; iy++) {
Rcpp::List tmp(nx);
for (R_xlen_t ix = 0; ix < nx; ix++) {
tmp[ix] = x[ix].row(iy);
}
y[iy] = tmp;
}
return y;
}
/*** R
L1 <- lapply(1:10, function(x) {
matrix(rnorm(20000), ncol = 100)
})
L2 <- lapply(1:nrow(L1[[1]]), function(x) {
lapply(L1, function(y) unlist(y[x,]))
})
microbenchmark::microbenchmark(
"R" = lapply(1:nrow(L1[[1]]), function(x) {
lapply(L1, function(y) unlist(y[x,]))
}),
"Transform" = Transform(L1),
"Transform2" = Transform2(L1),
times = 200L)
#Unit: microseconds
# expr min lq mean median uq max neval
# R 6049.594 6318.822 7604.871 6707.242 8592.510 64005.190 200
# Transform 928.468 1041.936 3130.959 1166.819 1659.745 71552.284 200
#Transform2 850.912 957.918 1694.329 1061.183 2856.724 4502.065 200
*/
- Pybind11:将元组列表从Python传递到C++
- 从包含m行的文件中提取n行,必要时(惰性地)重复该文件
- 从链接列表c++中删除一个项目
- 从异构列表中提取数据
- 使用doxygen分别提取类的公共方法列表
- 如何在 C++ 中从链表中提取列表
- 提取头文件中的函数列表
- 是否可以提取 lambda 的捕获列表
- Rcpp - 从矩阵/数据帧列表中提取行
- 从 2d 坐标的列表(矢量)中提取上限和下边界
- 仅从decltype(someFunction)中提取参数类型列表
- 提取并转换 boost::p ython::list 的列表元素
- 如何使用QT RegExp从字符串中提取子字符串列表
- 从wab(mapi)中提取联系人和通讯组列表
- 尝试从文本文件中读取列表,然后搜索文本文件,并在c++中提取字符串
- 计算从文件中提取的列表中的和和平均值
- 如何从列表中提取某些值并将其放入另一个列表中
- c++ boost python列表提取导致分段错误
- 从初始值设定项列表中提取模板类型
- 从变长参数列表中提取std::string