2015-07-21 46 views
0

我具有對應於狀態變化(例如,光開關翻轉)看起來像這樣記錄的時間戳的大的數據集:轉換時間戳狀態事件日誌中的R data.table運行時

library(data.table) 
library(lubridate) 
foo <- 
    data.table(ts = ymd_hms("2013-01-01 01:00:01", 
          "2013-01-01 05:34:34", 
          "2013-01-02 14:12:12", 
          "2013-01-02 20:01:00", 
          "2013-01-02 23:01:00", 
          "2013-01-03 03:00:00", 
          "2013-05-04 05:00:00"), 
      state = c(1, 0, 1, 0, 0, 1, 0)) 

而且我試圖(1)以秒爲單位將狀態日誌的歷史轉換爲運行時間,並且(2)將它們轉換爲每日累積運行時間。大部分(但不是全部)時間,連續記錄狀態值交替出現。這是一個糟糕的開始,但它有點短。

foo[, dif:=diff(ts)] 
foo[state==1][, list(runtime = sum(dif)), .(floor_date(ts, "day"))] 

特別是,當狀態爲「開」期間跨越午夜,這種做法是不夠聰明的東西分裂,並錯誤地報告運行時間超過一天。而且,使用diff也不是那麼聰明,因爲如果存在連續相同的狀態或者NAs,它將會出錯。

任何可以正確解析對大型數據集仍然快速高效的運行時的建議?

+0

如何處理狀態具有連續相同值的事件?如何計算運行時間呢? –

+0

如果有連續的狀態值(例如'state = c(1,1,1)',這些都應該被認爲是相同的運行週期,因爲狀態從未真正改變過。 – Bryan

回答

0

這應該起作用。我玩了foo的不同起始值,但仍然可能存在一些我沒有考慮到的邊緣情況。你需要注意的一件事情是,如果你的真實數據有一​​個接受夏令時的時區,那麼在製作具有所有日期的data.table時,這將會中斷。您可以通過首先對UTC或GMT執行force_tz(稍後可以更改它)來解決此問題。另一方面,如果您需要考慮25小時或23小時的日期,那麼您需要策略性地將其更改回您的時區。

#I'm using devel version of data.table which includes shift function for leading/lagging variables 
foo[,(paste0("next",names(foo))):=shift(.SD,1,0,"lead")] 
#shift with fill=NA produced an error for some reason this is workaround 
foo[nrow(foo),`:=`(nextts=NA,nextstate=NA)] 
#make data.table with every date from min ts to max ts 
complete<-data.table(datestamp=seq(from=floor_date(foo[,min(ts)],unit="day"),to=ceiling_date(foo[,max(ts)],unit="day"),by="days")) 
#make column for end of day 
complete[,enddate:=datestamp+hours(23)+minutes(59)+seconds(59.999)] 
#set keys and then do overlapping join 
setkey(foo,ts,nextts) 
setkey(complete,datestamp,enddate) 
overlap<-foverlaps(foo[state==1],complete,type="any") 
#compute run time for each row 
overlap[,runtime:=as.numeric(difftime(pmin(datestamp+days(1),nextts),pmax(datestamp,ts),units="secs"))] 
#summarize down to seconds per day 
overlap[,list(runtime=sum(runtime)),by=datestamp] 
+0

@Bryan這是做你要找的嗎? –