2015-07-21 47 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这是做你要找的吗? –