我有一套我需要处理的医院入院数据,当我试图循环数据并拿起我需要的东西时,我感到困惑,这是一个例子:
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:
我正在考虑通过过滤病房来使用ddply
,但不行,因为B将被“省略”,A的时间段不会分解为2个。
有什么建议吗?谢谢!
答案 0 :(得分: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
答案 1 :(得分: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)])))
会为您提供访问ID。