如何在 bigmemory rcpp 中修改文件支持矩阵的值
how to modify values of a file-backed matrix in bigmemory rcpp
我正在使用 R bigmemory 包和 Rcpp 来处理大矩阵(1 到 1000 万列 x 1000 行)。一旦我将包含 0、2 和 NA 的整数矩阵读入 R 中的文件支持的大内存矩阵,我想通过 C++ 修改所有 NA 值,以便对每列的平均值或任意值进行插补(我在这里显示后者)。
下面是我编写的Rcpp 函数,但它不起作用。我希望从 R 中调用 BigNA(mybigmatrix@address)
可以找到矩阵中的 NA 元素并直接在支持文件中修改它的值。
我认为问题可能出在 std::isnan(mat[j][i])
的评估中。我通过创建一个替代函数来检查这一点,该函数使用累加器计算 NA 值并且确实没有计算任何 NA。但是一旦解决了这个问题,我也不确定表达式 mat[j][i] = 1
是否会修改支持文件中的值。对于具有 R 背景的我来说,编写这些语句感觉很直观,但可能是错误的。
任何 help/suggestion 将不胜感激。
#include <stdio.h>
#include <Rcpp.h>
#include <bigmemory/MatrixAccessor.hpp>
#include <numeric>
// [[Rcpp::depends(BH, bigmemory)]]
// [[Rcpp::depends(Rcpp)]]
// [[Rcpp::export]]
void BigNA(SEXP pBigMat) {
/*
* Imputation of "NA" values for "1" in a big 0, 2 NA matrix.
*/
// Create the external bigmatrix pointer and iniciate matrix accessor
XPtr<BigMatrix> xpMat(pBigMat);
MatrixAccessor<int> mat = (*xpMat);
// Iterater over the elements in a matrix and when NA is found, substitute for "1"
for(int i=0; i< xpMat->ncol(); i++){
for(int j=0; j< xpMat->nrow(); j++){
if(std::isnan(mat[j][i])){
mat[j][i] = 1;
}
}
}
}
问题源于R中的NA
和C++中的NAN
之间的差异。
MatrixAccessor<int>
为您提供 int
类型值的访问器。 R 中的任何数字都可以是 NA
,但 C++ 中的 int
永远不会是 NAN
。优化编译器可以完全忽略 std::isnan(x)
,其中 x
属于 int
类型,就像您的情况一样。
要解决此问题,您可以:
- 使用
MatrixAccessor<float>
(或double
)。这意味着实际存储不同的数据类型。
- 检查
NA
个元素实际获得的价值。我想你会发现它在 C++ 中是 INT_MIN
(-2147483648)。将 isnan(x)
替换为 x == INT_MIN
.
相关:
软件包 bigmemory 有一些检查 NAs 的函数。
只需添加带有 #include <bigmemory/isna.hpp>
的页眉。
并将 std::isnan(mat[j][i])
替换为 isna(mat[j][i])
.
我正在使用 R bigmemory 包和 Rcpp 来处理大矩阵(1 到 1000 万列 x 1000 行)。一旦我将包含 0、2 和 NA 的整数矩阵读入 R 中的文件支持的大内存矩阵,我想通过 C++ 修改所有 NA 值,以便对每列的平均值或任意值进行插补(我在这里显示后者)。
下面是我编写的Rcpp 函数,但它不起作用。我希望从 R 中调用 BigNA(mybigmatrix@address)
可以找到矩阵中的 NA 元素并直接在支持文件中修改它的值。
我认为问题可能出在 std::isnan(mat[j][i])
的评估中。我通过创建一个替代函数来检查这一点,该函数使用累加器计算 NA 值并且确实没有计算任何 NA。但是一旦解决了这个问题,我也不确定表达式 mat[j][i] = 1
是否会修改支持文件中的值。对于具有 R 背景的我来说,编写这些语句感觉很直观,但可能是错误的。
任何 help/suggestion 将不胜感激。
#include <stdio.h>
#include <Rcpp.h>
#include <bigmemory/MatrixAccessor.hpp>
#include <numeric>
// [[Rcpp::depends(BH, bigmemory)]]
// [[Rcpp::depends(Rcpp)]]
// [[Rcpp::export]]
void BigNA(SEXP pBigMat) {
/*
* Imputation of "NA" values for "1" in a big 0, 2 NA matrix.
*/
// Create the external bigmatrix pointer and iniciate matrix accessor
XPtr<BigMatrix> xpMat(pBigMat);
MatrixAccessor<int> mat = (*xpMat);
// Iterater over the elements in a matrix and when NA is found, substitute for "1"
for(int i=0; i< xpMat->ncol(); i++){
for(int j=0; j< xpMat->nrow(); j++){
if(std::isnan(mat[j][i])){
mat[j][i] = 1;
}
}
}
}
问题源于R中的NA
和C++中的NAN
之间的差异。
MatrixAccessor<int>
为您提供 int
类型值的访问器。 R 中的任何数字都可以是 NA
,但 C++ 中的 int
永远不会是 NAN
。优化编译器可以完全忽略 std::isnan(x)
,其中 x
属于 int
类型,就像您的情况一样。
要解决此问题,您可以:
- 使用
MatrixAccessor<float>
(或double
)。这意味着实际存储不同的数据类型。 - 检查
NA
个元素实际获得的价值。我想你会发现它在 C++ 中是INT_MIN
(-2147483648)。将isnan(x)
替换为x == INT_MIN
.
相关:
软件包 bigmemory 有一些检查 NAs 的函数。
只需添加带有 #include <bigmemory/isna.hpp>
的页眉。
并将 std::isnan(mat[j][i])
替换为 isna(mat[j][i])
.