我有一些包含入院和出院日期的数据,我需要(对于每个人和入院ID #)创建一个宽到长的数据框,其中包含人员和入院ID,入院和出院之间的序列指示入院和出院之间的每天的值。
我偶然发现了一种非常hack的方法,它利用了apply如何命名它创建的列表中的项目;然而,我担心它可能容易出错。无论哪种方式,感觉都很笨拙,我想知道是否有一种使用更少代码的更干净的方法。
person <- c(1, 2, 3, 3)
admit <- c(1, 1, 1, 2)
admit.date <- as.Date(c("1/1/2010", "1/1/2010", "1/1/2010", "2/1/2010"), "%m/%d/%Y")
discharge.date <- as.Date(c("1/1/2010", "1/1/2010", "1/1/2010", "2/1/2010"), "%m/%d/%Y") + c(1,2,2,2)
df1 <- data.frame(person, admit, admit.date, discharge.date)
df1 ## where I start
library(plyr)
los_seq <- function(df) { seq(df$admit.date, df$discharge.date, 1)}
lst1 <- dlply(df1, .(person, admit), los_seq)
vec1 <- unlist(lst1)
## now it gets really hackish
df2 <- data.frame(v1 = paste(names(vec1), vec1, sep="__"))
df2$person <- substr(df2$v1, 1, regexpr("\.", df2$v1)-1)
df2$admit <- substr(df2$v1, regexpr("\.", df2$v1)+1, regexpr("\.", df2$v1)+1)
df2$date <- as.Date(as.numeric(substr(df2$v1, regexpr("__", df2$v1)+2, nchar(df2$v1))), origin="1970-01-01")
df2[,-1] ## this is how I need the result to look
使用以下内容如何(因为您使用的是实际日期):
SEQ <- df1$discharge.date - df1$admit.date + 1
df1[rep(row.names(df1), SEQ), 1:2]
# person admit
# 1 1 1
# 1.1 1 1
# 2 2 1
# 2.1 2 1
# 2.2 2 1
# 3 3 1
# 3.1 3 1
# 3.2 3 1
# 4 3 2
# 4.1 3 2
# 4.2 3 2
现在,为了猜测你在评论中可能指的是什么,也许你也在寻找日期的顺序。
SEQ <- df1$discharge.date - df1$admit.date + 1
df2 <- df1[rep(row.names(df1), SEQ), 1:3]
df2$date <- df2$admit.date + sequence(SEQ)-1
df2[-3]
# person admit date
# 1 1 1 2010-01-01
# 1.1 1 1 2010-01-02
# 2 2 1 2010-01-01
# 2.1 2 1 2010-01-02
# 2.2 2 1 2010-01-03
# 3 3 1 2010-01-01
# 3.1 3 1 2010-01-02
# 3.2 3 1 2010-01-03
# 4 3 2 2010-02-01
# 4.1 3 2 2010-02-02
# 4.2 3 2 2010-02-03