这是一个 dplyr 方法:
library(dplyr)
dat %>%
mutate(rn = row_number()) %>%
rowwise() %>%
slice(rep(1, Count)) %>%
group_by(rn) %>%
mutate(Date = seq(Date[1], by = "months", length.out = n())) %>%
ungroup() %>%
select(-rn)
# # A tibble: 12 x 3
# Name Date Count
# <chr> <date> <int>
# 1 John 2019-10-21 12
# 2 John 2019-11-21 12
# 3 John 2019-12-21 12
# 4 John 2020-01-21 12
# 5 John 2020-02-21 12
# 6 John 2020-03-21 12
# 7 John 2020-04-21 12
# 8 John 2020-05-21 12
# 9 John 2020-06-21 12
# 10 John 2020-07-21 12
# 11 John 2020-08-21 12
# 12 John 2020-09-21 12
快速演练:
- 添加
rn 以便我以后可以最轻松/自信地按它们分组(因为每个名称/日期组合可能出现任意次数,我在推断);
-
slice(rep(1, Count)) 选择第一行,Count 次,给出所需的重复行;因为这已经是逐行(rowwise()),这只是将行扩展Count
-
seq(Date[1], ...) 因为此时,Date 是一个可能大于 1 的向量,我们真的只关心重复日期中的第一个; by="months" and length.out=n()` 确保我们获得填充行数所需的间隔和跨度/周期
- 使用
ungroup() 进行一些清理并删除 rn 帮助器列
更新
如果您需要将月份中的某天 (dom) 设为起始 dom 和该月份的天数中的较小者,请尝试此操作。
也就是说,使用"2019-01-31",按月排序不会跳转到"2019-02-31"(不存在),而是跳转到"2019-03-03"。如果你需要它跳转到"2019-02-28"(因为那是那个月的最后一天),那么试试这个功能。 (我们现在依赖lubridate 包。)
seq_similar_dom <- function(first, length.out) {
dom <- lubridate::day(first)
month1 <- first - dom + 1L
months1 <- seq(month1, by = "months", length.out = length.out)
months1 - 1L + pmin(dom, lubridate::days_in_month(months1))
}
让我们更新我们的示例并尝试几个极端情况。
首先,如果特定条目的dom 为 28 或更少,那么这将完全相同。如果是 29 或更高,虽然...
dat$Date <- as.Date("2014-07-31")
dat %>%
mutate(rn = row_number()) %>%
rowwise() %>%
slice(rep(1, Count)) %>%
group_by(rn) %>%
mutate(Date = seq_similar_dom(Date[1], length.out = n())) %>%
ungroup() %>%
select(-rn)
# # A tibble: 12 x 3
# Name Date Count
# <chr> <date> <int>
# 1 John 2014-07-31 12
# 2 John 2014-08-31 12
# 3 John 2014-09-30 12
# 4 John 2014-10-31 12
# 5 John 2014-11-30 12
# 6 John 2014-12-31 12
# 7 John 2015-01-31 12
# 8 John 2015-02-28 12
# 9 John 2015-03-31 12
# 10 John 2015-04-30 12
# 11 John 2015-05-31 12
# 12 John 2015-06-30 12
dat$Date <- as.Date("2019-01-31")
dat %>%
mutate(rn = row_number()) %>%
rowwise() %>%
slice(rep(1, Count)) %>%
group_by(rn) %>%
mutate(Date = seq_similar_dom(Date[1], length.out = n())) %>%
ungroup() %>%
select(-rn)
# # A tibble: 12 x 3
# Name Date Count
# <chr> <date> <int>
# 1 John 2019-01-31 12
# 2 John 2019-02-28 12
# 3 John 2019-03-31 12
# 4 John 2019-04-30 12
# 5 John 2019-05-31 12
# 6 John 2019-06-30 12
# 7 John 2019-07-31 12
# 8 John 2019-08-31 12
# 9 John 2019-09-30 12
# 10 John 2019-10-31 12
# 11 John 2019-11-30 12
# 12 John 2019-12-31 12
数据:
dat <- structure(list(Name = "John", Date = "10-21-2019", Count = 12L), class = "data.frame", row.names = c(NA, -1L))
dat$Date <- as.Date(dat$Date, format = "%m-%d-%Y")