根据尺寸

时间:2017-04-13 14:03:12

标签: rcpp

Rcpp中是否有基本功能:

  1. 如果向量的大小为1,则完全由单个值填充。
  2. 如果长度相同,则完全填充另一个向量。
  3. 如果Vector的长度不同且矢量的大小为1,则填充NA值。
  4. 我使用NumericVector作为示例,将以上标准编写为下面的函数。如果在Rcpp中没有执行所述操作的基本函数,那么应该有一种模板函数的方法,以便给定任何类型的向量(例如numericcharacter等)以上逻辑将能够被执行。

    // [[Rcpp::export]]
    NumericVector cppvectorize(NumericVector x,NumericVector y) {
    
      NumericVector y_out(y.size());
    
      if(x.size() == 1) {
        for(int i = 0; i < y_out.size(); i++) {
          y_out[i] = x[0];
        }
      } else if(x.size() == y_out.size()) {
        for(int i = 0; i < y_out.size(); i++) {
          y_out[i] = x[i];
        }
      } else {
        for(int i = 0; i < y_out.size(); i++) {
          y_out[i] = NA_REAL;
        }
      }
    
      return y_out;
    } 
    

1 个答案:

答案 0 :(得分:2)

不幸的是,你最接近这种功能的是Rcpp支持的rep变种之一。但是,没有一种变体符合所需的输出。因此,唯一的选择是真正实现所需功能的模板化版本。

要创建模板化函数,我们将首先创建一个处理SEXP objects调度的路由函数。路由功能背后的基本原理是SEXP objects能够使用Rcpp属性从 R 中检索并映射到 R ,而模板化版本不是。因此,我们需要指定可能的SEXTYPE (used as RTYPE)个调度。 TYPEOF()宏检索编码的数字。使用switch语句,我们可以将此号码发送到适当的案例中。

调度后,我们到达模板化函数。模板化函数使用Rcpp的基类Vector类来简化数据流。从这里开始,显着的新颖性是使用::traits::get_na<RTYPE>()动态检索适当的NA值并填充它。

有了这个计划,让我们来看看代码:

#include <Rcpp.h>
using namespace Rcpp;

// ---- Templated Function

template <int RTYPE>
Vector<RTYPE> vec_helper(const Vector<RTYPE>& x, const Vector<RTYPE>& y) {
  Vector<RTYPE> y_out(y.size());

  if(x.size() == 1){
    y_out.fill(x[0]);
  } else if (x.size() == y.size()) {
    y_out = x;
  } else {
    y_out.fill(::traits::get_na<RTYPE>());
  }

  return y_out;
} 

// ---- Dispatch function

// [[Rcpp::export]]
SEXP cppvectorize(SEXP x, SEXP y) {
  switch (TYPEOF(x)) {
  case INTSXP: return vec_helper<INTSXP>(x, y);
  case REALSXP: return vec_helper<REALSXP>(x, y);
  case STRSXP: return vec_helper<STRSXP>(x, y);
  default: Rcpp::stop("SEXP Type Not Supported."); 
  }
  // Need to return a value even though this will never be triggered
  // to quiet the compiler.
  return R_NilValue;
}

样本测试

这里我们对每个支持的数据进行一些样本测试

# Case 1: x == 1

x = 1:5
y = 2

cppvectorize(x, y)
## [1] NA

# Case 2: x == y

x = letters[1:5]
y = letters[6:10]

cppvectorize(x, y)
## [1] "a" "b" "c" "d" "e"

# Case 3: x != y && x > 1

x = 1.5
y = 2.5:6.5

cppvectorize(x, y)

## [1] 1.5 1.5 1.5 1.5 1.5