在RCpp中移除NumericVector中的NA值

3

我是一个Rcpp的新手(也是C++的新手)。我写了一段代码,使用这里的示例代码https://gist.github.com/kevinushey/4561281计算矩阵的行/列最大值和最小值:

#include <Rcpp.h>
using namespace Rcpp;

template <class T>
inline double do_max(T& x) {
  return max(x);
}

template <class T>
inline double do_min(T& x) {
  return min(x);
}

NumericVector colMaxsCpp(NumericMatrix& x) {
  int nRows = x.nrow();
  NumericVector out = no_init(nRows);

  for (int i=0; i<nRows;i++) {
    NumericMatrix::Row tmp = x(i,_);
    out[i]=do_max(tmp);
  }

  return out;
}

NumericVector colMinsCpp(NumericMatrix& x) {
  int nRows = x.nrow();
  NumericVector out = no_init(nRows);

  for (int i=0; i<nRows;i++) {
    NumericMatrix::Row tmp = x(i,_);
    out[i]=do_min(tmp);
  }

  return out;
}

NumericVector rowMaxsCpp(NumericMatrix& x) {
  int nCols = x.ncol();
  NumericVector out = no_init(nCols);

  for (int i=0; i<nCols;i++) {
    NumericMatrix::Column tmp = x(_,i);
    out[i]=do_max(tmp);
  }

  return out;
}

NumericVector rowMinsCpp(NumericMatrix& x) {
  int nCols = x.ncol();
  NumericVector out = no_init(nCols);

  for (int i=0; i<nCols;i++) {
    NumericMatrix::Column tmp = x(_,i);
    out[i]=do_min(tmp);
  }

  return out;
}

// [[Rcpp::export]]
NumericVector Max(NumericMatrix x, int dim) {
  if (dim==1) {
    return rowMaxsCpp(x);
  } else if (dim==2) {
    return colMaxsCpp(x);
  }
}

// [[Rcpp::export]]
NumericVector Min(NumericMatrix x, int dim) {
  if (dim==1) {
    return rowMinsCpp(x);
  } else if (dim==2) {
    return colMinsCpp(x);
  }
}

我希望修改代码,使do_mindo_max函数能够处理NA。这些函数使用一个类的模板。

我在网上看到了NA_REALNA_INTEGER,但它们是特定于类的。

(a) 是否有适用于类的通用NA可用(例如上面的示例)?

(b) 另外,是否有可用的函数,可以将变量x子集化为仅使用非NA元素,例如在R中等同于max(x[!is.na(x)])min(x[!is.na(x)])

(c) 最后,上面的代码已经被编写为处理数字matrix,但似乎即使输入一个整数matrix也能正常工作(尽管输出被转换为numeric)。这是为什么?


3
有一个名为 na_omit 的函数可以删除数据中的空值。 - Roland
@Roland,非常好,谢谢。我尝试用max(na_omit(x))替换max(x),但它没有编译通过。您能告诉我如何使用max(x)吗? - uday
你使用的是哪个版本的Rcpp?如果我这样做,你的代码可以编译通过。 - Roland
@Roland,使用Rcpp 0.11.1。实际上,代码已经编译了,但是出现了像“第70行控制到达非void函数结尾”的错误。 - uday
1
在足够的警告级别下,g++会发出这种警告是正常的。您需要插入一个无条件返回,例如 NumericVector NeverReached(1); return NeverReached; 来抑制它。 - Dirk Eddelbuettel
@DirkEddelbuettel,谢谢。现在它可以正常工作了,没有两个警告。我可能已经找到了原因——else if语句需要一个最终的else语句。 - uday
1个回答

4

简短回答:

a) 是的,但我不确定它们是否进行了向量化处理。但是添加了一些模板化的NA traits。

b) 是的,例如在

R> cppFunction('double mymax(NumericVector x) { \
                   IntegerVector x2 = wrap(na_omit(x)); \
                   return max(x2);}')
R> mymax(c(1L, 2L, NA, 4L))
[1] 4
R> 

c) 整数类型总是会被转换为数字类型,这会带来一次复制的开销。

@Roland 已经提到了 na_omit。在 b) 中,我需要通过一个 wrap() 来生成一个中间的 SEXP 对象。


2
我可以编译并使用cppFunction('double mymax(NumericVector x){return max(na_omit(x));} '),没有任何问题。 - Roland
@Roland,实际上是我的错,代码确实编译了,但是它给了我两个警告。Dirk在他的评论中给了我警告的答案。 - uday

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接