一种将长格式的连续开始日期和停止日期重新编码为一个向量的方法

时间:2019-07-08 14:58:04

标签: r data-manipulation

我有很长的数据,人们会在一个位置上停留数周,但是有些条目代表一次逗留,而其他条目则代表他们“重新填写”注册的连续逗留。

我想确定一种重新编码数据的方法,以使每行仅代表一个人一个住所,将单个住所与多个条目折叠成一行。

我想通过将每个实例的真实开始和结束日期拖入一行来实现此目的。

问题在于,除了先前的结束日期等于后续的开始日期之外,我们无法将这些停留分组。实际停留的次数和单次停留的多次入境次数因人而异。

这是数据外观的一个示例:

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来解决此问题-我一直都在尝试这两种方法,但是一直陷于困境,尤其是因为我缺少一些结束日期。

1 个答案:

答案 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