【问题标题】:Split durations into annual parts将持续时间拆分为年度部分
【发布时间】:2020-03-24 09:34:53
【问题描述】:

问题: 我有一个数据框,它包含跨案例(列:case)的持续时间(列:beginend)。一些持续时间跨越两年。我需要将这些案例分成年度持续时间:一个持续到年底,其余持续时间从明年开始。

目前的做法: 我设法计算了这些持续时间(请参见下面的当前方法),但我无法将相应的行拆分为多个行,同时不影响年度案例。

您可以在下面找到一个可重现的示例:

# 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

【问题讨论】:

    标签: r date lubridate


    【解决方案1】:

    您不能使用mutate 来延长您的数据。

    通过复制桥接年份的条目,然后使用 lubridate 函数根据需要控制月份和日期,然后将重复项连接回原始数据框,这可能是最简单的方法来展示如何在基本 R 语法中完成此操作。

    bridgers                <- which(year(df$end) != year(df$begin))
    df2                     <- df[bridgers,]
    
    year(df$end[bridgers])  <- year(df$begin[bridgers])
    month(df$end[bridgers]) <- 12
    mday(df$end[bridgers])  <- 31
    
    year(df2$begin)         <- year(df2$end)
    month(df2$begin)        <- 1
    mday(df2$begin)         <- 1
    
    df <- rbind(df, df2)
    df[order(df$case), ]
    #> # A tibble: 6 x 4
    #>    case begin      end        reason
    #>   <dbl> <date>     <date>     <chr> 
    #> 1     1 2019-12-20 2019-12-31 X     
    #> 2     1 2019-08-05 2019-08-20 Y     
    #> 3     1 2020-01-01 2020-01-15 X     
    #> 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
    

    reprex package (v0.3.0) 于 2020 年 3 月 24 日创建

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2010-09-20
      • 2019-04-06
      • 1970-01-01
      • 2020-04-11
      • 2021-02-24
      • 2016-05-11
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多