【问题标题】:Break up rows representing long time intervals into multiple rows将表示长时间间隔的行分成多行
【发布时间】:2019-01-16 14:50:41
【问题描述】:

我有一个包含多行的数据框(tibble),每行包含一个 IDNR、一个开始日期、一个结束日期和一个曝光状态。 IDNR 是字符变量,开始和结束日期是日期变量,曝光状态是数字变量。这是前 3 行的样子:

# A tibble: 48,266 x 4

   IDNR                 start      end        exposure
   <chr>                <date>     <date>        <dbl>
 1 1                    2018-02-15 2018-07-01        0
 2 2                    2017-10-30 2018-07-01        0
 3 3                    2016-02-11 2016-12-03        1

# ... with 48,256 more rows

为了进行时变 cox 回归,我想将行分成 90 天的部分,同时保持开始和结束日期。这是我想要实现的一个例子。发生的情况是,新的结束日期是开始 + 90 天,并创建了一个新行。此行的开始日期与上一行的结束日期相同。如果现在开始和结束之间的时间小于 90 天,这很好(对于 IDNR 1 和 3),但是对于 IDNR 2,时间仍然超过 90 天。因此需要添加第三行。

# A tibble: 48,266 x 4
# Groups:   IDNR [33,240]
   IDNR                 start      end        exposure
   <chr>                <date>     <date>        <dbl>
 1 1                    2018-02-15 2018-05-16        0
 2 1                    2018-05-16 2018-07-01        0
 3 2                    2017-10-30 2018-01-28        0
 4 2                    2018-01-28 2018-04-28        0
 5 2                    2018-04-28 2018-07-01        0
 6 3                    2016-02-11 2016-08-09        1
 7 3                    2016-08-09 2016-12-03        1 

我对使用 R 进行编码比较陌生,但到目前为止我发现 dplyr 非常有用。因此,如果有人知道使用 dplyr 的解决方案,我将不胜感激。

提前致谢!

【问题讨论】:

  • 你能详细说明一下逻辑吗?你只提供了三行,我就是看不到逻辑。
  • 在分析的后期,我将使用这个数据框进行时变 cox 回归。由于我想以 90 天的间隔更新每个人(= 每个 IDNR)的协变量,因此我将使用此数据框作为“主干”来填充协变量。例如,一个人的过敏反应可能在 90 天内发生了变化,然后可以在每个时间间隔将其编码为 0 或 1。我希望现在这更有意义。
  • 或者我可能错误地解释了您的问题,这就是您正在寻找的答案。在我尝试创建的数据集中,开始和结束之间的时间永远不会超过 90 天。如果时间超过 90 天,则必须将结束日期设置为 start + 90 天,并且需要添加一个包含前一个结束日期的新行。此新行的开始日期与上一行的结束日期相同。如果新的开始日期和结束日期之间的时间不超过 90 天,那很好。否则,需要添加另一行(这发生在 IDNR 2 中)。
  • 非常清楚的问题,对于第一次贡献来说确实做得很好。

标签: r dplyr


【解决方案1】:

给你:

使用df 作为您的数据框:

df = data.frame(IDNR = 1:3, 
                start = c("2018-02-15","2017-10-30","2016-02-11"),
                end = c("2018-07-01","2018-07-01","2016-12-03"),
                exposure = c(0,0,1))

做:

library(lubridate)    

newDF = apply(df, 1, function(x){
    newStart = seq(from = ymd(x["start"]), to = ymd(x["end"]), by = 90)
    newEnd = c(seq(from = ymd(x["start"]), to = ymd(x["end"]), by = 90)[-1], ymd(x["end"]))
    d = data.frame(IDNR = rep(x["IDNR"], length(newStart)), 
                   start = newStart, 
                   end = newEnd, 
                   exposure = rep(x["exposure"], length(newStart)))
})

newDF = do.call(rbind, newDF)

newDF = newDF[newDF$start != newDF$end,]

结果:

> newDF
  IDNR      start        end exposure
1    1 2018-02-15 2018-05-16        0
2    1 2018-05-16 2018-07-01        0
3    2 2017-10-30 2018-01-28        0
4    2 2018-01-28 2018-04-28        0
5    2 2018-04-28 2018-07-01        0
6    3 2016-02-11 2016-05-11        1
7    3 2016-05-11 2016-08-09        1
8    3 2016-08-09 2016-11-07        1
9    3 2016-11-07 2016-12-03        1

这样做是创建从startend 90 天的天序列,并与它们一起创建一个较小的数据框以及IDNRexposure。此应用将返回您可以使用do.call 连接在一起的数据框列表。最后一行删除具有相同startend 日期的行

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-02-12
    • 2017-11-09
    • 2018-01-15
    • 1970-01-01
    • 1970-01-01
    • 2022-01-20
    • 1970-01-01
    相关资源
    最近更新 更多