【问题标题】:Calculate Duration Omitting Overlapping Dates in R计算 R 中省略重叠日期的持续时间
【发布时间】:2014-08-15 16:56:52
【问题描述】:

抱歉,我对 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 中完成的最复杂的编码,也是我第一次使用循环。请帮忙!

更新@理查德 感谢帮助。在扩大规模时,我注意到了一些问题。

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

开始日期停止日期持续时间重叠
3/26/2014 3/26/2014 1 3(此重叠来自上述记录) 2014 年 3 月 27 日 2014 年 3 月 27 日 1 0
2014 年 3 月 27 日 2014 年 3 月 27 日 1 1 2014 年 3 月 27 日 2014 年 3 月 30 日 4 1 3/28/2014 3/28/2014 1 3(不幸的是,我不确定如何解决)

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

【问题讨论】:

    标签: r lubridate


    【解决方案1】:

    一种解决方案是计算持续时间,然后纠正与前一个条目的重叠。

    注意:此解决方案假定某种排序类型,不适用于无序的 data.frame。假设(如在提供的示例中)数据按患者编号和时间顺序排序。

    如果数据格式不同,则必须进行相应的排序。

    # 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 
    

    编辑:

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

    【讨论】:

    • 非常感谢!简单而优雅的解决方案。没有你就无法做到这一点!谢谢!
    • 我已尝试扩大规模,但存在一些小问题:
    • 下面的数据集给了我一个不正确的修正值:
    • 我会尝试修复它。您能否发布您遇到问题的数据集?
    • 我修复了一些关于重叠计算的问题。现在请看看结果是否符合您的期望。干杯!
    【解决方案2】:

    此解决方案使用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
    

    【讨论】:

      猜你喜欢
      • 2016-12-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-02-18
      • 1970-01-01
      • 1970-01-01
      • 2015-10-30
      • 1970-01-01
      相关资源
      最近更新 更多