Способ перекодирования последовательных начальных и конечных дат в длинном формате в один вектор - PullRequest
1 голос
/ 08 июля 2019

У меня есть длинные данные о том, что люди остаются в каком-то месте в течение нескольких недель, но некоторые записи представляют собой одно пребывание, а другие представляют последовательные пребывания, когда они "повторно повышают" свою регистрацию.

Я хочу определить способ перекодирования данных таким образом, чтобы каждая строка представляла только одно пребывание на человека, сворачивая одно пребывание с несколькими записями в одном ряду.

Я бы хотел сделать это, вытащив истинную дату начала и окончания в одну строку для каждого экземпляра.

Проблема в том, что у нас нет способа сгруппировать это, за исключением случаев, когда предыдущая дата окончания совпадает с последующей датой начала. Количество истинных пребываний и количество многократных въездов за одно пребывание варьируются в широких пределах на человека.

Это пример того, как выглядят данные:

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 Ответ

1 голос
/ 08 июля 2019

Я пытался сделать все это за один 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
...