Search code examples
rpurrrdplyrbroom

How to apply sw_glance using mutate_at to nested time-series dataframe?


I am forecasting several models on a nested (grouped) df. My issue is solved if I apply sw_glance to each list-column separately, but, for my example, if I am applying 6 models, then it is asking me to mutate six times. I have spent countless hours and I think I am almost there. Why can't I do the line below and overwrite the existing variables with the new values the function brings? (I included a reprex below, where step 5 is where I am getting stuck)

models_df%<>% map(~mutate_at(.x,vars(mod_ets,mod_hw)),sw_glance)

Just to name a few, here is the list:

-tidyverse documentation, where it mentioned that for grouped variables, mutate_at would fail, unless I add -group_cols(). No go.

-purrr documentation: I tried pmap passing a list of variables. I tried map in combination with mutate_at. I tried mutate_at by itself. I have tried naming the function (.f ...) and anonymous one (~..), but nothing

-I tried here several articles, that almost got me there. I upgraded to tidyr 1.0 and can include my sessionInfo() if needed.

#1 dummy df
df=tibble(Tag=seq(as.Date("2010-01-01"),by="month", length.out = 60), gatos=sample(c("a","b"),60, replace = T), sales=runif(60))

#2 nesting 
nested_df= df %>% 
  group_by(gatos) %>% 
  nest()

#3 declaring time series
ts_vector = nested_df %>%
  mutate(data.ts=map(data,tk_ts,select=-Tag,start=c(2010,01),freq=12))

# Step 4: Apply models
models_df = ts_vector %>% 
  mutate(mod_ets = map(data.ts,ets),
         mod_hw = map(data.ts,HoltWinters))

# Step 5: Apply sw_glance (Does NOT work)
models_df %<>%
map(~mutate_at(.x,vars(mod_ets,mod_hw)),sw_glance)

Error in UseMethod("tbl_vars") : 
  no applicable method for 'tbl_vars' applied to an object of class "character"

# This DOES work
models_df %<>% 
  mutate(foo_ets=map(mod_ets,sw_glance),
         foo_hw=map(mod_hw,sw_glance))

I would expect that mutate_at modifies the existing variables without having to add new ones. Otherwise, I would appreciate how to apply sw_glance to several models in one-go if possible. Thank you guys. I really appreciate your help.


Solution

  • We can write a function to apply sw_glance to each model

    library(tidyverse)
    
    apply_models <- function(list_model) map(list_model, sweep::sw_glance)
    

    and apply it to multiple columns using mutate_at

    models_df %>% mutate_at(vars(mod_ets, mod_hw), apply_models)
    
    #  gatos           data data.ts mod_ets           mod_hw           
    #  <chr> <list<df[,2]>> <list>  <list>            <list>           
    #1 b           [31 × 2] <ts>    <tibble [1 × 12]> <tibble [1 × 12]>
    #2 a           [29 × 2] <ts>    <tibble [1 × 12]> <tibble [1 × 12]>