【问题标题】:Expand dataframe following sets of rules按照规则集展开数据框
【发布时间】:2020-04-24 18:37:33
【问题描述】:

我有一个非常复杂的问题,我无法解决。

我有一个在 dplyr 中读取的数据框:

trans_id date       type
9373    2019-09-29  6-months 
9945    2019-08-15  3-months 
9945    2019-11-13  3-months 
9615    2019-12-28  3-months 
11465   2019-07-13  3-months 
11465   2019-10-11  3-months 

可重现的例子:

library(tidyverse)

df <- data.frame(stringsAsFactors=FALSE,
          id = c(9373, 9945, 9945, 9615, 11465, 11465),
        date = c("2019-09-29", "2019-08-15", "2019-11-13", "2019-12-28",
                 "2019-07-13", "2019-10-11"),
        type = c("6-months", "3-months", "3-months", "3-months", "3-months",
                 "3-months")) %>%
  mutate(date = as.Date(date))

每个id 都是一个事务,发生在给定的date 上;每笔交易可以每 3 个月或 6 个月重复一次 - 如type 中所述。

我想扩展这些每月对应的交易,直到当前日期;这意味着第一笔交易 9373 必须重复 6 次,周期为 30 天(type == 6 个月),从 2019 年 9 月 29 日到当天(今天是 2020 年 1 月 7 日),又名将只有 4 次单月交易,因为最后两次必须发生。

对于 3 个月的交易也是如此,始终考虑开始日期和当前日期。

最终结果示例:

id      date        type
9373    2019-09-29  6-months # first 6-months cycle transaction
9373    2019-10-29  6-months 
9373    2019-11-28  6-months 
9373    2019-12-28  6-months 
9945    2019-08-15  3-months # 
9945    2019-09-14  3-months 
9945    2019-10-14  3-months 
9945    2019-11-13  3-months #
9945    2019-12-13  3-months 
9615    2019-12-28  3-months #

非常感谢任何帮助!

【问题讨论】:

    标签: r dplyr tidyverse


    【解决方案1】:

    您可以像这样使用rowwisedo

    df %>% 
      rowwise() %>% 
      do({
        p <- as.numeric(gsub('\\D+','',.$type))-1
        tibble(
          id=.$id,
          date=seq(.$date,pmin(Sys.Date(),.$date+p*30),30),
          type=.$type
        )
      }) %>% 
      ungroup()
    
    # A tibble: 16 x 3
    # id date       type    
    # * <dbl> <date>     <chr>   
    #   1  9373 2019-09-29 6-months
    # 2  9373 2019-10-29 6-months
    # 3  9373 2019-11-28 6-months
    # 4  9373 2019-12-28 6-months
    # 5  9945 2019-08-15 3-months
    # 6  9945 2019-09-14 3-months
    # 7  9945 2019-10-14 3-months
    # 8  9945 2019-11-13 3-months
    # 9  9945 2019-12-13 3-months
    # 10  9615 2019-12-28 3-months
    # 11 11465 2019-07-13 3-months
    # 12 11465 2019-08-12 3-months
    # 13 11465 2019-09-11 3-months
    # 14 11465 2019-10-11 3-months
    # 15 11465 2019-11-10 3-months
    # 16 11465 2019-12-10 3-months
    

    【讨论】:

      【解决方案2】:

      这是使用dplyrtidyr 函数的一种方法。

      library(dplyr)
      library(tidyr)
      
      df %>%
        #Extract the number from type column
        mutate(num = readr::parse_number(type)) %>%
        #For each transcation
        group_by(row = row_number()) %>%
        #Create a sequence from date till number of months with a break of 30 days
        complete(id, type, date = seq(date, by = "30 days", length.out = num)) %>%
        #Remove rows which have date value greater than today
        filter(date <= Sys.Date()) %>%
        ungroup() %>%
        select(-num, -row)
      
      # A tibble: 16 x 3
      #      id type     date      
      #   <dbl> <chr>    <date>    
      # 1  9373 6-months 2019-09-29
      # 2  9373 6-months 2019-10-29
      # 3  9373 6-months 2019-11-28
      # 4  9373 6-months 2019-12-28
      # 5  9945 3-months 2019-08-15
      # 6  9945 3-months 2019-09-14
      # 7  9945 3-months 2019-10-14
      # 8  9945 3-months 2019-11-13
      # 9  9945 3-months 2019-12-13
      #10  9615 3-months 2019-12-28
      #11 11465 3-months 2019-07-13
      #12 11465 3-months 2019-08-12
      #13 11465 3-months 2019-09-11
      #14 11465 3-months 2019-10-11
      #15 11465 3-months 2019-11-10
      #16 11465 3-months 2019-12-10
      

      【讨论】:

      • 嗨! “扩展”概念工作得很好,但它没有考虑到“类型”列......对于标记为“6个月”的行,它应该“最多”扩展6次,对于标记为“6个月”的行应该扩展3次标记为“3 个月”的行...
      • @xxxvincxxx 我认为我的代码也是如此。我的输出的哪一部分不遵循该规则?
      猜你喜欢
      • 2018-12-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多