我有很长的数据,人们会在一个位置上停留数周,但是有些条目代表一次逗留,而其他条目则代表他们“重新填写”注册的连续逗留。
我想确定一种重新编码数据的方法,以使每行仅代表一个人一个住所,将单个住所与多个条目折叠成一行。
我想通过将每个实例的真实开始和结束日期拖入一行来实现此目的。
问题在于,除了先前的结束日期等于后续的开始日期之外,我们无法将这些停留分组。实际停留的次数和单次停留的多次入境次数因人而异。
这是数据外观的一个示例:
ID Start_Date End_Date
1 05/06/18 05/10/18
1 05/10/18 05/14/18
1 05/14/18 05/25/18
1 06/28/19 07/02/19
1 07/02/19 07/08/19
2 04/20/18 04/23/18
2 07/20/18 07/25/18
2 07/26/18 07/30/18
3 05/14/17 05/29/17
我希望它看起来像:
ID Start_Date End_Date
1 05/06/18 05/25/18
1 06/28/19 07/08/19
2 04/20/18 04/23/18
2 07/20/18 07/30/18
3 05/14/17 05/29/17
我愿意使用R或SPSS来解决此问题-我一直都在尝试这两种方法,但是一直陷于困境,尤其是因为我缺少一些结束日期。
答案 0 :(得分:1)
我试图通过一个aggregate()
调用来完成所有操作,但是有点混乱。更容易split()
– lapply()
。
rr <- read.table(text="
ID Start_Date End_Date
1 05/06/18 05/10/18
1 05/10/18 05/14/18
1 05/14/18 05/25/18
1 06/28/19 07/02/19
1 07/02/19 07/08/19
2 04/20/18 04/23/18
2 07/20/18 07/25/18
2 07/26/18 07/30/18
3 05/14/17 05/29/17",
stringsAsFactors=FALSE, header=TRUE)
# Convert to Date class
rr[,2:3] <- lapply(rr[,2:3], as.Date, format="%m/%d/%y")
# Group rows that have consecutive time periods
consec <- cumsum(c(FALSE, head(rr[,3], -1) - tail(rr[,2], -1) != 0))
# Or group rows that have time periods 0 or 1 apart
consec <- cumsum(c(FALSE, !(tail(rr[,2], -1) - head(rr[,3], -1)) %in% c(0, 1)))
# Combine with ID
consec <- paste(rr$ID, consec, sep=".")
# Split rows by group
sp <- split(rr, consec)
# Take the top-left and bottom-right value of each data.frame fragment
rrl <- lapply(sp,
function(x) {
data.frame(ID=x[1, 1], Start_Date=x[1, 2], End_Date=x[nrow(x), 3])
}
)
# Rejoin vertically
rr2 <- do.call(rbind, rrl)
rr2
# ID Start_Date End_Date
# 1.0 1 2018-05-06 2018-05-25
# 1.1 1 2019-06-28 2019-07-08
# 2.2 2 2018-04-20 2018-04-23
# 2.3 2 2018-07-20 2018-07-30
# 3.4 3 2017-05-14 2017-05-29