抱歉,我对R很新,我不是数据专家。我正在尝试计算一个省略重叠日期的持续时间。我怀疑rubridate就是答案。 我的数据集如下所示:
patientnumber rxnumber startdate stopdate
100 1 1/1/2014 1/5/2014
100 2 1/1/2014 1/5/2014
100 3 1/20/2014 1/22/2014
200 4 2/14/2014 2/14/2014
200 5 2/15/2014 2/20/2014
我想计算得到患者100的值为8(5 + 3)和7为患者200(1 + 6)的值,以计算每位患者的总暴露量。
我认为我需要解决这个问题的方法是。计算每个患者的最小开始日期和最长停止日期,然后使用计数器变量从最小开始日期开始计数。 如果计数器变量与其中一个间隔重叠,则添加一个并移动。如果没有,只需移动直到达到最大停止日期。
我只是不知道如何编码。这将是我在R中完成的最复杂的编码,也是我第一次使用循环。请帮忙!
更新@ Richard 感谢帮助。在扩大规模时,我发现了一些问题。
假设患者数量相同且rx增加#
startdate stopdate duration重叠
3/26/2014 3/26/2014 1 3(此重叠来自上述记录)
3/27/2014 3/27/2014 1 0
3/27/2014 3/27/2014 1 1
3/27/2014 3/30/2014 4 1
3/28/2014 3/28/2014 1 3(不幸的是,我不确定要解决这个问题)
代码正常运行,只需要进行微调。希望你能帮忙。我将继续尝试解决这个问题。
答案 0 :(得分:3)
一种解决方案是计算持续时间,然后纠正与前一个条目的重叠。
注意:此解决方案假定某种类型的排序,并且不适用于无序的data.frames。假设(如在提供的示例中)数据按患者编号和按时间顺序排序。
如果数据格式不同,则必须对其进行相应的排序。
# example data
dat <- read.table(header=TRUE, text=
"patientnumber rxnumber startdate stopdate
100 1 1/1/2014 1/5/2014
100 2 1/1/2014 1/5/2014
100 3 1/20/2014 1/22/2014
200 4 2/14/2014 2/14/2014
200 5 2/15/2014 2/20/2014
300 5 2/19/2014 2/22/2014
300 6 3/27/2014 3/27/2014
300 7 3/27/2014 3/27/2014
300 8 3/27/2014 3/30/2014
300 9 3/28/2014 3/28/2014")
# convert to date
dat$startdate <- as.Date(dat$startdate, "%m/%d/%Y")
dat$stopdate <- as.Date(dat$stopdate, "%m/%d/%Y")
# base duration
dat$duration <- difftime(dat$stopdate, dat$startdate, units="days")+1
# calculate overlap
dat$overlap <- 0
for(i in 2:nrow(dat)){
samepat <- dat$patientnumber[i]==dat$patientnumber[i-1]
curovl <- min(dat$stopdate[i],dat$stopdate[i-1]) - dat$startdate[i]+1
if(curovl>0 & samepat) dat$overlap[i] <- curovl
}
# aggregate duration and overlap
res <- aggregate(duration ~ patientnumber, data=dat, sum)
res$overlap <- aggregate(overlap ~ patientnumber, data=dat, sum)[,2]
# calculate corrected value
res$corrected <- res$duration - res$overlap
结果:
> res
patientnumber duration overlap corrected
1 100 13 5 8
2 200 7 0 7
3 300 11 3 8
修改强>
修正了有关重叠计算的一些问题(如果患者数量发生变化,如果重叠仅是部分的话)。看看结果现在是否符合您的期望。谢谢你指出这个!
答案 1 :(得分:1)
此解决方案使用unique
函数删除重复日期。在使用unique
之前,需要将原始数据框重新格式化为高瘦版本。
# example data
dat <- read.table(header=TRUE, text=
"patientnumber rxnumber startdate stopdate
100 1 1/1/2014 1/5/2014
100 2 1/1/2014 1/5/2014
100 3 1/20/2014 1/22/2014
200 4 2/14/2014 2/14/2014
200 5 2/15/2014 2/20/2014
300 5 2/19/2014 2/22/2014
300 6 3/27/2014 3/27/2014
300 7 3/27/2014 3/27/2014
300 8 3/27/2014 3/30/2014
300 9 3/28/2014 3/28/2014")
# convert to date
dat$startdate <- as.Date(dat$startdate, "%m/%d/%Y")
dat$stopdate <- as.Date(dat$stopdate, "%m/%d/%Y")
# Create integer versions of the dates
dat$startdate <- as.integer(dat$startdate)
dat$stopdate <- as.integer(dat$stopdate)
# Initialize a "long" version of the original data frame
dat2 <- data.frame(patientnumber = as.integer(),
date = as.integer())
# Loop through each row in the original data frame
for (i in 1:nrow(dat)) {
# Loop through the days between the startdate and stopdate
for (j in dat[i, "startdate"]:dat[i, "stopdate"]) {
# Create a new row for each day
rowij <- data.frame(patientnumber = dat[i, "patientnumber"],
date = j)
# Concatenate the new row to the "long" version of the original data frame
dat2 <- rbind(dat2, rowij)
}
}
# Use the unique() function to get rid of duplicate days
dat3 <- unique(dat2)
# Aggregate the days
dat4 <- aggregate(date ~ patientnumber, data=dat3, length)
names(dat4)[2] <- "numberNonoverlappingDays"
dat4
<强>结果:强>
> dat4
patientnumber numberNonoverlappingDays
1 100 8
2 200 7
3 300 8