使用数据表聚合重叠间隔

时间:2017-10-11 14:23:07

标签: r data.table intervals

我有一些样本数据,其中存在(错误的)重叠间隔,因此我想将数据拆分为非重叠间隔,根据原始数据向每个间隔添加数据。

假设我有一个这样的数据表:

x <- c(1000, 2000, 2000, 1000, 1500)
y <- c(1200, 3000, 4000, 2000, 3000)
z <- c("a", "a", "a", "b", "b")
n1 <- 1:5
n2 <- 4:8

DT <- data.table(id=z,
           start=as.POSIXct(x, origin = "2016-01-01"), 
           end=as.POSIXct(y, origin = "2016-01-01"),
           x=x,
           y=y,
           data1=n1,
           data2=n2)

DT

   id               start                 end    x    y data1 data2
1:  a 2016-01-01 01:16:40 2016-01-01 01:20:00 1000 1200     1     4
2:  a 2016-01-01 01:33:20 2016-01-01 01:50:00 2000 3000     2     5
3:  a 2016-01-01 01:33:20 2016-01-01 02:06:40 2000 4000     3     6
4:  b 2016-01-01 01:16:40 2016-01-01 01:33:20 1000 2000     4     7
5:  b 2016-01-01 01:25:00 2016-01-01 01:50:00 1500 3000     5     8

对于每个id,我想使用每个间隔内的数据总和来聚合数据。对于id==a,它看起来像这样:

1:  a 2016-01-01 01:16:40 2016-01-01 01:20:00 1000 1200     1     4
2:  a 2016-01-01 01:33:20 2016-01-01 01:50:00 2000 3000     3.5   8
3:  a 2016-01-01 01:50:01 2016-01-01 02:06:40 3001 4000     1.5   3

由于第3行的一半会被添加到第2行。对于id=="b",它会变得更复杂一些:

4:  b 2016-01-01 01:16:40 2016-01-01 01:24:59 1000 1499     2     3.5
5:  b 2016-01-01 01:25:00 2016-01-01 01:33:20 1500 2000     3.67  6.16
6:  b 2016-01-01 01:33:21 2016-01-01 01:50:00 2001 3000     3.33  5.33

这里增加了一行,因为我们有三个不同的时间。根据原始区间中的数据将数据分成每一行。例如,DT$data1[5]计算为1/2 * 4 + 1/3 * 5

我假设你可以在data.table中使用foverlaps,但我真的不知道如何。请帮忙。

1 个答案:

答案 0 :(得分:1)

我不清楚逻辑如何使用权重或如何减去或添加开始和停止时间。但是,您可能会发现data.table对于获取所需的最终表格非常有用:

> (unique_times <- DT[
+   , .(times = sort(unique(c(x, y)))), by = id][
+     , `:=`(new_start = times, new_end = shift(times, type = "lead")), 
+     by = id][
+       !is.na(new_end)][
+         , times := NULL])
> unique_times
   id new_start new_end
1:  a      1000    1200
2:  a      1200    2000
3:  a      2000    3000
4:  a      3000    4000
5:  b      1000    1500
6:  b      1500    2000
7:  b      2000    3000
> 
> # add data1 and data2 and x and y. The later to compute weights later
> unique_times <- unique_times[
+   DT, .(id, x, y, data1, data2, x.new_start, new_end),
+   on = .(id, new_start <= y), allow.cartesian = TRUE][
+     x < new_end & y > x.new_start]
> unique_times
   id    x    y data1 data2 x.new_start new_end
1:  a 1000 1200     1     4        1000    1200
2:  a 2000 3000     2     5        2000    3000
3:  a 2000 4000     3     6        2000    3000
4:  a 2000 4000     3     6        3000    4000
5:  b 1000 2000     4     7        1000    1500
6:  b 1000 2000     4     7        1500    2000
7:  b 1500 3000     5     8        1500    2000
8:  b 1500 3000     5     8        2000    3000

我认为可以使用byidx.new_start使用new_end参数进行最后一步。