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