Переработка векторов с помощью Rcpp - PullRequest
0 голосов
/ 28 марта 2019

Я пытаюсь заставить векторную переработку работать в Rcpp.

> recycle_and_add <- Rcpp::cppFunction("
+ NumericVector recycle_and_add(NumericVector x, NumericVector y) {
+     return x + y;
+ }")
> recycle_and_add(42, 1:5)
[1] 43

Я ожидаю, что он вернет что-то вроде

> 42 + 1:5
[1] 43 44 45 46 47

После некоторого анализа я обнаружил, что x.size() - это 1, а y.size() - это 5 в функции Rcpp, поэтому очевидно, что рециркуляция векторов не работает "из коробки".

Хотя я могу вручную найти самый длинный из x и y и перезапустить более короткий, в реальном приложении есть 3 или 4 аргумента, требующих переработки, поэтому я могу представить, что ручное развертывание приведет к множеству переменных указывая на разные векторы и превратить код в кучу спагетти.

Имеет ли Rcpp встроенную поддержку для переработки векторов, например, с небольшим количеством сахара?

1 Ответ

4 голосов
/ 28 марта 2019

В стратегическом плане почти всегда проще переработать R и затем перейти на C ++ .

Если это , необходимо сделатьв C ++ , тогда должен работать следующий шаблон проектирования:

#include <Rcpp.h>

// [[Rcpp::export]]
Rcpp::NumericVector recycle_vector(Rcpp::NumericVector x, 
                             Rcpp::NumericVector y) {

    // Obtain vector sizes
    int n_x = x.size();
    int n_y = y.size(); 

    // Check both vectors have elements
    if(n_x <= 0 || n_y <= 0) {
        Rcpp::stop("Both `x` and `y` vectors must have at least 1 element.");
    }

    // Compare the three cases that lead to recycling... 
    if(n_x == n_y) {
        return x + y;
    } else if (n_x > n_y) {
        return Rcpp::rep_len(y, n_x) + x;
    }

    return Rcpp::rep_len(x, n_y) + y; 
}

Тестовые случаи:

recycle_vector(1:3, 1:3)
# [1] 2 4 6
recycle_vector(4, 1:3)
# [1] 5 6 7
recycle_vector(10:12, -2:-1)
# [1] 8 10 10
...