2010-11-09 8 views
2

J'ai un ensemble de données d'admission à l'hôpital que je dois traiter, je suis bloqué en essayant de boucler les données et ramasser les trucs que je besoin, voici l'exemple:traitement des données d'admission à l'hôpital en utilisant R

Date Ward 
1 A 
2 A 
3 A 
4 A B 
5 A 
6 A 
7 A C 
8  C 
9  C 
10  C 

Et je leur dois être transformé en:

Ward Adm_Date Dis_Date 
A 1  4 
B 4  4 
A 4  7 
C 7  10 

pour le mettre dans la phrase, c'est un dossier d'admission du patient X qui:

  • aller au service A du jour 1 au jour 4
  • aller au service B (peut-être un service de soins intensifs) pendant moins d'un jour le jour 4, et retourner au service A ce jour
  • rester dans le service A du jour 4 au jour 7
  • mouvement pour éloigner C de service A partir du jour 7 et de rester dans le quartier C jusqu'à ce jour 10

Je pense à l'aide ddply en filtrant la salle, mais il n'est pas correct puisque B sera "omis" et la période de temps pour A n'est pas décomposée en 2 parties.

Des suggestions? Merci!

+0

Quelle est ici la variable 'Ward'? Une chaîne de caractères? À quel point cela peut-il être complexe - plus de deux services par jour? Si vous aviez trois codes de salle - disons «A D F» où vous avez «A B», comment sauriez-vous si le patient est allé en D ou F en premier? Est ce que c'est important? C'est faisable mais pourrait juste avoir besoin d'une boucle de suivi de l'endroit où le patient est à chaque itération. En outre, ce n'est pas le lupus. – Spacedman

+0

ward est une chaîne de caractères, et je ne pense pas qu'il puisse y avoir plus de 2 salles par jour, et oui, ce n'est pas le lupus. ;) actuellement j'utilise ddply et loop pour cela, mais c'est un peu lent (j'ai des dossiers d'admission de 8000 patients du 1/1/2009 au 31/9/2010) – lokheart

+1

En esquissant une réponse il y a une ambiguïté dans vos données que j'ai trouvé quand ma solution ne correspondait pas à la vôtre! Vous dites que si le code est "A B" puis "A" alors ils sont dans B pour moins d'un jour. Mais que se passe-t-il s'ils sont dans B pendant exactement un jour? Serait-il alors "A" "B" "A"? Le problème que j'ai dans mon code est que vous ne savez pas si le patient revient à "A" quand vous voyez "A B" jusqu'à ce que vous vérifiez l'enregistrement suivant. Et cela affecte le code, parce que vos données d'admission pour A dans la ligne 3 de votre sortie sont 4, et non 5 ce qui est ce que je m'attendrais ... Peut-être que c'est le lupus. – Spacedman

Répondre

1
dat <- data.frame(Date=1:10,Ward=c(rep("A",3),"A B",rep("A",2),"A C",rep("C",3))) 
dat$Ward <- as.character(dat$Ward) 

# Change data to a "long" format 

Date2 <- rep(dat$Date,nchar(gsub(" ","",dat$Ward))) 
Ward2 <- unlist(strsplit(dat$Ward," ")) 
dat2 <- data.frame(Date=Date2,Ward=Ward2) 
dat2$Ward <- as.character(dat2$Ward) # pesky factors! 

# Create output 

Ward3 <- unlist(strsplit(gsub("(\\w)\\1+","\\1",paste(dat2$Ward,collapse="")),"")) 

#helper function to find lengths of repeated characters, probably a better way of doing this 

repCharLength <- function(str) 
{ 
    out <- numeric(0) 
    tmp <- 1 
    for (i in 2:length(str)) 
     { 
     if (str[i]!=str[i-1]) 
      {out<-c(out,tmp) 
      tmp<-1} 
     else 
     tmp <- tmp+1 
     } 
    return(c(out,tmp)) 
} 

stays <- repCharLength(dat2$Ward) 

Adm_Date <- c(1,dat2$Date[cumsum(stays)[1:(length(stays)-1)]]) 
Dis_Date <- dat2$Date[cumsum(stays)] 
dat3 <- data.frame(Ward=Ward3,Adm_Date=Adm_Date,Dis_Date=Dis_Date) 

> dat3 
    Ward Adm_Date Dis_Date 
1 A  1  4 
2 B  4  4 
3 A  4  7 
4 C  7  10 

Un peu plus impliqué que je pensais d'abord, et il y a probablement une meilleure façon d'obtenir les longueurs de séjour que vous utilisez la fonction d'aide je l'ai écrit, mais cela semble faire le travail.

Modifier

À la lumière du commentaire de Spacedman, il y a une fonction de bibliothèque pour calculer Ward3 et stays:

Ward3 <- rle(dat2$Ward)$values 
stays <- rle(dat2$Ward)$lengths 
+0

Vous voulez rle (foo) $ longueurs pour repCharLength (foo). Ma semi-solution que j'ai mentionnée plus tôt était assez similaire, je n'ai pas pris la peine de la poster car elle était a) un peu fausse, et b) je savais que quelqu'un posterait une bonne solution avant de revenir à un ordinateur ... :) – Spacedman

+0

@Spacedman Merci, je pensais qu'il y aurait une meilleure façon de le faire. Je vois qu'il sort aussi la commande de la salle trop donc pas besoin de s'embêter avec la version compliquée de regex :) – James

0

Ce n'est pas une réponse complexe, mais vous pouvez transformer vos données

X <- data.frame(
    Date=1:10, 
    Ward=c("A","A","A","A B","A","A","A C","C","C","C"), 
    stringsAsFactors=FALSE 
) 

w <- strsplit(X$Ward," +") 
n <- sapply(w, length) 
X_mod <- data.frame(
    Date = rep(X$Date, n), 
    Ward = unlist(w, FALSE, FALSE) 
) 

Avec X_mod vous pouvez écrire solution vectorisée (= rapide). Pour commencer with(X_mod, c(0,cumsum(Ward[-1]!=Ward[-length(Ward)]))) vous donne l'ID de la visite.