2017-10-11 69 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'可能會變得很大,並且有很多冗餘行。這可能是一個問題。 –