Генерация рядов из запаздывающих данных с помощью глагола Mutate в R Tidyverse - PullRequest
0 голосов
/ 12 октября 2019

Я работаю с некоторыми большими наборами данных в R, но не могу найти способ изменить переменную с предыдущим значением.

В цикле for это будет:

df <- tibble(x=c(1:10),y=c(1:10))

for(i in c(2:nrow(df))) {
    df$x[i] = df$x[i-1] * 1.05
}

Я попробовал следующее, но оно не работает. Это только отстает от серии один раз. Мне нужно, чтобы он отставал, поскольку он перебирает данные.

df %>% mutate(x=ifelse(x==1,1,lag(x)*1.05))

, где мой метод возвращает 1, 1.05, 2.10 для первых трех строк, я хотел бы, чтобы он возвращал 1, 1.05,1.10.

Ответы [ 2 ]

2 голосов
/ 12 октября 2019

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

df %>%
  mutate(xrate = 1.05,  # make a helper column to hold the growth rate
         # method 1, using cumprod on the helper column
         x  = cumprod(lag(xrate, default = 1)),
         # method 2, using algebra
         x2 = 1.05 ^ (y-1)) %>%
  select(-xrate)

# A tibble: 10 x 3
       x     y    x2
   <dbl> <int> <dbl>
 1  1        1  1   
 2  1.05     2  1.05
 3  1.10     3  1.10
 4  1.16     4  1.16
 5  1.22     5  1.22
 6  1.28     6  1.28
 7  1.34     7  1.34
 8  1.41     8  1.41
 9  1.48     9  1.48
10  1.55    10  1.55
0 голосов
/ 12 октября 2019

Я думаю, что суть вашего вопроса в том, как векторизовать вычисления, но, в конечном счете, вы не сможете, если одна строка является функцией результата предыдущей строки. Есть несколько быстрых накопительных функций, встроенных в базу (cumsum, cumprod, cummax, cummin), но я предполагаю, что они используют цикл C или C ++ под капотом. Если по какой-то случайности вы можете преобразовать вычисление в функцию с начальным значением x, это может позволить вам векторизовать функцию. Например, в предоставленных вами фиктивных данных это просто экспоненциальный рост, который может быть выражен как

tibble(x=c(1:10),y=c(1.05)) %>%
  mutate(x = 1*y^(x-1))

, как это было предложено в предыдущем ответе

Если ваш вопрос заключается в том, как этовычисление в сценарий стиля трубы, тогда единственное требование к выражению, предоставленному mutate, состоит в том, чтобы он возвращал вектор либо длины 1, либо одинаковой длины числа строк в группе. Таким образом, вы можете сделать что-то вроде этого:

tibble(x=c(1:10),y=c(1.05)) %>%
  mutate(x = {
    out <- x[1]
    for(i in seq(2, NROW(x))) {
      out[i] = out[i-1] * 1.05
    }
    out
  })
...