创建模板函数以根据大小用另一个向量填充向量 [英] Creating a Templated Function to Fill a Vector with another depending on Size

查看:39
本文介绍了创建模板函数以根据大小用另一个向量填充向量的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

Rcpp 中是否有一个基本函数:

Is there a base function in Rcpp that:

  1. 如果向量的大小为 1,则完全填充单个值.
  2. 如果长度相同,则完全填充另一个向量.
  3. 如果向量的长度和向量的大小都不相同,则用 NA 值填充.

我已使用 NumericVector 作为示例将上述条件编写为下面的函数.如果 Rcpp 中没有执行上述操作的基本函数,则应该有一种方法来模板化该函数,以便给定任何类型的向量(例如 numericcharacter 和等等)上面的逻辑就可以执行了.

I've written the above criteria as a function below using a NumericVector as an example. If there isn't a base function in Rcpp that performs said operations there should be a way to template the function so that given any type of vector (e.g. numeric, character and so on) the above logic would be able to be executed.

// [[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;
} 

推荐答案

不幸的是,您最接近这样的函数是 Rcpp 支持的 rep 变体之一.但是,没有一个变体与所需的输出相匹配.因此,唯一的选择是真正实现所需函数的模板化版本.

Unfortunately, the closest you will come to such a function is one of the rep variants that Rcpp supports. However, none of the variants match the desired output. Therefore, the only option is to really implement a templated version of your desired function.

要创建模板化函数,我们将首先创建一个路由函数来处理 SEXP 对象.路由功能背后的基本原理是 SEXP 对象 可以使用 Rcpp 属性从 R 中检索并显示到 R 中,而模板化版本不是.因此,我们需要指定 SEXTYPE(用作 RTYPE) 可能的调度.TYPEOF() 宏检索编码号码.使用 switch 语句,我们可以将这个数字分配到适当的案例中.

To create the templated function, we will first create a routing function that handles the dispatch of SEXP objects. The rationale behind the routing function is SEXP objects are able to be retrieved from and surfaced into R using Rcpp Attributes whereas a templated version is not. As a result, we need to specify the SEXTYPE (used as RTYPE) dispatches that are possible. The TYPEOF() macro retrieves the coded number. Using a switch statement, we can dispatch this number into the appropriate cases.

调度后,我们到达模板化函数.模板化函数利用 Rcpp 的基本 Vector 类来简化数据流.从这里开始,值得注意的新颖之处将是使用 ::traits::get_na() 来动态检索适当的 NA 值并填充它.

After dispatching, we arrive at the templated function. The templated function makes use of the base Vector class of Rcpp to simplify the data flow. From here, the notable novelty will be the use of ::traits::get_na<RTYPE>() to dynamically retrieve the appropriate NA value and fill it.

有了计划,让我们看一下代码:

With the plan in place, let's look at the code:

#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;
}

<小时>

示例测试

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


Sample Tests

Here we conduct a few sample tests on each of the supported data

# 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

这篇关于创建模板函数以根据大小用另一个向量填充向量的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆