在群组内,找到日期所在的正确间隔跨多个群组

时间:2017-03-14 16:08:37

标签: r date data.table grouping

在一个数据集中,我有帐号(全部唯一)以及帐户中某些事件发生的日期。

在另一个数据集中,我有帐号和帐户状态指示以及帐户输入和退出该状态级别的日期。帐户会多次列出,因为状态日期会生成帐户从不同状态移动的历史记录。

我希望在事件发生的第一个数据集的日期附加帐户所在的状态。

我已经构建了一个执行此任务的循环,但考虑到我正在使用的帐户数量,历史记录的长度以及状态“切换”的数量,循环需要几个小时才能在我的系统上运行。

由于两个文件之间的帐号相同,我想知道是否有办法使用data.table包在帐号上使用setkey功能,并使用data.table方法来加快追加过程。基本上在每个帐户中我需要查看第一个数据集中的日期在第二个数据集中的哪个时间间隔以获取状态。

这是我为循环生成的代码以及一些玩具数据。我已经尝试在lubridate包中使用interval但是这给了我一些循环中data.table的问题所以我已经使用了between()命令。

是否有人对更有效的追加流程有任何想法。

library(data.table)
library(lubridate)

set.seed(65)
# data set 1
dt1 <- data.table(account=c(1234,1235,1236,1237,1238),
            eventDate=c(ymd(20170123),ymd(20170223),ymd(20170114),ymd(20170205),ymd(20170127)))
setkey(dt1,account)

# data set 2
se1 <- seq(from=ymd(20161201),to=ymd(20170228), length.out=4)
se2 <- seq(from=ymd(20170101),to=ymd(20170228), length.out=5)
se3 <- seq(from=ymd(20170103),to=ymd(20170228), length.out=4)
se4 <- seq(from=ymd(20160101),to=ymd(20170228), length.out=3)
se5 <- seq(from=ymd(20161101),to=ymd(20170228), length.out=6)
ss1 <- c(se1[1]-days(23),se1[-length(se1)]+days(1))
ss2 <- c(se2[1]-days(13),se2[-length(se2)]+days(1))
ss3 <- c(se3[1]-days(3),se3[-length(se3)]+days(1))
ss4 <- c(se4[1]-days(53),se4[-length(se4)]+days(1))
ss5 <- c(se5[1]-days(2),se5[-length(se5)]+days(1))

dt2 <- data.table(account=c(rep(1234,4),rep(1235,5),rep(1236,4),rep(1237,3),rep(1238,6)),
            status=sample(LETTERS,22, replace=T),
            statusStart=c(ss1,ss2,ss3,ss4,ss5),
            statusEnd=c(se1,se2,se3,se4,se5))

setkey(dt2,account)

#dt2[,interv:=interval(statusStart,statusEnd)]

# set up and do the loop    
accnts <- dt1[,unique(account)]

for(i in 1:length(accnts)){
    dt2[    account==accnts[i] & 
        between(dt1[account==accnts[i],eventDate],statusStart,statusEnd,incbounds=T),
        eventDate:=dt1[account==accnts[i],eventDate]]   
}

# put it back in the first data set
dt1 <- merge(dt1,dt2[!is.na(eventDate),list(account,eventDate,status)], by=c('account','eventDate'),all.x=T)

1 个答案:

答案 0 :(得分:1)

这是使用data.table中的foverlaps函数执行此操作的一种方法:

dt1$statusStart <- dt1$eventDate
dt1$statusEnd <- dt1$eventDate
setkey(dt2, account, statusStart, statusEnd)
foverlaps(dt1, dt2, by.x = c('account', 'statusStart', 'statusEnd'), by.y = c('account', 'statusStart', 'statusEnd'), type = 'within')