Я думаю, что полный диапазон дат можно расширить с помощью полного объединения / слияния. Это предполагает, что все даты в первом месяце. Расширенный диапазон дат, скрещенных со всеми уникальными id
s
daterange <- expand.grid(
id = unique(x$id),
date = seq.Date(min(x$date), max(x$date) + 31, by = "month"),
stringsAsFactors = FALSE
)
Вот две реализации, в зависимости от вашего стиля:
library(dplyr)
library(tidyr)
x %>%
full_join(daterange, by = c("id", "date")) %>%
arrange(id, date) %>%
group_by(id) %>%
mutate(clasif = zoo::na.locf(clasif)) %>%
ungroup()
# # A tibble: 8 x 3
# id date clasif
# <chr> <date> <chr>
# 1 A 2018-01-01 A
# 2 A 2018-02-01 A
# 3 A 2018-03-01 AAA
# 4 A 2018-04-01 AAA
# 5 B 2018-01-01 BBB
# 6 B 2018-02-01 BBB
# 7 B 2018-03-01 BBB
# 8 B 2018-04-01 BBB
и
library(data.table)
library(magrittr)
xDT <- copy(x)
setDT(xDT)
xDT <- merge(xDT, daterange, by = c("id", "date"), all = TRUE) %>%
.[ order(id, date), ] %>%
.[, clasif := zoo::na.locf(clasif), by = "id"]
(я использую magrittr
здесь, чтобы разбить поток data.table
на более пошаговый конвейер, в основном для визуальной выгоды. Это не требуется; в зависимости от ваших предпочтений, это может быть передано по DT так же, как легко, например, xDT[...][...][...]
.)
Оба оперируют тем, что после слияния мы получаем «дыры» в столбце clasif
:
x %>%
full_join(daterange, by = c("id", "date"))
# id date clasif
# 1 A 2018-01-01 A
# 2 A 2018-03-01 AAA
# 3 B 2018-01-01 BBB
# 4 A 2018-02-01 <NA>
# 5 B 2018-02-01 <NA>
# 6 B 2018-03-01 <NA>
# 7 A 2018-04-01 <NA>
# 8 B 2018-04-01 <NA>
Отсюда zoo::na.locf
(по id
, по date
) заполните отверстия.
Данные:
x <- data.frame(
id = c("A", "A", "B"),
date = c("01/01/2018", "03/01/2018", "01/01/2018"),
clasif = c("A", "AAA", "BBB"),
stringsAsFactors = FALSE
)
x$date <- as.Date(x$date, format = "%m/%d/%Y")