R 跨区间边界分块数据
假设我有这些数据:R 跨区间边界分块数据,r,data.table,R,Data.table,假设我有这些数据: start end duration 1 2.67026 2.903822 0.233562 2 4.40529 5.606470 1.201180 3 9.24340 10.010818 0.767418 4 11.87930 13.414140 1.534840 5 14.78210 15.182492 0.400392 6 16.51720 16.817494 0.300294 7 22.08930 25.125610 3
start end duration
1 2.67026 2.903822 0.233562
2 4.40529 5.606470 1.201180
3 9.24340 10.010818 0.767418
4 11.87930 13.414140 1.534840
5 14.78210 15.182492 0.400392
6 16.51720 16.817494 0.300294
7 22.08930 25.125610 3.036310
8 32.13240 33.667240 1.534840
9 45.47880 45.912558 0.433758
10 52.85270 54.454270 1.601570
11 55.62210 56.389518 0.767418
它们代表了一分钟内发生的11个事件。每个事件都有一个开始和结束时间(以秒为单位)以及该事件的持续时间(以秒为单位)
我想计算的是,在每10秒的时间间隔内,这些事件花费了多少秒
在data.table
中装箱数据的标准方法是:
as.data.table(df)[, .(total = sum(duration)), by = .(INTERVAL = cut(end, seq(0,60,10)))]
INTERVAL total
1: (0,10] 1.434742
2: (10,20] 3.002944
3: (20,30] 3.036310
4: (30,40] 1.534840
5: (40,50] 0.433758
6: (50,60] 2.368988
但是,请注意,事件3从9.24340秒开始,到10.010818秒结束。此方法仅对间隔(0,10)中前两个事件的持续时间求和。我希望第一个间隔包括10-9.24340=0.7566秒,也就是说,应该是2.19132秒。这个数字应该从第二个间隔中减去,它应该是2.246344秒
在本例中,0-10/10-20秒是事件跨越切点的唯一时间,但是,显然,我需要找到一个可推广到任意数量潜在切点的解决方案
我认为一个解决方案可能是将时间转换为datetime格式(包括毫秒?),并使用它来剪切数据,但是,我无法做到这一点
编辑@Arun的回答如下:
@阿伦的答案很好地解决了上述问题。但是,如果我们想包括所有的时间间隔,甚至那些总持续时间=0的时间间隔,该怎么办呢
例如:
set.seed(1)
df<-
data.frame(
start=c(2.3, 3.5,6.7,9.4,10.4,13.5,16.3,18.1),
duration=runif(8,0,1)
)
df$end<-df$start+df$duration
dt<-data.table(df)
dt
start duration end
1: 2.3 0.2655087 2.565509
2: 3.5 0.3721239 3.872124
3: 6.7 0.5728534 7.272853
4: 9.4 0.9082078 10.308208
5: 10.4 0.2016819 10.601682
6: 13.5 0.8983897 14.398390
7: 16.3 0.9446753 17.244675
8: 18.1 0.6607978 18.760798
结果:
1: 2 4 0.6376326
2: 6 8 0.5728534
3: 8 10 0.6000000
4: 10 12 0.5098897
5: 12 14 0.5000000
6: 14 16 0.3983897
7: 16 18 0.9446753
8: 18 20 0.6607978
请注意,结果中不包括间隔0-2和4-6。显然,我们可以将它们绑定回去,但我想知道是否可以通过简单地调整data.table
code?来实现这一点,我可以考虑使用foverlaps()
我觉得可能还有更好的选择。为什么不将跨越两个存储箱的事件拆分为仅位于一个存储箱中的两个事件呢?另外,我建议不要对毫秒数据使用datetime格式,因为存在一些问题:这似乎工作得很好——但是,如果总持续时间为零,它会降低间隔。e、 g.尝试将间隔更改为每2秒一次。有没有办法保持V1的零值?IIUC,只需交换参数(改为键入dt
)就可以了,并相应地更改j
?我编辑了我的问题,希望能让它更清楚。谢谢。但这一暗示仍然有效。你所要做的就是把论点颠倒过来,从这里开始。我将把这一点留给你们去试验和解决。好的,很好-这似乎是可行的:ans=foverlaps(lookup,setkey(dt,start,end));ans[,总和(pmin(i.end,end)-pmax(i.start,start)),由=(i.start,i.end)]
1: 2 4 0.6376326
2: 6 8 0.5728534
3: 8 10 0.6000000
4: 10 12 0.5098897
5: 12 14 0.5000000
6: 14 16 0.3983897
7: 16 18 0.9446753
8: 18 20 0.6607978
require(data.table) # v1.9.5+ (due to bug fixes in foverlaps for double)
lookup = data.table(start = seq(0, 50, by = 10), end = seq(10, 60, by = 10))
# start end
# 1: 0 10
# 2: 10 20
# 3: 20 30
# 4: 30 40
# 5: 40 50
# 6: 50 60
ans = foverlaps(dt, setkey(lookup, start, end))
ans[, sum(pmin(i.end, end) - pmax(i.start, start)), by=.(start,end)]
# start end V1
# 1: 0 10 2.191342
# 2: 10 20 2.246344
# 3: 20 30 3.036310
# 4: 30 40 1.534840
# 5: 40 50 0.433758
# 6: 50 60 2.368988