получить последний месяц и год из отдельных столбцов R

#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 записей ваших данных по группам? В этом случае будет работать приведенный ниже подход.

Этот подход предполагает, что:

  1. Каждый месяц — это одна строка / наблюдение (за один месяц нет двойных записей).
  2. Если месяц NA равен, он также будет «нарисован».
  3. Вы всегда заинтересованы в получении последних 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: Спасибо! Я добавил его в ответ со ссылкой на ваш комментарий.