繁体   English   中英

在 Rcpp 中检查向量的 Null 和 NA

[英]Checking Null and NA of a vector in Rcpp

我正在尝试以第二个可为空向量 ( r ) 的值是否为NA为条件来评估向量 ( y ) 的总和。 如果第二个向量r为 NULL,则应将y所有值相加。 如果r所有元素都是NA ,则函数应返回 NA。 请参阅文本末尾以获得所需的输出。

我首先尝试了以下代码:

library(Rcpp)
cppFunction('double foo(NumericVector y, Rcpp::Nullable<Rcpp::IntegerVector> r = R_NilValue) {
  double output = 0;
  bool return_na = !Rf_isNull(r);
  int y_count = y.size();
  for (int i = 0; i < y_count; i++) {
    if (Rf_isNull(r)  || !R_IsNA(r[i])) {
    //// if (Rf_isNull(r)  || !R_IsNA(as<IntegerVector>(r)[i])) {
      if (!Rf_isNull(r))
        Rcout << R_IsNA(as<IntegerVector>(r)[i]) << " - "<< as<IntegerVector>(r)[i] << std::endl;
      output = output + y[i];
      return_na = false;
    } 
  }
  if (return_na) 
    return NA_REAL;
  return output;
}')

这给了我以下错误:

 error: invalid use of incomplete type 'struct SEXPREC'
     if (Rf_isNull(r)  || !R_IsNA(r[i])) {
                                     ^

为了解决它,我使用if (Rf_isNull(r) || !R_IsNA(as<IntegerVector>(r)[i])) {代替。 但是这一次,当转换为整数向量时, NA值被转换为数字并且R_IsNA()测试给出了误报。

这是我想要的预期输出。

foo(1:4, NULL) #  <- This should return 10 = 1 + 2 + 3 + 4
foo(1:4, c(1, 1, 1, 1)) #  <- This should return 10 = 1 + 2 + 3 + 4
foo(1:4, c(1, 1, NA, 1)) #  <- This should return 7 = 1 + 2 + 4
foo(1:4, c(NA, NA, NA, NA)) # <- This should return NA

我怎样才能得到我想要的功能? (这个例子是简化的,我对 sum 函数不是特别感兴趣。相反,我对同时检查NANULL感兴趣,如示例中给出的那样。)

三点建议:

  • 使用 Rcpp 而不是 R 的 C API。
  • rNULL时提前返回。
  • 在循环输入向量之前创建一个LogicalVector
#include <Rcpp.h>

// [[Rcpp::export]]
double foo(Rcpp::NumericVector y, Rcpp::Nullable<Rcpp::IntegerVector> r = R_NilValue) {
    if (r.isNull())
        return Rcpp::sum(y);

    Rcpp::LogicalVector mask = Rcpp::is_na(r.as());
    if (Rcpp::is_true(Rcpp::all(mask))) 
        return NA_REAL;

    double output = 0.0;
    int y_count = y.size();
    for (int i = 0; i < y_count; ++i) {
        if (!mask[i]) {
            output += y[i];
        } 
    }
    return output;
}

/***R
foo(1:4, NULL) #  <- This should return 10 = 1 + 2 + 3 + 4
foo(1:4, c(1, 1, 1, 1)) #  <- This should return 10 = 1 + 2 + 3 + 4
foo(1:4, c(1, 1, NA, 1)) #  <- This should return 7 = 1 + 2 + 4
foo(1:4, c(NA, NA, NA, NA)) # <- This should return NA
*/ 

结果:

> Rcpp::sourceCpp('60569482.cpp')

> foo(1:4, NULL) #  <- This should return 10 = 1 + 2 + 3 + 4
[1] 10

> foo(1:4, c(1, 1, 1, 1)) #  <- This should return 10 = 1 + 2 + 3 + 4
[1] 10

> foo(1:4, c(1, 1, NA, 1)) #  <- This should return 7 = 1 + 2 + 4
[1] 7

> foo(1:4, c(NA, NA, NA, NA)) # <- This should return NA
[1] NA

进一步建议:

  • 使用掩码进行子设置y
#include <Rcpp.h>

// [[Rcpp::export]]
double foo(Rcpp::NumericVector y, Rcpp::Nullable<Rcpp::IntegerVector> r = R_NilValue) {
    if (r.isNull())
        return Rcpp::sum(y);

    Rcpp::LogicalVector mask = Rcpp::is_na(r.as());
    if (Rcpp::is_true(Rcpp::all(mask))) 
        return NA_REAL;

    Rcpp::NumericVector tmp = y[!mask];
    return Rcpp::sum(tmp);
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM