【发布时间】:2020-03-24 09:34:53
【问题描述】:
问题:
我有一个数据框,它包含跨案例(列:case)的持续时间(列:begin 和 end)。一些持续时间跨越两年。我需要将这些案例分成年度持续时间:一个持续到年底,其余持续时间从明年开始。
目前的做法: 我设法计算了这些持续时间(请参见下面的当前方法),但我无法将相应的行拆分为多个行,同时不影响年度案例。
您可以在下面找到一个可重现的示例:
# Packages
library(tidyverse)
library(lubridate)
# Reproducible example
df <- tibble(
case = c(1, 1, 2, 3),
begin = ymd("2019-12-20", "2019-08-05", "2012-01-01", "2014-10-10"),
end = ymd("2020-01-15", "2019-08-20", "2012-01-12", "2015-01-15"),
reason = c("X", "Y", "X", "Y"))
head(df)
#> # A tibble: 4 x 4
#> case begin end reason
#> <dbl> <date> <date> <chr>
#> 1 1 2019-12-20 2020-01-15 X
#> 2 1 2019-08-05 2019-08-20 Y
#> 3 2 2012-01-01 2012-01-12 X
#> 4 3 2014-10-10 2015-01-15 Y
# Goal (split durations and make them "longer")
goal <- tibble(
case = c(1, 1, 1, 2, 3, 3),
begin = ymd("2019-12-20", "2020-01-01", "2019-08-05", "2012-01-01", "2014-10-10", "2015-01-01"),
end = ymd("2019-12-31", "2020-01-15", "2019-08-20", "2012-01-12", "2014-12-31", "2015-01-15"),
reason = c("X", "X", "Y", "X", "Y", "Y"))
head(goal)
#> # A tibble: 6 x 4
#> case begin end reason
#> <dbl> <date> <date> <chr>
#> 1 1 2019-12-20 2019-12-31 X
#> 2 1 2020-01-01 2020-01-15 X
#> 3 1 2019-08-05 2019-08-20 Y
#> 4 2 2012-01-01 2012-01-12 X
#> 5 3 2014-10-10 2014-12-31 Y
#> 6 3 2015-01-01 2015-01-15 Y
# Current approach
df %>%
mutate(end_year = if_else(year(begin) != year(end),
ceiling_date(ymd(begin), "year") - days(1), end),
begin_year = if_else(year(begin) != year(end),
ceiling_date(ymd(end), "year"), begin))
#> # A tibble: 4 x 6
#> case begin end reason end_year begin_year
#> <dbl> <date> <date> <chr> <date> <date>
#> 1 1 2019-12-20 2020-01-15 X 2019-12-31 2021-01-01
#> 2 1 2019-08-05 2019-08-20 Y 2019-08-20 2019-08-05
#> 3 2 2012-01-01 2012-01-12 X 2012-01-12 2012-01-01
#> 4 3 2014-10-10 2015-01-15 Y 2014-12-31 2016-01-01
如果您能指出我的解决方案,我们将不胜感激。提前致谢。
编辑根据Allan Cameron的回答:
# Final solution
library(tidyverse)
library(lubridate)
# Reproducible example
df <- tibble(
case = c(1, 1, 2, 3),
begin = ymd("2019-12-20", "2019-08-05", "2012-01-01", "2014-10-10"),
end = ymd("2020-01-15", "2019-08-20", "2012-01-12", "2015-01-15"),
reason = c("X", "Y", "X", "Y"))
# Find durations that run across a year
df2 <- df %>%
filter(year(end) != year(begin)) %>%
mutate(begin = ceiling_date(ymd(begin), "year"), begin)
#
df <- df %>%
mutate(end = if_else(year(end) != year(begin),
ceiling_date(ymd(begin), "year") - days(1), end))
# Merge
df <- df %>%
bind_rows(df2) %>%
arrange(case, reason)
head(df)
#> # A tibble: 6 x 4
#> case begin end reason
#> <dbl> <date> <date> <chr>
#> 1 1 2019-12-20 2019-12-31 X
#> 2 1 2020-01-01 2020-01-15 X
#> 3 1 2019-08-05 2019-08-20 Y
#> 4 2 2012-01-01 2012-01-12 X
#> 5 3 2014-10-10 2014-12-31 Y
#> 6 3 2015-01-01 2015-01-15 Y
【问题讨论】: