我有一些数据,其中包括对特定状态适用于个人的时间范围的观察。一个人在给定的时间可以具有多种状态,或者根本没有任何统计信息(在这种情况下将没有观察值)。
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,但它们通常涉及将重叠的区域折叠成一个超级区域,而不是将它们分解成不同的子区域。
任何帮助或想法将不胜感激。谢谢。
答案 0 :(得分:2)
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'))