1
votes

Dans R: existe-t-il un moyen de signaler les plages de dates qui se chevauchent dans chaque groupe spécifique dans un tableau? (c'est-à-dire par ID du patient)

J'ai un ensemble de dates d'admission et de sortie à l'hôpital, ventilées par ID du patient. Il existe plusieurs plages de dates par ID et certaines se chevauchent. J'essaie de trouver un moyen d'indiquer quelles lignes contiennent des dates qui se chevauchent, de sorte que lorsque je calcule la «durée du séjour à l'hôpital», je ne compte pas deux fois.

Jusqu'à présent, j'ai créé une variable d'intervalle (date de sortie - date d'admission) et utilisé int_overlaps pour marquer les lignes où il y a des chevauchements. Cela a bien fonctionné, mais en plus de signaler les chevauchements, cela marque également les séjours consécutifs.

i.e. Je veux signaler:

Rester A: 2001-10-03 / 2001-10-06

Rester B: 2001-10-04 / 2001-10-11 p >

Mais je ne veux pas signaler:

Restez A: 2001-10-03 / 2001-10-06

Restez B: 2001-10-06 / 2001-10-11

Le code que j'ai utilisé a été copié d'une réponse ailleurs sur ce site, et je ne le comprends pas assez pour le modifier de la bonne manière (je suis presque totalement novice chez R ...!)

Ceci est un exemple simplifié du df et du code .... si quelqu'un peut me dire comment je pourrais le changer pour arrêter de signaler les séjours consécutifs, je l'apprécierais beaucoup !!!

ID <- c(1, 1, 2, 3, 3, 3, 4, 5, 5, 5, 5)
admdate <- c("2001-10-03", "2001-10-05", "2003-10-04", "2006-02-03", "2006-05-27", "2006-07-01", "2001-08-02", "2008-10-11", "2008-11-01", "2009-01-09", "2009-02-18")
dischdate <- c("2001-10-05", "2001-12-08", "2003-10-04", "2006-05-29", "2006-06-01", "2006-07-07", "2001-08-11", "2008-10-14", "2009-01-13", "2009-01-21", "2009-02-26")

HospAdms <- cbind(ID, admdate, dischdate)
HospAdms <- data.frame(ID, admdate, dischdate)

as_date(HospAdms$admdate)
as_date(HospAdms$dischdate)

HospAdms$Int <- interval(start=HospAdms$admdate, end=HospAdms$dischdate)

HospAdms$overlap <- unlist(tapply(HospAdms$Int,
                                 HospAdms$ID,
                                 function(x) rowSums(outer(x,x,int_overlaps))>1))

Dans le df que cet exemple de code produit, les deux premières lignes sont des séjours consécutifs mais elles sont marquées et je ne veux pas qu'elles le soient. J'espère que cela a du sens!

r

1 commentaires

3 Réponses :


0
votes

Est-ce que cela répond à votre question?

library(data.table)
admissions <- data.table(
  ID = c(1, 1, 2, 3, 3, 3, 4, 5, 5, 5, 5),
  admdate = c("2001-10-03", "2001-10-05", "2003-10-04", "2006-02-03", "2006-05-27", "2006-07-01", "2001-08-02", "2008-10-11", "2008-11-01", "2009-01-09", "2009-02-18"),
  dischdate = c("2001-10-05", "2001-12-08", "2003-10-04", "2006-05-29", "2006-06-01", "2006-07-07", "2001-08-11", "2008-10-14", "2009-01-13", "2009-01-21", "2009-02-26")
  )

# Non equi joins are only possible with numeric fields
admissions[,c('start','end'):=.(as.POSIXct(admdate),
                                as.POSIXct(dischdate))]

admissions[admissions, on = .(ID=ID,start<start,end>start ),nomatch = NULL]


4 commentaires

Merci pour cela - cela fonctionne parfaitement sur l'échantillon de données. Cependant, lorsque je l'essaye sur mon ensemble de données réel, il produit cette erreur: Join résulte en 22361 lignes; plus de 8188 = nrow (x) + nrow (i). Vérifiez les valeurs de clé en double dans i, chacune d'entre elles rejoignant le même groupe dans x encore et encore. Si cela vous convient, essayez par = .EACHI d'exécuter j pour chaque groupe afin d'éviter une allocation importante. Si vous êtes sûr de vouloir continuer, relancez avec allow.cartesian = TRUE. Sinon, recherchez ce message d'erreur dans la FAQ, le Wiki, le débordement de pile et l'outil de suivi des problèmes data.table pour obtenir des conseils.


J'ai essayé de le relancer avec allow.cartesian = TRUE et il a signalé un chevauchement pour chaque ligne. Des idées seraient très appréciées?!


Désolé, j'ai oublié de mettre l'ID dans la jointure non-equi! Je viens de le modifier: pouvez-vous réessayer?


Ça marche!! Incroyable, merci beaucoup. J'ai passé SI LONGTEMPS à essayer de résoudre ce problème, je suis très reconnaissant, haha!



0
votes

Cette approche data.table vous donnera la durée totale de séjour pour chaque ID , en tenant compte des lacunes et des chevauchements.

Avec seq.Date vous créez une séquence de dates individuelles de l'admission à la sortie, regroupées par ID .

uniqueN vous donnera des dates uniques à travers les dates de séquence pour éviter le double comptage.

   ID LOS
1:  1  67
2:  2   1
3:  3 126
4:  4  10
5:  5  95

Sortie

library(data.table)

setDT(HospAdms)[, .(dates = seq.Date(admdate, dischdate, 'day')) , by = .(ID, 1:nrow(HospAdms))
  ][, .(LOS = uniqueN(dates)), by = ID][]


0 commentaires

0
votes

Je pense que c'est ce que vous recherchez. Comme vous pouvez le voir, les périodes avec une date de début à une date de fin ne sont pas jointes, tandis que les périodes qui se chevauchent «réelles» sont jointes (par ID)

input

library( data.table )
library( intervals )
#make it a data.table
setDT(HospAdms)
#add time to dates, and since intervals-package can only 
#  handle numeric intervals, convert the date to numeric
HospAdms[, admdate := as.numeric(as.Date(admdate)) ]
HospAdms[, dischdate := as.numeric(as.Date(dischdate)) ]
#custom function for createing intervals
myfun <- function( y ) {
  data.table::as.data.table( 
    intervals::interval_union(
      intervals::Intervals( as.matrix( y ), 
                            closed = c(FALSE, FALSE) ),  # <--!! the reason why 
                                                         #       matching start-end 
                                                         #       intervals are 
                                                         #       NOT joined
      check_valid = TRUE ),
  )
}

# crate the final output
answer <- HospAdms[, myfun( .SD ), by = .(ID)]
#set numeric intervals back to dates
cols <- c("V1","V2")
answer[, (cols) := lapply( .SD, as.Date, origin = "1970-01-01" ), .SDcols = cols ]
#set colnumn names
setnames(answer, cols, c("admdate", "dischdate") )
#tadaaah
answer


1 commentaires

Merci pour cela. Cependant, je ne cherche pas à rejoindre les plages de dates (car elles peuvent représenter les informations dont j'ai besoin, telles que les transferts vers d'autres services), juste pour ajouter une autre colonne pour signaler les chevauchements. Si vous pouvez aider, je l'apprécierais vraiment!