在定义的时间段内识别组特定的定时事件

时间:2016-10-18 14:42:02

标签: r data.table data-analysis

我有一个记录分类事件的数据集,这些事件有两个时间点t1和t2,其中t2离开> = t1。事件分类为z1,z2,z3或NA(未分类)。对于每个组(grp),我想识别t1在组中任何分类的t2事件的指定时间段内的事件。在我的例子中,我将这些t2事件称为参考日期。循环过程显示了我需要的内容,但对于大型数据集而言却毫无希望地效率低下。我要求它在包含数百万行且包含超过一百万个组的数据集上运行。

我还尝试使用data.table语法更有效地编写代码。我的方法是将每个组的参考日期集分配给矢量“ref”,然后对于组中的每一行计算t1和参考日期之间的差异,并针对指定的间隔测试这些间隔,然后返回一个布尔值,表示行特定t1是否在任何参考日期的30天内。当我将每个组限制为单个参考日期(通过取第一个日期[1])时,代码可以工作,但是当我允许多个参考日期时,根据需要,代码会返回错误。显然,我不了解j语句中的数据表是做什么的。有人可以解释我的错误,并建议一个有效的data.table解决方案。

示例数据

library("data.table")
DT <-read.table(text=
"grp,zcat,t1,t2
a,NA,2007-03-18,2007-03-28
a,z1,2007-08-04,2007-08-14
a,NA,2007-08-21,2007-08-23
a,NA,2007-11-21,2007-11-29
a,z1,2007-12-10,2007-12-13
a,z2,2008-02-16,2008-02-19
a,NA,2008-03-14,2008-03-21
a,NA,2008-05-27,2008-06-03
b,NA,2003-04-22,2003-04-27
b,z3,2003-05-11,2003-05-23
b,z1,2003-07-16,2003-08-02
c,z3,2011-01-18,2011-02-07
c,z3,2011-03-01,2011-03-13
c,NA,2011-03-30,2011-04-11
c,NA,2011-05-21,2011-05-28",
header=TRUE, sep=",", stringsAsFactors=FALSE, na.strings="NA", colClasses="character")
DT <-data.table(DT)
setorder(DT,grp,t1)

按组分组的参考日期

grp-a:“2007-08-14”“2007-12-13”“2008-02-19”

grp-b:“2003-05-23”“2003-08-02”

grp-c:“2011-02-07”“2011-03-13”

循环程序 - 确定

out<-c()
for(i in 1:nrow(DT)){
    ref <-DT[grp == grp[i] & !is.na(zcat),t2]
    temp <-as.Date(DT$t1[i]) - as.Date(ref)
    out[i] <-any(temp >=0 & temp <31)
    rm(ref,temp)
    # ref; delta; delta >=0 & delta <31
    if(i==nrow(DT)){DT[, newvar :=out]; rm(out)}
}

data.table编码尝试

前两个示例正常工作但每个组使用一个参考数据,第三个示例对所有参考日期使用相同的原则并失败。问题似乎在于j语句如何处理多个间隔值

DT[,{ref=t2[!is.na(zcat)]; delta=as.Date(t1) - as.Date(ref)[1]; delta >0 & delta <30}, by=grp]

DT[,{ref=t2[!is.na(zcat)][1]; delta=as.Date(t1) - as.Date(ref); delta >0 & delta <30}, by=grp]

DT[,{ref=t2[!is.na(zcat)]; delta=as.Date(t1) - as.Date(ref); any(delta >0 & delta <30)}, by=grp]

1 个答案:

答案 0 :(得分:2)

使用最新版本(1.9.8 +):

DT[, `:=`(t1 = as.Date(t1), t2 = as.Date(t2), newvar = FALSE)]

DT[DT[!is.na(zcat), .(grp, t2, t2.end = t2 + 31)],
   on = .(grp, t1 >= t2, t1 < t2.end),
   newvar := TRUE]