zhiwei li
zhiwei li

Reputation: 1711

Use multiple functions in mutate efficiently in R

I used mutate to add new variables in my dataframe. The code below is an example and in my real data I need to mutate lag1 to lag100 and lag01 to lag0100. I don't want to type these one by one.

Is there an efficient way to do this?

c <- mtcars %>% mutate_all( .funs = list(lag1 = ~lag(., 1),
                                         lag2 = ~lag(., 2),
                                         lag3 = ~lag(., 3),
                                         lag4 = ~lag(., 4),
                                         lag5 = ~lag(., 5),
                                         lag6 = ~lag(., 6),
                                         lag01 = ~rollmean(., 2, fill = NA, align = 'right'),
                                         lag02 = ~rollmean(., 3, fill = NA, align = 'right'),
                                         lag03 = ~rollmean(., 4, fill = NA, align = 'right'),
                                         lag04 = ~rollmean(., 5, fill = NA, align = 'right'),
                                         lag05 = ~rollmean(., 6, fill = NA, align = 'right'),
                                         lag06 = ~rollmean(., 7, fill = NA, align = 'right')
                                         ))

Any help will be highly appreciated!

Upvotes: 1

Views: 1114

Answers (2)

Ronak Shah
Ronak Shah

Reputation: 388982

You can use across in new dplyr 1.0.0 to apply multiple functions to all columns. rollmean with align = 'right is same as using rollmeanr. You can assign relevant names using .names specification.

library(dplyr)
library(purrr)
library(zoo)

x <- 5
map_dfc(1:x, function(i) mtcars %>% 
        transmute(across(.fns = list(lag = ~lag(., i), 
                   mean =  ~rollmeanr(., i + 1, fill = NA)), 
                   .names = paste0('{col}_{fn}_', i))))

Upvotes: 3

Rui Barradas
Rui Barradas

Reputation: 76432

In the example that follows I have subset mtcars keeping only 20 rows and 5 columns.
The code uses bind_cols/Map to apply the functions lag and rollmeanr (rollmean, align = "right").

library(dplyr)
library(zoo)

bind_cols(
  mtcars[1:20, 1:5] %>% 
    mutate_all(.funs = Map(function(n) lag = ~lag(., n), 1:2)),
  mtcars[1:20, 1:5] %>% 
    mutate_all(.funs = Map(function(n) lag0 = ~rollmeanr(., n, fill = NA), 1:2)) %>%
    select(-(1:5))
)

Then it's a matter of assigning new column names.

Upvotes: 1

Related Questions