#r
#r
Вопрос:
У меня есть фрейм данных (в R) с отдельными столбцами для месяца и года. для каждой группы в dataframe я хочу получить последние 12 месяцев в серии. Если в данных отсутствует один из самых последних месяцев, я хочу заменить его месяцем за предыдущий год. Например, предположим, я хочу получить данные за 2020 год (январь — декабрь), но самые последние данные для группы — сентябрь, тогда я бы хотел получить данные за октябрь-декабрь 2019 года. Я просто не могу понять, как это сделать.
Вот один из примеров.
a = expand.grid(1:2,2019,1:12)
b = expand.grid(1:2,2020,1:9)
dat = rbind(a,b)
names(dat) = c("group","year","month")
dat = dat[order(dat$group,dat$year,dat$month),]
Итак, данные выглядят следующим образом:
group year month
1 1 2019 1
3 1 2019 2
5 1 2019 3
7 1 2019 4
9 1 2019 5
11 1 2019 6
Комментарии:
1. Вашим данным больше двух лет? Если да, то как вы справляетесь со случаем, когда, скажем, в 2019 и 2020 годах отсутствуют данные? Заполняете ли вы сначала 2019 год с 2018 года, а затем заполняете 2020 год обновленными данными за 2019 год? Или вы просматриваете исходные данные только на один год назад (в этом случае 2020 год покажет NA для недостающих месяцев в 2019 и 2020 годах)?
2. Мне нужно оглянуться назад только на один год, так как данные являются полными за каждый месяц. У меня просто есть случаи, когда данные не поступали, и поэтому мне нужно подстроиться под разные группы.
Ответ №1:
Я не уверен, будет ли достаточно всегда получать последние 12 записей ваших данных по группам? В этом случае будет работать приведенный ниже подход.
Этот подход предполагает, что:
- Каждый месяц — это одна строка / наблюдение (за один месяц нет двойных записей).
- Если месяц
NA
равен, он также будет «нарисован». - Вы всегда заинтересованы в получении последних 12 месяцев (так что это не 12 месяцев назад по времени от указанной даты ввода).
# your data
a = expand.grid(1:2,2019,1:12)
b = expand.grid(1:2,2020,1:9)
dat = rbind(a,b)
names(dat) = c("group","year","month")
dat = dat[order(dat$group,dat$year,dat$month),]
# using dplyr
library(dplyr)
dat %>%
group_by(group) %>%
slice_tail(n = 11)
#> # A tibble: 22 x 3
#> # Groups: group [2]
#> group year month
#> <int> <dbl> <int>
#> 1 1 2019 11
#> 2 1 2019 12
#> 3 1 2020 1
#> 4 1 2020 2
#> 5 1 2020 3
#> 6 1 2020 4
#> 7 1 2020 5
#> 8 1 2020 6
#> 9 1 2020 7
#> 10 1 2020 8
#> # … with 12 more rows
# using base R
do.call("rbind",
lapply(split(dat, dat$group), function(x) {
x[(nrow(x)-11):nrow(x), ]
}))
#> group year month
#> 1.19 1 2019 10
#> 1.21 1 2019 11
#> 1.23 1 2019 12
#> 1.25 1 2020 1
#> 1.27 1 2020 2
#> 1.29 1 2020 3
#> 1.31 1 2020 4
#> 1.33 1 2020 5
#> 1.35 1 2020 6
#> 1.37 1 2020 7
#> 1.39 1 2020 8
#> 1.41 1 2020 9
#> 2.20 2 2019 10
#> 2.22 2 2019 11
#> 2.24 2 2019 12
#> 2.26 2 2020 1
#> 2.28 2 2020 2
#> 2.30 2 2020 3
#> 2.32 2 2020 4
#> 2.34 2 2020 5
#> 2.36 2 2020 6
#> 2.38 2 2020 7
#> 2.40 2 2020 8
#> 2.42 2 2020 9
# using data.table (from @thelatemail's comment)
library(data.table)
setDT(dat)
setorder(dat, group, year, month)
dat[, .SD[(.N-11):.N], by = group]
#> group year month
#> 1: 1 2019 10
#> 2: 1 2019 11
#> 3: 1 2019 12
#> 4: 1 2020 1
#> 5: 1 2020 2
#> 6: 1 2020 3
#> 7: 1 2020 4
#> 8: 1 2020 5
#> 9: 1 2020 6
#> 10: 1 2020 7
#> 11: 1 2020 8
#> 12: 1 2020 9
#> 13: 2 2019 10
#> 14: 2 2019 11
#> 15: 2 2019 12
#> 16: 2 2020 1
#> 17: 2 2020 2
#> 18: 2 2020 3
#> 19: 2 2020 4
#> 20: 2 2020 5
#> 21: 2 2020 6
#> 22: 2 2020 7
#> 23: 2 2020 8
#> 24: 2 2020 9
#> group year month
Создано 2021-01-04 пакетом reprex (версия 0.3.0)
Комментарии:
1. Я думаю, что логика будет работать, но вам нужно сделать это для каждой группы. Кроме того,
nrow(dat)-11
я думаю, что это правильно, иначе вы вернетесь слишком много.2. @thelatemail: спасибо, что указали на это, я этого совершенно не видел 😉 — обновил ответ соответствующим образом.
3. перевод данных.таблицы для развлечения —
setDT(dat); setorder(dat, group, year, month); dat[, .SD[(.N-11):.N], by=group]
4. @thelatemail: Спасибо! Я добавил его в ответ со ссылкой на ваш комментарий.