分组连续周数

时间:2019-06-04 01:34:43

标签: r data.table

如何从组中找到连续的周数,但是从数据集中的最大日期开始计算?

说我有这个数据框:

  id       Week
1   A  2/06/2019
2   A 26/05/2019
3   A 19/05/2019
4   A 12/05/2019
5   A  5/05/2019
6   B  2/06/2019
7   B 26/05/2019
8   B 12/05/2019
9   B  5/05/2019
10  C 26/05/2019
11  C 19/05/2019
12  C 12/05/2019
13  D  2/06/2019
14  D 26/05/2019
15  D 19/05/2019
16  E  2/06/2019
17  E 19/05/2019
18  E 12/05/2019
19  E  5/05/2019

我想要的输出是:

id count
1:  A     5
2:  B     2
3:  D     3
4:  E     1

我目前正在将日期转换为要获取订购号的因子,并对照根据每个组中的行数创建的参考号。

library(data.table)
df <- structure(list(id = structure(c(1L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 
                                      2L, 3L, 3L, 3L, 4L, 4L, 4L, 5L, 5L, 5L, 5L), 
                                    .Label = c("A", "B", "C", "D", "E"), class = "factor"), 
                     Week = structure(c(3L, 4L, 2L, 1L, 5L, 3L, 4L, 1L, 5L, 4L, 2L, 1L, 3L, 4L, 2L, 3L, 2L, 1L, 5L), 
                                      .Label = c("12/05/2019", "19/05/2019", "2/06/2019", "26/05/2019", "5/05/2019"), class = "factor")), 
                class = "data.frame", row.names = c(NA, -19L))
dt <- data.table(df)
dt[, Week_no := as.factor(as.Date(Week, format = "%d/%m/%Y"))]
dt[, Week_no := factor(Week_no)]
dt[, Week_no := as.numeric(Week_no)]

max_no <- max(dt$Week_no)
dt[, Week_ref := max_no:(max_no - .N + 1), by = "id"]
dt[, Week_diff := Week_no - Week_ref]
dt[Week_diff == 0, list(count = .N), by = "id"]

3 个答案:

答案 0 :(得分:1)

dplyr解决方案的道歉,但我认为使用data.table可以更简洁地实现类似的方法。

library(dplyr)
df$Week = lubridate::dmy(df$Week)
df %>%
  group_by(id) %>%
  arrange(id, Week) %>%
  # Assign group to each new streak
  mutate(new_streak = cumsum(Week != lag(Week, default = 0) + 7)) %>%
  add_count(id, new_streak) %>%
  slice(n()) # Only keep last week

答案 1 :(得分:1)

这是执行此操作的一种方法:

dt <- dt[, Week := as.Date(Week, format = "%d/%m/%Y")]
ids_having_max <- dt[.(max(Week)), id, on = "Week"]
dt <- dt[.(ids_having_max), on = "id"
         ][order(-Week), .(count = sum(rleid(c(-7L, diff(Week))) == 1)), by = "id"]

将其分解为步骤:

我们将Week保留为日期,因为它已经可以比较了, 您可以减去日期以获得时差。

然后我们获得整个表中包含最大日期的所有id。 这是使用secondary indices

我们再次使用二级索引来过滤掉先前结果 部分中的iddt[.(ids_having_max), on = "id"部分)。

最后一帧很棘手。 我们按id分组,并确保行按Week降序排列。 那么逻辑如下。

连续几个星期后, 根据所选的排序,diff(Week)始终为-7。 计算diff会返回一个较短的向量,因为第一个结果是通过从第二个元素减去第一个输入元素来计算的, 因此我们在前面加上-7以确保它是rleid输入中的第一个元素。

使用rleid,我们将第一个-7分配为1,并保持1,直到看到与-7不同的值。 不同的方式意味着几周不再连续。 sum(rleid(c(-7L, diff(Week))) == 1)将仅返回rleid等于1的行数。

B的最后一部分的示例:

  • 差异:-7, -14, -7
  • 在加-7之前:-7, -7, -14, -7
  • rleid之后:1, 1, 2, 3
  • 从前一个,两个有一个rleid == 1

答案 2 :(得分:0)

因此,我建议按如下所示将数据列的格式转换为显示周数"%W"

dt[, Week_no := format(as.Date(Week, format = "%d/%m/%Y"),"%W")]

然后找到每个id值的唯一星期数

dt[,(length(unique(Week_no))),by="id"]

完全公开

我意识到,当我运行此命令时,我得到的表与您提供的表不同,因为R用给定年份的周数来计数周数。

如果这不能回答您的问题,请告诉我,我可以尝试更新