How to create multiple columns at once using same function with different argument values in R?

Advertisements

I have the following data:

library(tidyverse)
library(slider)

data <- tibble::tribble(
  ~group, ~value,
  "0001",     2L,
  "0001",    -2L,
  "0001",     7L,
  "0001",    -9L,
  "0001",     2L,
  "0001",    -4L,
  "0001",     6L,
  "0001",   -10L,
  "0001",     4L,
  "0001",    -3L,
  "0002",    -2L,
  "0002",     5L,
  "0002",    -2L,
  "0002",     4L,
  "0002",    -2L,
  "0002",     2L,
  "0002",    -3L,
  "0002",     3L,
  "0002",    -1L,
  "0002",     5L,
  "0003",    -2L,
  "0003",     6L,
  "0003",   -19L,
  "0003",     2L,
  "0003",    -1L,
  "0003",     2L,
  "0003",    -2L,
  "0003",     2L,
  "0003",    -2L,
  "0003",     4L
  )

I want to create multiple columns with the rolling sum of different numbers of previous rows, by group. I could do this manually and it would look like this:

data %>%
  group_by(group) %>%
  mutate(rolling1 = slide_sum(value, before = 1),
         rolling3 = slide_sum(value, before = 3),
         rolling5 = slide_sum(value, before = 5),
         rolling7 = slide_sum(value, before = 7),
         rolling9 = slide_sum(value, before = 9)) %>%
  ungroup()

However, I’m looking for ways to create multiple columns at once instead of doing it one by one. Anyone knows how I can do this?

>Solution :

With a user-defined function (that was slightly modified from here).

library(dplyr)
library(purrr)
calculate_lags <- function(df, var, lags){
  map_lag <- lags %>% map(~ partial(slider::slide_sum, before = .x))
  return(df %>% mutate(across(.cols = {{var}}, .fns = map_lag, .names = "rolling{lags}")))
}

data %>% 
  group_by(group) %>% 
  calculate_lags(value, seq(1, 9, 2))

output

# A tibble: 30 × 7
# Groups:   group [3]
   group value rolling1 rolling3 rolling5 rolling7 rolling9
   <chr> <int>    <dbl>    <dbl>    <dbl>    <dbl>    <dbl>
 1 0001      2        2        2        2        2        2
 2 0001     -2        0        0        0        0        0
 3 0001      7        5        7        7        7        7
 4 0001     -9       -2       -2       -2       -2       -2
 5 0001      2       -7       -2        0        0        0
 6 0001     -4       -2       -4       -4       -4       -4
 7 0001      6        2       -5        0        2        2
 8 0001    -10       -4       -6       -8       -8       -8
 9 0001      4       -6       -4      -11       -6       -4
10 0001     -3        1       -3       -5       -7       -7
# … with 20 more rows
# ℹ Use `print(n = ...)` to see more rows

Leave a ReplyCancel reply