我正在学习熟悉Rcpp软件包,并且我有一个R数据框 df ,其中的列表列分两步生成:
df<- data.frame(w= 1:3, x=3:5, y=6:8, z = I(list(1:2, 1:3, 1:4)))
df <- as.data.frame(do.call(cbind, lapply(df[1:3], function(x) Map("*",
df$z, x))))
>df
w x y
1, 2 3, 6 6, 12
2, 4, 6 4, 8, 12 7, 14, 21
3, 6, 9, 12 5, 10, 15, 20 8, 16, 24, 32
我正在处理近200万行的数据集。为了节省长时间的嵌套时间,我想直接访问数据框并使用Rcpp处置直接执行以下操作,以生成数据框 df1 。
df1 <- as.data.frame (4*sin(df*pi))
主要受此站点信息启发,我以下列方式构造了我希望能够运行的代码:
library(Rcpp)
cppFunction('NumericVector transfo(Rcpp::DataFrame x) {
int nrow = x.nrow(), ncol = x.ncol();
NumericVector out(nrow*ncol);
int pi;
int vol = 4;
for (int j = 0; j < ncol; j++) {
for (int i = 0; i < nrow; i++) {
out[i, j] = sin(x[i,j]*pi)*vol;
}
}
return out;
}')
但是使用transfo(df)
:
我收到错误消息:
Expecting a single value: [extent=3].
对于任何有关我的错误来源的提示,我将不胜感激。
答案 0 :(得分:2)
您的数据结构非常不寻常,我不确定您在这里使用C ++会得到很多支持。但是您可以使用类似这样的东西:
#include <Rcpp.h>
using namespace Rcpp;
// [[Rcpp::export]]
DataFrame df_sin(DataFrame df) {
R_xlen_t nCols = df.cols();
R_xlen_t nRows = df.rows();
List result(nCols * nRows);
result.attr("dim") = Dimension(nRows, nCols);
colnames(result) = as<CharacterVector>(df.names());
for (R_xlen_t i = 0; i < nCols; ++i) {
List column = as<List>(df[i]);
for (R_xlen_t j = 0; j < nRows; ++j) {
NumericVector tmp = as<NumericVector>(column[j]);
result[i * nCols + j] = 4 * sin(tmp * M_PI);
}
}
DataFrame df1(result);
return df1;
}
/*** R
df <- data.frame(w= 1:3, x=3:5, y=6:8, z = I(list(1:2, 1:3, 1:4)))
df <- as.data.frame(do.call(cbind, lapply(df[1:3],
function(x) Map("*", df$z, x))))
df_sin(df)
*/
请注意,我已经从源代码作为字符串参数切换到Rcpp::cppFunction()
到单独的.cpp
文件。可以在任何了解C ++的编辑器(包括RStudio)中方便地编辑此类文件。然后,在RStudio中,您可以源文件(Ctrl-Shift-Return或源按钮),该文件将编译并链接代码。此外,最后将执行特殊R注释内的R代码。如果您只需要一点R代码和C ++代码,这将很方便。如果C ++代码是较大的R代码库的一部分,则可以在R代码中调用Rcpp::sourceCpp(<cppFile>)
。这将再次编译和链接代码,并使导出的函数在R中可用。在那种情况下,最后删除特殊的R注释可能更容易,因为在每次调用sourceCpp
时都会执行该注释。 。