Предположим, что наши входные данные - это фрейм данных со столбцами ID, st, en, как показано ниже. Значения st и en для разных идентификаторов могут отличаться.
Пример ниже имеет одинаковую дату начала и ту же дату окончания для каждого идентификатора, но код обрабатывает общий случай.
Использование функции make_dates
для каждого входного идентификатора, т.е. для каждого строка, преобразуйте st
и en
в класс yearqtr
, создайте последовательность между ними, преобразуйте в дату конца квартала (fra c = 1 означает конец квартала), включите st
и en
убедитесь, что ни один элемент не превышает en
, и удалите дубликаты. Используйте group_by / group_modify, чтобы применить это к каждому идентификатору (то есть к каждой строке), или в конце мы показали, как использовать do.call/by в качестве альтернативы.
library(dplyr)
library(zoo)
# test input
inp <- data.frame(ID = 1:2, st = as.Date("2001-12-29"), en = as.Date("2002-05-31"))
# given dates st & en return a vector of them and intervening qtr ends
make_dates <- function(st, en) {
st <- as.Date(st)
en <- as.Date(en)
yq1 <- as.yearqtr(st)
yq2 <- as.yearqtr(en)
dates <- as.Date(seq(yq1, yq2, 1/4), frac = 1)
unique(pmin(c(st, dates, en), en))
}
inp %>%
group_by(ID) %>%
group_modify(~ cbind(., Date = make_dates(st, en))) %>%
ungroup
, давая:
# A tibble: 8 x 4
ID st en Date
<int> <date> <date> <date>
1 1 2001-12-29 2002-05-31 2001-12-29
2 1 2001-12-29 2002-05-31 2001-12-31
3 1 2001-12-29 2002-05-31 2002-03-31
4 1 2001-12-29 2002-05-31 2002-05-31
5 2 2001-12-29 2002-05-31 2001-12-29
6 2 2001-12-29 2002-05-31 2001-12-31
7 2 2001-12-29 2002-05-31 2002-03-31
8 2 2001-12-29 2002-05-31 2002-05-31
Альтернативно конвейер dplyr можно выполнить без dplyr, например:
add_dates <- function(x) with(x, data.frame(ID, st, en, Date = make_dates(st, en)))
do.call("rbind", by(inp, inp$ID, add_dates))
Обновление
Обновление несколько раз.