【问题标题】:How to bin date by month如何按月分类日期
【发布时间】:2022-01-03 11:48:10
【问题描述】:

我有以下数据:

  df <- data.frame(dt1 = c("2019-05-02", "2019-01-02", "2019-06-02"), 
                   dt2 =   c("2019-08-30", "2019-04-24", "2019-12-06") )
> df
         dt1        dt2
1 2019-05-02 2019-08-30
2 2019-01-02 2019-04-24
3 2019-06-02 2019-12-06

这是我想做的:

i) 我想通过分箱来创建因子,例如,对于第一个日期,日期分箱为 2019 年 7 月 31 日、2019 年 6 月 30 日、2019 年 5 月 31 日,因此基本上按 dt2 分箱。
ii) 我想计算每个 bin 中的日期总数。

预期的输出是:

        dt1        dt2      val_count
1 2019-05-02 2019-08-30         3
2 2019-01-02 2019-04-24         3 
3 2019-06-02 2019-12-06         6 

我发现这个post 相关。

注意:我不想计算两个日期的月份之间的差异。

感谢您的建议。

【问题讨论】:

    标签: r date binning


    【解决方案1】:

    这很混乱,但如果你想计算几个月的最后日期在dt1dt2 之间有多少个,你可以试试

    library(lubridate)
    library(dplyr)
    
    fd <- paste0(lubridate::year(min(df$dt1, df$dt2)), "-02-01") %>% as.Date()
    
    ld <- paste0(lubridate::year(max(df$dt1, df$dt2))+1, "-01-01") %>% as.Date()
    x <- seq.Date(fd, ld, by = "month") - 1
    df %>%
      rowwise() %>%
      mutate(val_count = length(x[dt1 < x & x < dt2]))
    
      dt1        dt2        val_count
      <chr>      <chr>          <int>
    1 2019-05-02 2019-08-30         3
    2 2019-01-02 2019-04-24         3
    3 2019-06-02 2019-12-06         6
    

    &lt;&lt;= 的选择取决于您的目的。

    要获得dt1dt2 之间的总天数,

    df %>%
      rowwise() %>%
      mutate(val_count = length(x[dt1 < x & x < dt2])) %>%
      mutate(dd = as.Date(dt2) - as.Date(dt1))
    
      dt1        dt2        val_count dd      
      <chr>      <chr>          <int> <drtn>  
    1 2019-05-02 2019-08-30         3 120 days
    2 2019-01-02 2019-04-24         3 112 days
    3 2019-06-02 2019-12-06         6 187 days
    

    添加

    df %>%
      rowwise() %>%
      mutate(val_count = length(x[dt1 < x & x < dt2]),
             val_count = ifelse(val_count == 0, 1, val_count)) %>%
      mutate(dd = as.Date(dt2) - as.Date(dt1))
    
      dt1        dt2        val_count dd      
      <chr>      <chr>          <dbl> <drtn>  
    1 2019-05-02 2019-08-30         3 120 days
    2 2019-01-02 2019-04-24         3 112 days
    3 2019-06-02 2019-12-06         6 187 days
    4 2019-06-01 2019-06-02         1   1 days
    

    【讨论】:

    • 感谢您提供好的解决方案,您的代码运行良好。我想知道是否可以为日期在2019-06-022019-06-03 之间的情况添加快速修复以避免输出零?
    • @Vendetta 对不起。我无法理解你想要的是什么......你能解释一下吗?
    • 例如,有了这个数据df &lt;- data.frame(dt1 = c("2019-05-02", "2019-01-02", "2019-06-02", "2019-06-01"), dt2 = c("2019-08-30", "2019-04-24", "2019-12-06", "2019-06-02") ),我得到最后一行 val_count 为零。我想输出 1 而不是 0。
    • @Vendetta 我添加了上面的代码。请检查一下。
    【解决方案2】:

    上面的解决方案确实有点乱,只需要一个简单的oneliner就可以了

    df <- data.frame(dt1 = c("2019-05-02", "2019-01-02", "2019-06-02", "2019-06-01"), dt2 =   c("2019-08-30", "2019-04-24", "2019-12-06", "2019-06-02") )
    
    df %>%
      mutate(val_count = as.period(ymd(dt2) - ymd(dt1)) %/% months(1))
    
    #          dt1        dt2 val_count
    # 1 2019-05-02 2019-08-30         3
    # 2 2019-01-02 2019-04-24         3
    # 3 2019-06-02 2019-12-06         6
    # 4 2019-06-01 2019-06-02         0
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-04-05
      • 2018-02-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-02-03
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多