Почему мой код генерирует ошибку: ожидается одно значение: [экстент = 3]? - PullRequest
0 голосов
/ 03 июля 2018

Я учусь знакомиться с пакетом Rcpp, и у меня есть фрейм данных R df со столбцами списка, сгенерированными в два этапа:

df<- data.frame(w= 1:3, x=3:5, y=6:8, z = I(list(1:2, 1:3, 1:4)))

df <- as.data.frame(do.call(cbind, lapply(df[1:3], function(x) Map("*", 
         df$z, x))))

>df
           w                x                  y
        1, 2             3, 6              6, 12
     2, 4, 6         4, 8, 12          7, 14, 21
 3, 6, 9, 12    5, 10, 15, 20      8, 16, 24, 32

Я работаю с набором данных из почти 2 миллионов строк. Чтобы сэкономить много времени для удаления, я хочу получить прямой доступ к фрейму данных и выполнить следующую операцию непосредственно с расположением Rcpp, чтобы сгенерировать фрейм данных df1 .

df1 <- as.data.frame (4*sin(df*pi))

Основываясь на информации с этого сайта, я структурировал свой код, который, как я ожидал, смог бы работать, следующим образом:

library(Rcpp)

cppFunction('NumericVector transfo(Rcpp::DataFrame x) {
    int nrow = x.nrow(), ncol = x.ncol();
    NumericVector out(nrow*ncol);
    int pi;
    int vol = 4;

    for (int j = 0; j < ncol; j++) {
        for (int i = 0; i < nrow; i++) {
            out[i, j] = sin(x[i,j]*pi)*vol;
            } 
        }
        return out;
    }')

Но с transfo(df): Я получаю ошибку:

Expecting a single value: [extent=3].

Буду благодарен за любые подсказки о том, откуда возникла моя ошибка.

1 Ответ

0 голосов
/ 04 июля 2018

Ваша структура данных очень необычная, и я не уверен, что вы получите много ускорения от использования C ++ здесь. Но вы можете использовать что-то вроде этого:

#include <Rcpp.h>
using namespace Rcpp;

// [[Rcpp::export]]
DataFrame df_sin(DataFrame df) {
  R_xlen_t nCols = df.cols();
  R_xlen_t nRows = df.rows();
  List result(nCols * nRows);
  result.attr("dim") = Dimension(nRows, nCols);
  colnames(result) = as<CharacterVector>(df.names());

  for (R_xlen_t i = 0; i < nCols; ++i) {
    List column = as<List>(df[i]);
    for (R_xlen_t j = 0; j < nRows; ++j) {
      NumericVector tmp = as<NumericVector>(column[j]);
      result[i * nCols + j] = 4 * sin(tmp * M_PI);
    }
  }
  DataFrame df1(result);
  return df1;
}

/*** R
df <- data.frame(w= 1:3, x=3:5, y=6:8, z = I(list(1:2, 1:3, 1:4)))
df <- as.data.frame(do.call(cbind, lapply(df[1:3], 
                                          function(x) Map("*", df$z, x))))
df_sin(df)
*/

Обратите внимание, что я переключился с исходного кода в качестве строкового аргумента на Rcpp::cppFunction() в отдельный .cpp файл. Такой файл может быть легко отредактирован в любом редакторе, который знает о C ++, который включает в себя RStudio. В RStudio вы можете получить исходный файл (Ctrl-Shift-Return или кнопку источника), который скомпилирует и свяжет код. Кроме того, код R в специальном комментарии R в конце будет выполнен. Это удобно, если вам нужен только небольшой код R вместе с кодом C ++. Если код C ++ является частью большей базы кода R, то вы можете вызвать Rcpp::sourceCpp(<cppFile>) в коде R. Это снова скомпилирует и свяжет код, а также сделает экспортированные функции доступными в R. В этом случае, вероятно, легче удалить специальный комментарий R в конце, так как он выполняется при каждом вызове sourceCpp.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...