2017-03-14 19 views
0

在一個數據集中,我有賬戶號碼(全部唯一)以及某個事件在賬戶中發生的日期。在組內,找到日期在多個組中的正確間隔

在另一個數據集中,我有帳戶號碼和帳戶狀態指示器以及帳戶進入和退出該狀態級別的日期。這些帳戶會多次列出,因爲狀態日期會生成帳戶從不同狀態轉移的歷史記錄。

我希望將帳戶處於發生事件發生日期的狀態附加到第一個數據集。

我已經建立了一個循環來執行這個任務,但是考慮到我正在使用的帳戶的數量,歷史的長度以及狀態「開關」的數量,循環需要幾個小時才能在我的系統上運行。

由於這兩個文件之間的帳號是相同的,我想知道是否有一種方法使用data.table包在帳號上使用setkey功能,並使用data.table方法來加速追加處理。基本上在每個帳戶內,我需要查看第一個數據集中的日期在第二個數據集中的哪個時間間隔以獲取狀態。

這是我爲我的循環制作的代碼以及一些玩具數據。我試過在lubridate包中使用間隔,但是這給了我一些與循環中的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

這裏有一個辦法做到這一點,使用foverlaps功能從data.table:

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') 
+0

哇! Oropendola這是現象!我只是在一個修剪下來的數據集組合中運行這個,其中dt1約有30K行,而dt2約有350K行。我的循環花了大約7分鐘。 foverlaps()函數在...中完成了它,你準備好了嗎? 0.36秒。非常感謝您提供此解決方案。非常有效。非常快。 –

相關問題