Как вычислить переменную, используя запаздывающее значение, используя 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