Как да изчислим променлива с помощта на лагирана стойност с помощта на R

Да предположим, че имам прост набор от данни

df <- data.frame(id=c("A","B","C","D","E","F"),
                 value=c(1,NA,NA,NA,NA,NA))

Искам да прекодирам стойност (или да създам нова променлива), така че всяка следваща стойност да е равна на предишната стойност * 2 + предишната стойност.

| id | value |
|----|-------|
| A  | 1     |
| B  | 3     |
| C  | 9     |
| D  | 27    |
| E  | 81    |
| F  | 243   |

Мислех, че мога да направя това с помощта на забавяне:

df <- df %>%
  mutate(value=(lag(value)*2)+lag(value))

Но това не проработи. Затова вместо това използвах for цикъл

for (i in 2:nrow(df)){
  df[I,"value"] <-(df[i-1,"value"]*2)+df[i-1,"value"]
}

Това работи, но изглежда неелегантно. Има ли по-добър начин да направите това с помощта на конвенции/инструменти на tidyverse?


person Martin    schedule 13.03.2020    source източник


Отговори (2)


Можем да използваме accumulate от purrr

library(dplyr)
library(purrr)
df %>% 
     mutate(value = accumulate(value, ~ .x * 2 + .x))
#  id value
#1  A     1
#2  B     3
#3  C     9
#4  D    27
#5  E    81
#6  F   243

Или по-компактен

df %>%
     mutate(value = accumulate(value, ~ .x* 3))

Или в base R с Reduce

Reduce(function(x, y)  x * 2 + x, df$value, accumulate = TRUE)
#[1]   1   3   9  27  81 243
person akrun    schedule 13.03.2020

Можем да използваме accumulate от purrr:

library(dplyr)

df %>%
  mutate(value = purrr::accumulate(value[-n()], ~.x * 2 + .x, 
                .init = first(value)))

#  id value
#1  A     1
#2  B     3
#3  C     9
#4  D    27
#5  E    81
#6  F   243

Което може да се направи по подобен начин в база R, използвайки Reduce

Reduce(function(x, y) x * 2 + x, df$value[-nrow(df)], init = df$value[1], 
       accumulate = TRUE)
#[1]   1   3   9  27  81 243
person Ronak Shah    schedule 13.03.2020