Код R на C ++ для циклического перебора списка кадров данных (Rcpp)

Я не видел упоминания выше, но вы также увидите, что некоторые люди используют левый и правый сдвиг для арифметических операций. Левый сдвиг на x эквивалентен умножению на 2 ^ x (пока он не переполняется), а правый сдвиг эквивалентен делению на 2 ^ x.

Недавно я видел людей, использующих x & lt; 1 и x >> 1 для удвоения и сокращения пополам, хотя я не уверен, что они просто стараются быть умными или действительно есть отличное преимущество над нормальными операторами.

0
задан zeekster26 13 July 2018 в 14:48
поделиться

2 ответа

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

#include <Rcpp.h>

// [[Rcpp::export]]
Rcpp::List listDf(Rcpp::List l) {
  for (int i = 0; i < l.length(); ++i) {
    Rcpp::DataFrame df = Rcpp::as<Rcpp::DataFrame>(l[i]);
    for (int j = 0; j < df.cols(); ++j) {
      Rcpp::NumericVector col = df[j];
      df[j] = 1.23 * col;
    }
  }
  return l;
}

/*** R
set.seed(42)
df1 <- data.frame(a = sample(1:100, 3),
                  b = sample(1:100, 3),
                  c = sample(1:100, 3))

df2 <- data.frame(a = sample(1:100, 3),
                  b = sample(1:100, 3),
                  c = sample(1:100, 3))

l <- list(df1 = df1, df2 = df2)

listDf(l)

*/

И если вы действительно хотите добавьте 1/100 последнего столбца к другим столбцам, вы можете использовать:

#include <Rcpp.h>

// [[Rcpp::export]]
Rcpp::List listDf(Rcpp::List l) {
  for (int i = 0; i < l.length(); ++i) {
    Rcpp::DataFrame df = Rcpp::as<Rcpp::DataFrame>(l[i]);
    Rcpp::NumericVector last = df[df.cols() - 1];
    for (int j = 0; j < df.cols() - 1; ++j) {
      Rcpp::NumericVector col = df[j];
      df[j] = col + last / 100.0;
    }
  }
  return l;
}

/*** R
set.seed(42)
df1 <- data.frame(a = sample(1:100, 3),
                  b = sample(1:100, 3),
                  c = sample(0:99, 3))

df2 <- data.frame(a = sample(1:100, 3),
                  b = sample(1:100, 3),
                  c = sample(0:99, 3))

l <- list(df1 = df1, df2 = df2)

listDf(l)

*/

Выход:

> listDf(l)
$df1
      a     b  c
1 92.73 84.73 73
2 93.13 64.13 13
3 29.64 51.64 64

$df2
       a     b  c
1  71.94 94.94 94
2  46.96 26.96 96
3 100.11 46.11 11
2
ответ дан Ralf Stubner 17 August 2018 в 13:39
поделиться
  • 1
    – zeekster26 13 July 2018 в 14:50
  • 2
    поэтому происходит что-то смешное, как только количество элементов выходит за пределы 2 с помощью функции R do.call («список», ...) для создания большего списка, цифры меняются, а а и b выглядят по-разному, почему это? – zeekster26 13 July 2018 в 17:38
  • 3
    @ zeekster26 Я не следую вашему описанию. Ка вы предоставляете минимальный пример? – Ralf Stubner 13 July 2018 в 17:45
  • 4
    Таким образом, в R используется df1 & lt; - data.frame (a = образец (1: 100, 3), b = образец (1: 100, 3), c = образец (0:99, 3)), затем составить список объекты следующим образом: dsets & lt; -d.call («список», репликация (100, x, simplify = FALSE)) и создание, скажем, 100 (это просто быстрый пример, наборы данных не будут точно соответствовать то же самое в списке в реальной жизни). Теперь, когда вы запустите функцию listDf (dsets), она будет вставляться неправильно, а значения столбцов a и b будут отключены (почти так же, как если бы они факторизуются в элементах numbe rof в списке или что-то в этом роде). – zeekster26 13 July 2018 в 18:02
  • 5
    Извините, используйте это: dsets & lt; -do.call («список», репликация (100, df1, simplify = FALSE)), чтобы создать 100 наборов df1 – zeekster26 13 July 2018 в 18:11

@ Ralf Stubner понял, что я дам вам визуальный

df1 <- data.frame(a = sample(1:100, 3), b = sample(1:100, 3), c = sample(0:99, 3))

дает (не задал.seed):

  df1
  a  b  c
  28 70 70
  14 63  5
   8 12 20

dsets<-do.call("list", replicate(10, df1, simplify=FALSE)) #to replicate this 10 times 
#and store as list 

Запустите это

       listDf(dsets)

И вывод выглядит следующим образом:

[[9]]
  a    b  c
35.0 77.0 70
14.5 63.5  5
10.0 14.0 20

[[10]]
  a    b  c
35.0 77.0 70
14.5 63.5  5
10.0 14.0 20

Наверное, что-то простое мне не хватает?

0
ответ дан zeekster26 17 August 2018 в 13:39
поделиться
  • 1
    Таким образом, я обнаружил, что он добавляет + (c / 100) для одной итерации, а затем снова добавляет c / 100 к результату + (c / 100), поэтому он учитывает элементы списка. То же самое для столбца b. Однако я не знаю, как это исправить. – zeekster26 13 July 2018 в 18:52
  • 2
    Это является результатом управления памятью R с использованием «copy on write», то есть если вы создаете «копию», например, через rep, чем это только ссылка. Но прежде чем вы напишете объект, сделайте копию. Это потеряно при переходе на C ++. Ваш список dsets содержит десять ссылок на один и тот же объект, которые затем обрабатываются на месте. Если вы создадите список из десяти различных кадров данных, то он работает так, как ожидалось. – Ralf Stubner 13 July 2018 в 20:15
  • 3
    Ahhh, спасибо, это имеет смысл и ценится! – zeekster26 13 July 2018 в 20:28