2010-11-09 2 views
2

У меня есть набор госпитализация данных, что мне нужно обрабатывать, я застрял при попытке цикла данные и подобрать материал, который мне нужен, вот пример:обработка данных больницы приема с использованием 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 

И мне нужно, чтобы они были преобразованы в:

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

Выражаясь в предложении, это прием запись пациента X, который:

  • перейдите в палату А с 1-го по 4-й день
  • перейдите в палату В (возможно, это отделение отделения интенсивной терапии) менее суток в день 4 и вернитесь в палату А в этот день
  • пребывание в палате А с 4-го дня 7-го дня
  • шаг, чтобы предотвратить C от прихода а с 7-го дня и пребывание в палате C до дня 10

Я имею в виду использование ddply путем фильтрации подопечного, но не в порядке, так как B будет «опущен», и период времени для A не разбивается на 2 части.

Любые предложения? Благодаря!

+0

Что переменная 'Ward' здесь? Строка символов? Насколько сложно это получить - более двух подопечных в день? Если у вас было три кода охраны - скажем, «A D F», где у вас есть «A B», как вы узнаете, первым ли пациент отправился в D или F? Это имеет значение? Это выполнимо, но может потребоваться только цикл, отслеживающий, где находится пациент на каждой итерации. Кроме того, это не волчанка. – Spacedman

+0

ward - это символьная строка, и я не думаю, что в день может быть больше двух подопечных, и да, это не волчанка. ;) В настоящее время я использую ddply и loop для этого, но он довольно медленный (у меня есть записи регистрации 8000 пациентов с 01.01.2009 по 31.09.2010) – lokheart

+1

Во время наброса ответа есть двусмысленность в ваших данных что я нашел, когда мое решение не совсем соответствовало вашим требованиям! Вы говорите, что если код «A B», а затем «A», то они находятся в B менее одного дня. Но что, если они находятся в Б ровно за один день? Затем будет ли он «A» «B» «A»? Проблема, которую я испытываю в своем коде, заключается в том, что вы не знаете, возвращается ли пациент к «А», когда вы видите «A B», пока не проверите следующую запись. И это влияет на код, потому что ваши данные для входа в A в строке 3 вашего вывода составляют 4, а не 5, что я бы ожидал .... Возможно, это волчанка. – Spacedman

ответ

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 

немного сложнее, чем я думал, что первый, и, вероятно, лучший способ получить длину пребывания, чем с помощью вспомогательной функции, которую я написал, но это, кажется, чтобы сделать работу.

Редактировать

В свете комментария Spacedman, есть функция библиотеки для расчета Ward3 и stays:

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

Вы хотите rle (foo) $ lengths для repCharLength (foo). Мое полу-решение, о котором я упоминал ранее, было довольно похоже, я не стал его размещать, поскольку он был a) немного неправильным, и b) я знал, что кто-то опубликует надлежащее решение к тому времени, когда я вернусь на компьютер ... :) – Spacedman

+0

@Spacedman Спасибо, я думал, что будет лучший способ сделать это. Я также вижу, что он также выводит порядок прихода, поэтому не нужно беспокоиться о сложной версии регулярного выражения :) – James

0

Это не сложный ответ, но вы можете преобразовать ваши данные

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) 
) 

С X_mod вы могли бы написать векторизованную (= быстро) решение. Для начала with(X_mod, c(0,cumsum(Ward[-1]!=Ward[-length(Ward)]))) дает вам идентификатор посещения.

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