2017-10-11 88 views
1

我有一些示例数据,其中有(错误的)重叠间隔,所以我想将数据分成不重叠的间隔,根据原始数据将数据添加到每个间隔。使用数据表的聚合重叠间隔

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

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

你接受'dplyr'解决方案吗?> _ < – Wen

+0

当然。只要它工作 –

+0

为什么'DT $ data1 [5]'是'1/2 * 4 + 1/3 * 5'而不是'1/2 * 4 + 1/2 * 5'。换句话说,为什么权重不等于一,而不是一半,因为两者都有“半”(几乎)的时期? –

回答

1

我不清楚这个逻辑如何与权重一起工作,或者如何减去或增加开始和停止时间。但是,你会发现这里data.table有用得到你所需要的最终TABEL:

> (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 

我估计最后一步可以使用idx.new_startnew_endby参数进行。

+0

如果有一种方法可以通过'on'参数来执行'或'条件而不是'和'条件,我们可以避免''.data.table''的双重使用。当我写出答案时,我没有找到办法。中间'data.table'可能会变得很大,并且有很多冗余行。这可能是一个问题。 –