首页 > 解决方案 > 根据R中的分组变量为连续天的特定序列创建ID

问题描述

对于国家日级别的事件列表,我们希望为特定国家的连续几天创建一个唯一 ID(如果一个国家/地区连续两天或更多天的事件 --> 创建唯一 ID) ,以便我最终可以将数据框简化为特定的事件序列,而不是事件日期。

我没有设法根据事件的顺序汇总数据。我相信这个响应是相似的(创建符合给定标准的连续天组)但是它是在 SQL 中。

数据格式如下:

country <- c("Angola","Angola","Angola","Angola","Angola", "Benin","Benin","Benin","Benin","Benin","Benin")
event_date <- as.Date(c("2017-06-16", "2017-06-17", "2017-06-18", "2017-08-22", "2017-08-23", "2019-04-18", "2019-04-19", "2019-04-20", "2018-03-15", "2018-03-16", "2016-03-17"))

mydata <- data.frame(country, event_date)

在输出中,我希望有一个新列,其 ID 对一个国家/地区的每个事件系列都是唯一的:

seq.ID <- c(1,1,1,2,2,3,3,3,4,4,4)

mydata2 <- data.frame(country, event_date, seq.ID)

所以最终,我可以将数据减少到国家和事件序列的级别:

mydata3 <- mydata2[!duplicated(mydata2$seq.ID),]

标签: rlubridate

解决方案


尝试:

library(dplyr)

mydata %>%
  group_by(country) %>%
  distinct(seq.ID = cumsum(event_date != lag(event_date, default = first(event_date)) + 1L)

输出:

# A tibble: 5 x 2
# Groups:   country [2]
  seq.ID country
   <int> <fct>  
1      1 Angola 
2      2 Angola 
3      1 Benin  
4      2 Benin  
5      3 Benin 

您还可以使用.keep_all参数 indistinct并保留每个序列的第一个日期:

mydata %>%
  group_by(country) %>%
  distinct(seq.ID = cumsum(event_date != lag(event_date, default = first(event_date)) + 1L),
           .keep_all = TRUE)

# A tibble: 5 x 3
# Groups:   country [2]
  country event_date seq.ID
  <fct>   <date>      <int>
1 Angola  2017-06-16      1
2 Angola  2017-08-22      2
3 Benin   2019-04-18      1
4 Benin   2018-03-15      2
5 Benin   2016-03-17      3

如果需要具有不同序列 ID 的非聚合输出,您可以执行以下操作:

mydata %>%
  mutate(
    seq.ID = cumsum(
      (event_date != lag(event_date, default = first(event_date)) + 1L) |
        country != lag(country, default = first(country))
    )
  )

   country event_date seq.ID
1   Angola 2017-06-16      1
2   Angola 2017-06-17      1
3   Angola 2017-06-18      1
4   Angola 2017-08-22      2
5   Angola 2017-08-23      2
6    Benin 2019-04-18      3
7    Benin 2019-04-19      3
8    Benin 2019-04-20      3
9    Benin 2018-03-15      4
10   Benin 2018-03-16      4
11   Benin 2016-03-17      5

请注意,您的 last 中有一个错字event_date,这就是为什么输出与您想要的输出不对应 100% 的原因。


推荐阅读