【问题标题】:Convert data of overlapping time ranges to data of distinct time ranges将重叠时间范围的数据转换为不同时间范围的数据
【发布时间】:2018-08-24 18:54:15
【问题描述】:

我的数据包含对个人特定状态应用的时间范围的观察。一个人在给定时间可以有多种状态,或者根本没有统计信息(在这种情况下,不会有观察)。

ID  STATUS START      END    
1   A      2013-03-07 2013-04-20
1   B      2013-04-10 2013-05-10
1   C      2013-04-16 2013-07-11
1   B      2013-07-25 2013-08-08
2   A      2013-09-10 2014-04-21
2   C      2013-12-27 2014-01-26
2   D      2014-04-28 2014-05-10
2   E      2014-05-11 2014-07-16

我想将其转换为一个数据框,该数据框包含不同的、不重叠的时段以及在这些时段内应用的所有状态。该示例的结果如下所示。

ID  STATUS START      END    
1   A      2013-03-07 2013-04-10
1   A,B    2013-04-10 2013-04-16
1   A,B,C  2013-04-16 2013-04-20
1   B,C    2013-04-20 2013-05-10
1   C      2013-05-10 2013-07-11
1   B      2013-07-25 2013-08-08
2   A      2013-09-10 2013-12-27
2   A,C    2013-12-27 2014-01-26
2   D      2014-04-28 2014-05-10
2   E      2014-05-11 2014-07-16

我的数据相当大,所以我努力寻找一种有效的方法来做到这一点。我发现了半相关的问题,例如here,但它们通常涉及将重叠区域折叠成一个超级区域,而不是将它们分解成不同的子区域。

任何帮助或想法将不胜感激。谢谢。

【问题讨论】:

  • 什么会准确定义周期?比如你如何确定一个时期是 2013-03-07 到 2013-04-16?
  • 作为起点,您可以将起点和终点连接成一个向量,然后按升序对它进行唯一排序,例如breakpoints <- sort(unique(c(dt$START, dt$END)))。然后创建一个新表,其中START = c(-Inf, breakpoints)END = c(breakpoints,Inf)。这将是您的一组不同的、不重叠的范围。
  • @bk18 在我拥有的数据中,一行定义了特定状态(例如状态 A)的不间断周期。因此,如果我处于状态 A 一个月,然后离开它一周,然后重新打开,这些将显示为两个单独的行。此外,可以同时存在其他状态,这些状态将由它们自己的行定义。

标签: r dataframe range overlap


【解决方案1】:
library(dplyr)

# Create all the possible date ranges
date_breaks <- sort(c(df$START, df$END))

# Build a data.frame with all possible combinations
df2 <- expand.grid(START = head(date_breaks, -1),
                   ID = unique(df$ID),
                   STATUS = unique(df$STATUS),
                   stringsAsFactors = F)
df2$END <- tail(date_breaks, -1)

# Join in original data and filter to where the start and end are in range
df2 %>%
    inner_join(df, by = c("ID", "STATUS")) %>%
    filter(START.y <= START.x, END.y >= END.x) %>%
    group_by(ID, START = START.x, END = END.x) %>%
    summarise(STATUS = paste(unique(STATUS), collapse = ', ')) %>% 
    select(ID, STATUS, START, END)

#  A tibble: 11 x 4
#  Groups:   ID, START [11]
#       ID STATUS  START      END       
#    <int> <chr>   <date>     <date>    
#  1     1 A       2013-03-07 2013-04-10
#  2     1 A, B    2013-04-10 2013-04-16
#  3     1 A, B, C 2013-04-16 2013-04-20
#  4     1 B, C    2013-04-20 2013-05-10
#  5     1 C       2013-05-10 2013-07-11
#  6     1 B       2013-07-25 2013-08-08
#  7     2 A       2013-09-10 2013-12-27
#  8     2 A, C    2013-12-27 2014-01-26
#  9     2 A       2014-01-26 2014-04-21
# 10     2 D       2014-04-28 2014-05-10
# 11     2 E       2014-05-11 2014-07-16

数据

df <- read.table(text = "ID  STATUS START      END    
                         1   A      2013-03-07 2013-04-20
                         1   B      2013-04-10 2013-05-10
                         1   C      2013-04-16 2013-07-11
                         1   B      2013-07-25 2013-08-08
                         2   A      2013-09-10 2014-04-21
                         2   C      2013-12-27 2014-01-26
                         2   D      2014-04-28 2014-05-10
                         2   E      2014-05-11 2014-07-16",
                 header = T,
                 colClasses = c('integer', 'character', 'Date', 'Date'))

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2022-09-24
    • 1970-01-01
    • 2018-03-03
    • 1970-01-01
    • 1970-01-01
    • 2023-04-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多