使用data.table查找间隔之间的间隙

时间:2015-06-04 21:51:42

标签: r data.table

我遇到以下问题:在data.table中给出一组非重叠间隔,报告间隔之间的间隙。

我已经在SQL中实现了一次,但由于缺少引导函数或滞后函数,我正在努力使用data.table。为了完整起见,我有here SQL代码。我知道data.table版本1.9.5中已实现了该功能。由changelog。那么data.table可以实现这一点而不需要进行大量的合并且没有滞后或引导函数吗?

原则上,只要性能不受影响,我并不完全反对使用合并(aka连接)。我认为这有一个简单的实现,但我无法弄清楚如何“获取”前一个结束时间作为我的差距表的开始时间。

例如:

# The numbers represent seconds from 1970-01-01 01:00:01
dat <- structure(
  list(ID = c(1L, 1L, 1L, 2L, 2L, 2L), 
       stime = structure(c(as.POSIXct("2014-01-15 08:00:00"),
                           as.POSIXct("2014-01-15 11:00:00"),
                           as.POSIXct("2014-01-16 11:30:00"),
                           as.POSIXct("2014-01-15 09:30:00"),
                           as.POSIXct("2014-01-15 12:30:00"),
                           as.POSIXct("2014-01-15 13:30:00")
                           ),
                         class = c("POSIXct", "POSIXt"), tzone = ""),
       etime = structure(c(as.POSIXct("2014-01-15 10:30:00"),
                           as.POSIXct("2014-01-15 12:00:00"),
                           as.POSIXct("2014-01-16 13:00:00"),
                           as.POSIXct("2014-01-15 11:00:00"),
                           as.POSIXct("2014-01-15 12:45:00"),
                           as.POSIXct("2014-01-15 14:30:00")
                           ), 
                         class = c("POSIXct", "POSIXt"), tzone = "")
  ),
  .Names = c("ID", "stime", "etime"),
  sorted = c("ID", "stime", "etime"),
  class = c("data.table", "data.frame"),
  row.names = c(NA,-6L)
)

dat <- data.table(dat)

这导致:

ID               stime               etime
1  2014-01-15 10:30:00 2014-01-15 11:00:00
1  2014-01-15 12:00:00 2014-01-16 11:30:00
2  2014-01-15 11:00:00 2014-01-15 12:30:00
2  2014-01-15 12:45:00 2014-01-15 13:30:00

注意:差距在几天内均匀报告。

2 个答案:

答案 0 :(得分:5)

如果我没有遗漏某些内容,那么您在所需的输出中缺少一行,所以我尝试使用您提到的devel版本中的shift

library(data.table) ## v >= 1.9.5
indx <- dat[, .I[-.N], by = ID]$V1
dat[, .(ID, stimes = etime, etime = shift(stime, type = "lead"))][indx]
res
#    ID               stime               etime
# 1:  1 2014-01-15 10:30:00 2014-01-15 11:00:00
# 2:  1 2014-01-15 12:00:00 2014-01-16 11:30:00
# 3:  2 2014-01-15 11:00:00 2014-01-15 12:30:00
# 4:  2 2014-01-15 12:45:00 2014-01-15 13:30:00

答案 1 :(得分:5)

大卫答案的变体,可能效率稍低,但输入更简单:

setkey(dat, stime)[, .(stime=etime[-.N], etime=stime[-1]), by=ID]

产地:

   ID               stime               etime
1:  1 2014-01-15 10:30:00 2014-01-15 11:00:00
2:  1 2014-01-15 12:00:00 2014-01-16 11:30:00
3:  2 2014-01-15 11:00:00 2014-01-15 12:30:00
4:  2 2014-01-15 12:45:00 2014-01-15 13:30:00

setkey只是为了确保表按时间排序。