【问题标题】:Grouping data.table by date sets按日期集分组 data.table
【发布时间】:2021-01-15 20:15:18
【问题描述】:

我有一个数据集查看一段时间内的交易,我正在尝试识别每个 ID 的交易周期。数据的基本示例如下所示。

# id       date
# 1  2018-02-01
# 1  2018-03-01
# 1  2018-04-01
# 1  2018-05-01
# 1  2018-06-01
# 1  2018-06-01
# 2  2018-02-01
# 2  2018-03-01
# 2  2018-05-01
# 2  2019-01-01
# 2  2019-02-01
# 2  2020-06-12
# 2  2020-07-13
# 2  2020-08-11

我想要做的是根据先前记录日期的接近程度对数据进行分组。因此,如果id 的间隔不超过 3 个月,他们将获得相同的组号。我已经整理了一个示例,说明期望的结果是什么样的。

# id       date group
# 1  2018-02-01     1
# 1  2018-03-01     1
# 1  2018-04-01     1
# 1  2018-05-01     1
# 1  2018-06-01     1
# 1  2018-06-01     1
# 2  2018-02-01     1
# 2  2018-03-01     1
# 2  2018-05-01     1
# 2  2019-01-01     2
# 2  2019-02-01     2
# 2  2020-06-12     3
# 2  2020-07-13     3
# 2  2020-08-11     3

所以我尝试考虑使用rleid() 或使用shift() 向前或向后看的解决方案,但无法为此找到合适的解决方案。我确实想知道其中一些是否归结为缺乏 R 词汇,所以任何想法都将不胜感激。

【问题讨论】:

  • 可以setDT(df)[, group := c(0, cumsum((diff(month(date)) + diff(year(date)) * 12) > 3)) + 1] 或者你如果你真的不关心精确度,可以只做df[, group := c(0, cumsum(diff(date) > 90)) + 1]df[, group := c(0, cumsum(`units<-`(diff(date), "weeks") > 13)) + 1]
  • 数据 >90 版本很不错。 cumsum 绝对是一种享受。我试过ifelse(),但效果不太好,但这很棒。谢谢!

标签: r date data.table


【解决方案1】:

当当前日期距离上一个日期超过 3 个月时,您可以增加每个 id 中的 group 值。

library(dplyr)
library(lubridate)

df %>%
    group_by(id) %>%
    mutate(group = cumsum((date %m-% months(3)) > 
                           lag(date, default = first(date))) + 1)

#      id date       group
#   <int> <date>     <dbl>
# 1     1 2018-02-01     1
# 2     1 2018-03-01     1
# 3     1 2018-04-01     1
# 4     1 2018-05-01     1
# 5     1 2018-06-01     1
# 6     1 2018-06-01     1
# 7     2 2018-02-01     1
# 8     2 2018-03-01     1
# 9     2 2018-05-01     1
#10     2 2019-01-01     2
#11     2 2019-02-01     2
#12     2 2020-06-12     3
#13     2 2020-07-13     3
#14     2 2020-08-11     3

data.table

library(data.table)
setDT(df)[, group := cumsum((date %m-% months(3)) > 
                             shift(date, fill = first(date))) + 1, id]

数据

df <- structure(list(id = c(1L, 1L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 
2L, 2L, 2L, 2L), date = structure(c(17563, 17591, 17622, 17652, 
17683, 17683, 17563, 17591, 17652, 17897, 17928, 18425, 18456, 
18485), class = "Date")), row.names = c(NA, -14L), class = "data.frame")

【讨论】:

    【解决方案2】:

    使用ave + cumsum + diff 的基本 R 选项

    within(
      df,
      group <- ave(as.numeric(date), id, FUN = function(x) cumsum(c(0, diff(x) > 30.42 * 3)) + 1)
    )
    

    给了

       id       date group
    1   1 2018-02-01     1
    2   1 2018-03-01     1
    3   1 2018-04-01     1
    4   1 2018-05-01     1
    5   1 2018-06-01     1
    6   1 2018-06-01     1
    7   2 2018-02-01     1
    8   2 2018-03-01     1
    9   2 2018-05-01     1
    10  2 2019-01-01     2
    11  2 2019-02-01     2
    12  2 2020-06-12     3
    13  2 2020-07-13     3
    14  2 2020-08-11     3
    

    【讨论】:

      猜你喜欢
      • 2019-04-03
      • 1970-01-01
      • 2016-10-06
      • 1970-01-01
      • 1970-01-01
      • 2011-02-19
      • 1970-01-01
      • 1970-01-01
      • 2021-06-09
      相关资源
      最近更新 更多