创建模板函数以根据大小用另一个向量填充向量 [英] Creating a Templated Function to Fill a Vector with another depending on Size
问题描述
Rcpp 中是否有一个基本函数:
Is there a base function in Rcpp that:
- 如果向量的大小为 1,则完全填充单个值.
- 如果长度相同,则完全填充另一个向量.
- 如果向量的长度和向量的大小都不相同,则用
NA
值填充.
我已使用 NumericVector
作为示例将上述条件编写为下面的函数.如果 Rcpp 中没有执行上述操作的基本函数,则应该有一种方法来模板化该函数,以便给定任何类型的向量(例如 numeric
、character
和等等)上面的逻辑就可以执行了.
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屋!