首页 文章

如何根据开始和结束日期R将记录拆分为多个记录

提问于
浏览
2

我会尝试通过获取样本数据来解释我的问题

ID      Region      Start_Date     End_Date
 1       Reg1       27/1/2017      27/1/2017
 2       Reg1       27/2/2017      05/3/2017
 1       Reg1       24/3/2017      25/5/2017

现在我希望结果是这样的:

ID      Region      n_Start_Date   n_End_Date
 1       Reg1       27/1/2017      27/1/2017
 2       Reg2       27/2/2017      28/2/2017
 2       Reg2       01/3/2017      05/3/2017
 1       Reg1       24/3/2017      31/3/2017
 1       Reg1       01/4/2017      30/4/2017
 1       Reg1       01/5/2017      31/5/2017

我正在考虑实施的当前方法:

我创建了一个数据框,其中有14条记录,每个月的开始日期和结束日期分别为2017年和2018年:

Year    Month   Start of Month  End of Month
2017      1        1/1/2017      31/1/2017
2017      2        1/2/2017      28/2/2017
2017      3        1/3/2017      31/3/2017
2017      4        1/4/2017      30/4/2017
2017      5        1/5/2017      31/5/2017
2017      6        1/6/2017      30/6/2017
2017      7        1/7/2017      31/7/2017
2017      8        1/8/2017      31/8/2017
2017      9        1/9/2017      30/9/2017
2017      10       1/10/2017     31/10/2017
2017      11       1/11/2017     30/11/2017
2017      12       1/12/2017     31/12/2017
2018      1        2/12/2017     31/1/2018
2018      2        3/12/2017     28/2/2018

我已经为一年和一个月创建了一个新专栏:

  • 如果开始日期年份,月份与结束日期年份,月份相同,则下一个相同的开始日期和结束日期将被复制到新的数据框架中
ID      Region   Start_Date     End_Date   n_Start_Date   n_End_Date
1       Reg1      27/1/2017     27/1/2017   27/1/2017      27/1/2017
  • 如果开始日期年份,月份不相同,则会附加
ID      Region   Start_Date     End_Date   n_Start_Date   n_End_Date
2       Reg2      27/2/2017    05/3/2017    27/2/2017      28/2/2017
2       Reg2      27/2/2017    05/3/2017    01/3/2017      05/3/2017

我无法通过这个link,但没有用 .

如果有更好的方法,请告诉我 .

1 回答

  • 1

    我想我已经理解了你想要的东西,如果你有一个日期,结束日期不在同一年和月份,你会产生一个新的行,直到它发生 . 生成的行应在一天后开始,并在该月末结束 .

    # packages we need
    library(tidyverse)
    library(lubridate)
    

    示例数据

    test_data <- tribble(
      ~ID, ~Region, ~Start_Date, ~End_Date,
      1L, "Reg1", "27/1/2017", "27/1/2017",
      2L, "Reg2", "27/2/2017", "05/3/2017",
      1L, "Reg1", "24/3/2017", "25/5/2017"
    ) %>% mutate_at(vars(Start_Date, End_Date), dmy)
    

    创建一个函数

    如果我们在任何开始和结束时使功能完成您想要的功能,我们可以在之后轻松应用它 .

    expand_dates <- function(start, end) {
    
      # the number of entries we want to add
      to_add <- month(end) - month(start) 
    
      # Take the start date, roll it forwards until the month is equal to the end month
      start_dates <- start + months(0:to_add)
    
      # everything but the first start_date is rolled back to first of month
      start_dates <- c(start_dates[1],
                       rollback(start_dates[-1], roll_to_first = T))
    
      # end dates are just the start_dates rolled forwards to the end of the month
      # apply to all but last, thats the end date
      end_dates <- c(rollback(ceiling_date(start_dates[-length(start_dates)], unit = "months")), end)
    
      data.frame(start_dates = start_dates,
                 end_dates = end_dates)
    }
    

    使用该功能

    我们可以使用 purrr 来自 purrr ,这使我们可以迭代开始和结束日期 . 使用 mutate 我们添加了一个列表列 . 列表列中的每个元素都是一个data.frame,它是从我们的新函数输出的 . 我们将使用 unnest 然后将数据扩展到所需的数据 .

    test_data %>%
      mutate(test = map2(Start_Date, End_Date, expand_dates)) %>%
      unnest()
    
    
    # A tibble: 6 x 6
         ID Region Start_Date End_Date   start_dates end_dates 
      <int> <chr>  <date>     <date>     <date>      <date>    
    1     1 Reg1   2017-01-27 2017-01-27 2017-01-27  2017-01-27
    2     2 Reg2   2017-02-27 2017-03-05 2017-02-27  2017-02-28
    3     2 Reg2   2017-02-27 2017-03-05 2017-03-01  2017-03-05
    4     1 Reg1   2017-03-24 2017-05-25 2017-03-24  2017-03-31
    5     1 Reg1   2017-03-24 2017-05-25 2017-04-01  2017-04-30
    6     1 Reg1   2017-03-24 2017-05-25 2017-05-01  2017-05-25
    

相关问题