由于我不理解的原因,我的Rcpp代码偶尔会失败(SEGFAULT等)。代码创建一个大型data.frame,然后通过调用R子集函数[.data.frame
)尝试从创建帧的相同方法中获取此data.frame的子集。它的简化版本如下所示:
library(Rcpp)
src <- '// R function to subset data.frame - what will be called to subset
DataFrame test() {
Function subsetinR("[.data.frame");
// Make a dataframe in Rcpp to subset
size_t n = 100;
auto df = DataFrame::create(Named("a") = std::vector<double> (n, 2.0),
Named("b") = std::vector<double> (n, 4.0));
// Now make a vector to subset with
LogicalVector filter = LogicalVector::create(n, TRUE);
for (size_t i =0; i < n; i++) {
if (i % 2 == 0) filter[i] = FALSE;
}
// Subset, here is where it fails!
df = subsetinR(df, filter, R_MissingArg);
return df;
}'
fun <- cppFunction(plugins=c("cpp11"), src, verbose = TRUE, depends="Rcpp")
fun()
然而,虽然这种情况偶尔会起作用,但有时它会因以下错误而失败:
*** caught segfault ***
address 0x7ff700000030, cause 'memory not mapped'`
任何人都知道出了什么问题?
注意:这不是重复。我已经看到了其他堆栈溢出答案,它通过利用每个向量上的子集来创建向量,例如
// Next up, create a new DataFrame Object with selected rows subset.
return Rcpp::DataFrame::create(Rcpp::Named("val1") = val1[idx],
Rcpp::Named("val2") = val2[idx],
Rcpp::Named("val3") = val3[idx],
Rcpp::Named("val3") = val4[idx]
);
但是,我明确地希望避免重复的[idx]
子集化,因为在构造data.frame时不知道idx(它只在结尾处知道),并且我希望找到一个不涉及反复调用的方式。如果可以在最后一次转换data.frame,那就可以了。
答案 0 :(得分:2)
这里的问题是LogicalVector::create()
没有按照您的期望进行操作 - 它返回长度为2的向量,其元素为TRUE
和TRUE
。换句话说,你的代码:
LogicalVector filter = LogicalVector :: create(n,TRUE);
不生成长度为n
且值为TRUE
的逻辑向量,而是生成长度为2的逻辑向量,第一个元素为“truthy”,因此TRUE
,第二个明确TRUE
。
您可能只想使用常规构造函数,例如LogicalVector(n, TRUE)
。