2016-12-22 1 views
1

У меня есть два кадра данных следующим образом. Они имеют неравную длину:Определить наличие и степень перекрытия диапазонов дат по идентификационному номеру - два кадра данных

library(lubridate) 

id <- c(1, 2, 2, 2, 2, 3, 4, 4, 6, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 
    10, 10, 10, 11, 11, 12, 13, 14, 15, 15, 5451396, 5451396, 5451396, 5451396, 5451396) 
admDt <- ymd(c("2000-02-24", "2000-04-30", "2000-06-06", "2001-01-29", "2004-06-10", "2001-05-21", 
      "2000-01-25", "2000-04-18", "2000-01-14", "1991-10-06", "1992-02-25", "2000-05-17", 
      "2003-06-06", "2009-02-16", "2000-01-23", "2000-03-10", "2000-04-05", "2000-06-16", 
      "2000-07-04", "2000-07-27", "2001-01-19", "2002-08-16", "2002-09-19", "2004-04-17", 
      "2005-08-02", "2005-09-21", "2006-07-10", "2000-02-24", "2000-05-05", "2000-08-29", 
      "2001-01-24", "2000-01-27", "2000-03-09", "2000-04-15", "2000-03-20", "2002-11-13", 
      "2000-06-28", "2000-07-02", "2000-06-13", "1999-12-27", "2008-09-10", "2000-04-09", 
      "2000-06-01", "2002-11-25", "2006-08-04", "2006-10-07")) 
sepDt <- ymd(c("2000-02-25", "2000-05-25", "2000-06-06", "2001-02-15", "2004-07-12", "2001-06-01", 
      "2000-01-31", "2000-04-20", "2000-01-31", "1991-11-07", "1992-03-26", "2000-05-31", 
      "2003-06-17", "2009-02-23", "2000-03-06", "2000-03-17", "2000-04-06", "2000-06-28", 
      "2000-07-17", "2000-07-31", "2002-04-19", "2002-09-11", "2003-05-06", "2004-05-03", 
      "2005-08-31", "2006-05-29", "2009-06-19", "2000-03-09", "2000-05-06", "2000-09-12", 
      "2001-01-24", "2000-02-15", "2000-03-17", "2000-04-16", "2000-04-20", "2002-12-05", 
      "2000-07-27", "2000-08-15", "2000-06-22", "2000-02-12", "2008-09-17", "2000-05-26", 
      "2000-08-29", "2003-02-24", "2006-09-22", "2006-11-10")) 
adm <- data.frame(id, admDt, sepDt) 

id <- c(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 5451396) 
birthDt <- ymd(c("1971-07-22", "1982-08-09", "1976-01-30", "1972-02-03", "1958-05-26", "1979-05-24", 
      "1971-11-03", "1980-02-05", "1978-06-08", "1969-10-14", "1962-01-01", "1977-03-09", 
      "1952-01-24", "1974-12-16", "1956-05-05", "1963-07-16")) 
dxDt <- ymd(c("2000-02-24", "2000-04-30", "2000-03-03", "2000-01-31", "2000-06-20", "2000-12-13", 
      "2000-05-14", "2000-01-23", "2000-03-09", "2000-02-15", "2000-05-01", "2000-06-30", 
      "2000-08-15", "2000-06-22", "2000-01-27", "2000-06-01")) 
admPreDx <- c("No", "No", "No", "Yes", "No", "No", "No", "No", "Yes", "Yes","Yes", "Yes", "Yes", 
      "Yes", "Yes", "Yes") 
admPreDxNbr <- c(0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1) 
admPreDxDur <- c(0, 0, 0, 6, 0, 0, 0, 0, 14, 19, 20, 2, 31, 9, 31, 25) 
admPostDx <- c("Yes", "Yes", "No", "No", "No", "No", "Yes", "Yes", "No", "Yes", "No", "Yes", "No", 
      "No", "Yes", "Yes") 
admPostDxNbr <- c(1, 1, 0, 0, 0, 0, 1, 1, 0, 1, 0, 1, 0, 0, 1, 3) 
admPostDxDur <- c(1, 25, 0, 0, 0, 0, 14, 31, 0, 6, 0, 27, 0, 0, 16, 31) 
admDx <- data.frame(id, birthDt, dxDt, admPreDx, admPreDxNbr, admPreDxDur, admPostDx, admPostDxNbr, 
       admPostDxDur) 


> head(adm) 
    id  admDt  sepDt 
1 1 2000-02-24 2000-02-25 
2 2 2000-04-30 2000-05-25 
3 2 2000-06-06 2000-06-06 
4 2 2001-01-29 2001-02-15 
5 2 2004-06-10 2004-07-12 
6 3 2001-05-21 2001-06-01 

> head(admDx) 
    id birthDt  dxDt admPreDx admPreDxNbr admPreDxDur admPostDx admPostDxNbr admPostDxDur 
1 1 1971-07-22 2000-02-24  No   0   0  Yes   1   1 
2 2 1982-08-09 2000-04-30  No   0   0  Yes   1   25 
3 3 1976-01-30 2000-03-03  No   0   0  No   0   0 
4 4 1972-02-03 2000-01-31  Yes   1   6  No   0   0 
5 5 1958-05-26 2000-06-20  No   0   0  No   0   0 
6 6 1979-05-24 2000-12-13  No   0   0  No   0   0 

Фактические наборы данных составляют от 10 000 до 1 000 000+ строк.

Каждый ряд в adm относится к дискретному госпитализации. Примечание: id - идентификационный номер пациента, а admDt и sepDt относятся к датам поступления и выписки, соответственно. У некоторых пациентов есть множественные поступления.

Каждая строка в admDx относится к одному пациенту: id это идентификационный номер пациента (в соответствии с информацией, представленной в adm), в то время как birthDt и dxDt являются роды и диагностика даты пациента, соответственно.

Я проводил анализ продольных/временных рядов и хотел бы определить, были ли пациенты или не были госпитализированы в разные периоды времени до и после диагностики. Для краткости этот вопрос касается одного месяца до и после постановки диагноза. В идеале, я хотел бы:

  • Создать дихотомичный переменную («Да»/«Нет»), что указывает на потраченный ли данный пациент время в больнице в течение периода времени (то есть, меня не беспокоит, если они были допускается до наступления периода времени или если они были выписаны после смещения периода времени)
  • Рассчитать количество случаев, когда каждый пациент находился в больнице в течение периода времени
  • Рассчитать продолжительность (количество дней) каждого пациент находился в больнице в течение периода времени

Я рассмотрел несколько сообщений за несколько дней (например, R Time periods overlapping, Join dataframes by id and overlapping date range, how to show an event happened between two dates in R); однако ни один из них, кажется, не объединяет три аспекта, которые меня интересуют (расчет времени между перекрывающимися датами, несколькими кадрами данных, «группой» [или отдельным человеком]).

Я новичок в R и у меня мало опыта с циклами и более продвинутыми формулами. Похоже, что можно использовать foverlaps, lubridate или %overlaps% от "DescTools"; однако я не уверен, как построить соответствующие формулы.

Любая помощь была бы принята с благодарностью!

EDIT # 1:

Хотя @ sirallen-х предложений работал на определенный период времени, в приведенном примере, sum(pmin(dxDt, sepDt) - pmax(admDt, dxDt)), by = "id" вернулся неточные значения в моем реальных данных (например, у больных с множественными госпитализаций длительностью один день [» 2000-01-25 "-" 2000-01-26 "], как сообщается, провел в больнице нулевые дни. Мне это кажется странным, поскольку код, похоже, используется для ответа на подобные примеры. Означает ли этот вопрос тот факт, что У меня есть несколько перекрывающихся диапазонов дат для этих пациентов? Кроме того, как отметил @sirallen, код не выделял, когда пациенты имели одно или более одного приема в течение периода времени.

ниже код предоставляется более прямой путь к первым двум частям моего вопроса, путем определения) ли провел пациент время в больнице, и б) число госпитализаций:

library(data.table) 
setDT(adm) 
setDT(admDx)[, (4:9) := NULL] 

#Period bounds 
admDx[, `:=`(dxDtN1 = dxDt %m-% months(1), dxDtP1 = dxDt %m+% months(1))] 

#Hospitalised in the month preceding diagnosis 
admDx <- adm[admDx, on = .(id, admDt < dxDt, sepDt > dxDtN1), .N, by = .EACHI] 
admDx[, `:=` (admPreDx = factor(ifelse(N > 0, "Yes", "No")))] 

Однако, рмин код/​​ртах все еще не работает, возвращая отрицательные значения:

admDx[, `:=` (birthDt = birthDt, dxDt = dxDt, dxDtN1 = dxDt %m-% months(1), dxDtP1 = dxDt %m+% months(1))] 
admDx[, `:=` (admPreDxDur=as.numeric(sum(pmin(dxDt, adm$sepDt) - pmax(dxDtN1, adm$admDt)))), by = "id"] 
admDx <- select(admDx, admPreDx, N, admPreDxDur) 


> head(admDx) 
    admPreDx N admPreDxDur 
1:  No 0  -28573 
2:  No 0  -27160 
3:  No 0  -28366 
4:  Yes 1  -29357 
5:  No 0  -26701 
6:  No 0  -28044 

EDIT # 2

После проверки что вопрос re: pmin/pmax может относиться к использованию > против >=: когда используется >, возвращается правильное значение Dur; однако, когда используется >=, Dur возвращает значение 0.

Как этот код можно настроить, чтобы я мог рассчитать количество дней до даты диагноза и включая дату диагноза?

+0

Вместо описания вашего ожидаемого результата, показывают его (убедитесь, что он отражает ваши примеры) – Sotos

+0

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

+0

Если вы хотите включить дату диагностики, просто добавьте '+ (dxDt <= sepDt)' для preDx ('+ (dxDt> = admDt)' для postDx) – sirallen

ответ

0

Мы можем сделать это с non-equi joins в data.table (> = v1.9.8):

library(data.table) 
setDT(adm) 
setDT(admDx)[, (4:9):= NULL] 

# period bounds 
admDx[, `:=`(dxDtLo=dxDt-31, dxDtHi=dxDt+31)] 

# hospitalized pre-dxnosis? 
admDx = adm[, .(id, admDt, sepDt, dxDt=admDt, dxDtLo=sepDt)][admDx, 
    on=.(id, dxDt < dxDt, dxDtLo > dxDtLo)] 
admDx[, admPreDx:= as.numeric(!is.na(admDt))] 
admDx[, `:=`(admPreDxNbr=sum(admPreDx), admPreDxDur=as.numeric(
    sum(pmin(dxDt,sepDt) - pmax(admDt,dxDtLo)))), by='id'] 
admDx[, c('admDt','sepDt'):= NULL] 

# hospitalized post-dxnosis? 
admDx = adm[, .(id, admDt, sepDt, dxDtHi=admDt, dxDt=sepDt)][admDx, 
    on=.(id, dxDtHi < dxDtHi, dxDt > dxDt)] 
admDx[, admPostDx:= as.numeric(!is.na(admDt))] 
admDx[, `:=`(admPostDxNbr=sum(admPostDx), admPostDxDur=as.numeric(
    sum(pmin(sepDt,dxDtHi) - pmax(dxDt,admDt)))), by='id'] 
admDx[, c('admDt','sepDt'):= NULL] 

admDx[is.na(admDx)] = 0 
admDx = unique(admDx)[, c('dxDtLo','dxDtHi'):= NULL] 

> admDx 
#   id  dxDt birthDt admPreDx admPreDxNbr admPreDxDur admPostDx admPostDxNbr admPostDxDur 
# 1:  1 2000-02-24 1971-07-22  0   0   0   1   1   1 
# 2:  2 2000-04-30 1982-08-09  0   0   0   1   1   25 
# 3:  3 2000-03-03 1976-01-30  0   0   0   0   0   0 
# 4:  4 2000-01-31 1972-02-03  1   1   6   0   0   0 
# 5:  5 2000-06-20 1958-05-26  0   0   0   0   0   0 
# 6:  6 2000-12-13 1979-05-24  0   0   0   0   0   0 
# 7:  7 2000-05-14 1971-11-03  0   0   0   1   1   14 
# 8:  8 2000-01-23 1980-02-05  0   0   0   1   1   31 
# 9:  9 2000-03-09 1978-06-08  1   1   14   0   0   0 
# 10:  10 2000-02-15 1969-10-14  1   1   19   1   1   8 
# 11:  11 2000-05-01 1962-01-01  1   1   20   0   0   0 
# 12:  12 2000-06-30 1977-03-09  1   1   2   1   1   27 
# 13:  13 2000-08-15 1952-01-24  1   1   31   0   0   0 
# 14:  14 2000-06-22 1974-12-16  1   1   9   0   0   0 
# 15:  15 2000-01-27 1956-05-05  1   1   31   1   1   16 
# 16: 5451396 2000-06-01 1963-07-16  1   1   25   1   1   31 
+0

Спасибо за ваша помощь. У меня были некоторые трудности с аспектом pmin/pmax кода. Какое влияние будет иметь уникальный фильтр на столбцах Nbr и Dur? –

+0

Можете ли вы обновить свои данные образца с идентификатором, для которого приведен код выше? Благодарю. Я думаю, что мой код будет генерировать повторяющиеся строки при наличии нескольких допущений; 'unique' избавится от этих – sirallen

+0

Несомненно! Я зайду на него сейчас –

Смежные вопросы