2

抱歉,我对 R 很陌生,而且我不是数据专家。我正在尝试计算省略重叠日期的持续时间。我怀疑 lubridate 是答案。我的数据集如下所示:

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 感谢您的帮助。在扩大规模时,我注意到了一些问题。

假设 1 个相同的患者人数并增加 rx#

startdate stopdate 持续时间重叠
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(不幸的是,我不确定如何解决)

代码可以正常工作,只需要微调。希望你能帮忙。我会继续尝试解决这个问题。

4

2 回答 2

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 

编辑:

修复了有关重叠计算的一些问题(如果患者编号发生变化,如果重叠只是部分)。现在看看结果是否符合您的期望。感谢您指出了这一点!

于 2014-08-15T18:22:49.767 回答
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
于 2015-07-01T21:59:22.063 回答