【问题标题】:R trying to create start and stop times from single columnR试图从单列创建开始和停止时间
【发布时间】:2015-06-01 04:53:34
【问题描述】:

我是一个 R 初学者,一直被这个看似简单的问题所困扰。我有一个有 4 列的大数据框; id、观察日期、值 (alb) 和结束日期。单个 id 在不同日期可能有 1 到 15 个左右的观察值。结束日期是事件的时间或每个 id 审查的时间。

    id        date  alb         end
  1143  2010-03-23   41  2010-12-15
  1143  2010-06-29   39  2010-12-15
  1144  2008-01-01   34  2009-08-06 
  1145  2010-03-23   42  2012-10-25 
  1145  2011-01-12   45  2012-10-25

对于使用 alb 作为时变协变量的生存分析,我正在尝试为每个观察创建一个带有开始和停止时间列的情节。我正在尝试创建一个列,其中停止时间是下一个 alb 观察的开始时间或结束时间,如果该 ID 没有进一步的 alb 观察。像这样:

    id        date  alb         end       start        stop
  1143  2010-03-23   41  2010-12-15  2010-03-23  2010-06-29
  1143  2010-06-29   39  2010-12-15  2010-06-29  2010-12-15
  1144  2008-01-01   34  2009-08-06  2008-01-01  2009-08-06
  1145  2010-03-23   42  2012-10-25  2010-03-23  2011-01-12
  1145  2011-01-12   45  2012-10-25  2011-01-12  2012-10-25

我无法创建一列停止时间。我试图用嵌套的 if else 语句创建一个函数,结果一团糟。有没有人有一个简单的方法?提前致谢!

回复 r2evans,这是 data.frame 的很大一部分,其中 dplyr 操作中的一些值返回 1970-01-01。 (完整的数据框大约有 130,000 行)。谢谢

  id       date  alb        end
1143 2010-03-23 41.0 1996-08-10
1143 2010-06-29 39.0 1996-08-10
1143 2011-01-12 42.0 1996-08-10
1143 2010-09-28 47.0 1996-08-10
1143 2011-07-19 40.0 1996-08-10
1143 2012-06-12 41.0 1996-08-10
1143 2013-06-25 40.0 1996-08-10
1143 2013-12-26 40.0 1996-08-10
1143 2014-06-15 40.0 1996-08-10
1143 2014-12-26 39.9 1996-08-10
1144 2008-01-01 34.0 2015-04-28
1145 2010-03-23 42.0 2015-04-28
1145 2012-01-13 44.0 2015-04-28
1145 2012-06-15 41.0 2015-04-28

【问题讨论】:

  • 这些答案足够了吗?如果是这样,请接受一个(这是 SO 的惯例)。
  • 供以后参考:最好使用dput函数分享数据示例(见stackoverflow.com/q/5963269/168747)。

标签: r


【解决方案1】:

您的数据:

data.frame(
    id=c(        1143,         1143,         1144,         1145,         1145 ),
  date=c("2010-03-23", "2010-06-29", "2008-01-01", "2010-03-23", "2011-01-12" ),
   alb=c(          41,           39,           34,           42,           45 ),
   end=c("2010-12-15", "2010-12-15", "2009-08-06", "2012-10-25", "2012-10-25" )
)

一种技术是使用dplyr

library(dplyr)
df %>%
    group_by(id) %>%
    mutate(start=date, stop=lead(start, default=end[1]))
## Source: local data frame [5 x 6]
## Groups: id
## 
##     id       date alb        end      start       stop
## 1 1143 2010-03-23  41 2010-12-15 2010-03-23 2010-06-29
## 2 1143 2010-06-29  39 2010-12-15 2010-06-29 2010-12-15
## 3 1144 2008-01-01  34 2009-08-06 2008-01-01 2009-08-06
## 4 1145 2010-03-23  42 2012-10-25 2010-03-23 2011-01-12
## 5 1145 2011-01-12  45 2012-10-25 2011-01-12 2012-10-25

如果您只想使用 base 函数:

do.call('rbind', by(df, df$id, function(x) {
    cbind(x, start=x$date, stop=lead(x$date, default=x$end[1]))
}))
##          id       date alb        end      start       stop
## 1143.1 1143 2010-03-23  41 2010-12-15 2010-03-23 2010-06-29
## 1143.2 1143 2010-06-29  39 2010-12-15 2010-06-29 2010-12-15
## 1144   1144 2008-01-01  34 2009-08-06 2008-01-01 2009-08-06
## 1145.4 1145 2010-03-23  42 2012-10-25 2010-03-23 2011-01-12
## 1145.5 1145 2011-01-12  45 2012-10-25 2011-01-12 2012-10-25

【讨论】:

  • data.tablesetDT(dat)[, c('start', 'stop') := list(date,shift(date, type='lead',fill=end[1L])), by=id]类似的方法
  • 感谢@r2evans,dplyr 解决方案易于阅读并且可以工作,但每个 ID 的一系列观察中的最后停止日期显示为 1970-01-01 04:35:35 (与POSIXct有关吗?)。无论如何,现在很容易用正确的结束日期替换。
  • 您的数据没有显示异常。你能提供一个小数据集来说明这个问题吗?
  • @MartinWolley,我用你的新数据运行代码,在我的结果中看不到“1970”。我认识到您无法粘贴所有数据,但如果我看不到问题,我也无能为力。如果您可以手动处理它,那就太好了,除非您想以编程方式修复它,否则无需将其拖出。
  • 谢谢。当我将所有日期都设置为时,问题似乎消失了。日期优先,而不是像以前一样编码的 POSIXct。
【解决方案2】:

样本数据:

dat<-read.table(text="
    id        date  alb         end
  1143  2010-03-23   41  2010-12-15
  1143  2010-06-29   39  2010-12-15
  1144  2008-01-01   34  2009-08-06 
  1145  2010-03-23   42  2012-10-25 
  1145  2011-01-12   45  2012-10-25", header=TRUE, stringsAsFactors=FALSE)

解决方案:

dat$start <- dat$date
dat$stop[!duplicated(dat$id, fromLast = TRUE)] <- dat$end[!duplicated(dat$id, fromLast = TRUE)]
dat$stop[duplicated(dat$id, fromLast = TRUE)] <- dat[duplicated(dat$id), "date"]

dat
#    id       date alb        end      start       stop
#1 1143 2010-03-23  41 2010-12-15 2010-03-23 2010-06-29
#2 1143 2010-06-29  39 2010-12-15 2010-06-29 2010-12-15
#3 1144 2008-01-01  34 2009-08-06 2008-01-01 2009-08-06
#4 1145 2010-03-23  42 2012-10-25 2010-03-23 2011-01-12
#5 1145 2011-01-12  45 2012-10-25 2011-01-12 2012-10-25

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多