purrr::accumulate() для двух кумулированных переменных, а не только 1

#r #purrr

Вопрос:

У меня есть модель, которая в качестве предиктора имеет предыдущий прогноз. например target ~ lag(target prediction)

Используя purrr::накопите, я могу написать пользовательскую функцию для прогнозирования. Пример некоторых глупых данных и глупой модели, которая иллюстрирует:

  ### A model that uses a lag prediction as a predictor using purrr::accumulate() ###
my_diamonds <- diamonds %>% 
  group_by(cut) %>% 
  mutate(cumprice = cumsum(price)) %>% # cumulative within groups
  mutate(lag_cumprice = lag(cumprice)) %>% 
  mutate(InitialValue = min(cumprice)) %>% 
  filter(!is.na(lag_cumprice)) %>% 
  select(cut, cumprice, lag_cumprice, x, InitialValue)

silly_model <- glm(formula = cumprice ~ x   lag_cumprice, family = 'poisson', data = my_diamonds)
 

Эта модель использует предыдущий прогноз в качестве входных данных для следующего прогноза. Я могу написать пользовательскую функцию для изменения прогноза:

 # when predicting won't have lag_cumprice, instead the result of the previous pediction should be an input to the model:
accPrice <- function(mod, acc, cur) {
  
  db=cur_data_all() # grouped data segment
  x = db$x[cur] # cur is the current row in the data, use it to get 'this' iterations value of x
  
  total_exponent <- mod$coefficients['(Intercept)']   
    (mod$coefficients['x'] * x)  
    (mod$coefficients['lag_cumprice'] * acc) # acc is the accumulated prediction for cumprice
}

# now predict
my_diamonds <- my_diamonds %>% 
  mutate(predicted = accumulate(.x = row_number()[-1], .init = InitialValue %>% unique, .f = accPrice, mod = silly_model))
 

Пока все хорошо. В этом примере я использовал предыдущий прогноз acc в качестве входных данных.

Но я создал вариационную модель, которая теперь использует две запаздывающие переменные в качестве предикторов:

 ### now a model with lag on two variables not just one ###
my_diamonds2 <- diamonds %>% 
  group_by(cut) %>% 
  mutate(cumprice = cumsum(price)) %>% # cumulative within groups
  mutate(lag_cumprice = lag(cumprice)) %>% 
  mutate(InitialValue = min(cumprice)) %>% 
  mutate(rn = row_number()) %>% 
  mutate(cumrn = cumsum(rn)) %>% 
  mutate(lag_cumrn = lag(cumrn)) %>% 
  filter(!is.na(lag_cumprice)) %>% 
  select(cut, cumprice, lag_cumprice, lag_cumrn, x, InitialValue)

silly_model2 <- glm(formula = cumprice ~ x   lag_cumprice   lag_cumrn, family = 'poisson', data = my_diamonds2)

### Stuck after here ###
 

Как я могу изменить функцию accPrice() выше, чтобы накапливать 2 переменные, как lag_cumprice, так и lag_cumrn, а не просто lag_cumprice, как раньше?

Комментарии:

1. есть accumulate2

2. @akrun правильно, я начал существовать, когда увидел это, но, возможно, я неправильно понял документацию… насколько я мог судить, accumulate2() не накапливается на 2 var, вместо этого он просто позволяет передать дополнительный var в функцию. Если только я не неправильно его понял? Я нахожу эту конкретную проблему r более сложной, чем другие, с которыми я боролся в прошлом

3. for Вариант с циклом был бы более прямым

4. Bsaed на посту, вы не используете lag_cumprice' or lag_cumrn в функции?

5. вы можете добавить новый параметр в функцию accPrice2 <- function(mod, acc, acc2, cur)

Ответ №1:

Мы могли бы добавить аргумент в функцию. Затем извлеките соответствующий коэффициент из модели и умножьте на него

 accPrice2 <- function(mod, acc, acc2, cur) {
   
   db=cur_data_all() # grouped data segment
   x = db$x[cur] # cur is the current row in the data, use it to get 'this' iterations value of x
   
   total_exponent <- mod$coefficients['(Intercept)']   
     (mod$coefficients['x'] * x)  
     (mod$coefficients['lag_cumprice'] * acc)    
    (mod$coefficients['lag_cumrn'] * acc2)
 }

my_diamonds2 %>% 
   mutate(predicted = accumulate(.x = row_number()[-1], 
      .init = InitialValue %>%
              unique, .f = accPrice2, mod = silly_model))
 

Комментарии:

1. Потрясающе! Он действительно работает! Большое спасибо. Один свободный конец с ним, при вызове, в последней строке, с которой я использую начальное значение .init . Когда он запускается, предположительно, он использует одно и то же начальное значение как для acc, так и для acc2? Любая идея, как сказать «используйте .init для начального значения lag_cumprice и, например,. init2 для начального значения lag_cumrn»

2. @DougFir Я тоже думал о вашей структуре. Создается InitialValue' из min «cumprice», что будет соответствовать cumrn

3. Для этого примера это было бы то же самое, но для cumrn, поэтому, когда я создавал второй пример набора данных, я должен был добавить что-то вроде mutate(InitialValueRN = min(cumrn)) %>%

4. @DougFir не min(cumrn) будет всегда 1

5. Я имел в виду, что я бы сделал, например. if(cur==1) acc2 = db$myvar[curr] else acc2