2017-02-24 40 views
1

我有一個看起來數據幀有點像這樣:從一組包裝紙累積和起始行中的R

wt <- data.frame(region = c(rep("A", 5), rep("B", 5)), time = c(1:5, 1:5), 
       start = c(rep(2,5), rep(4, 5)), value = rep(1, 10)) 

value列中的值可以是任意數字(我在一個非常大的工作數據集),但每個區域都將超過等長時間序列並具有單個起點。

我想在每個區域內開始累積起始點,在時間序列中繼續前進,並在時間序列中的起始點之前換行。

完整的數據表,與預期的結果,應該是這樣的:

region time  start value result 
A   1  2  1  5 
A   2  2  1  1 
A   3  2  1  2 
A   4  2  1  3 
A   5  2  1  4 
B   1  4  1  3 
B   2  4  1  4 
B   3  4  1  5 
B   4  4  1  1 
B   5  4  1  2 

時間列,然後cumsum的一個簡單的變換是不行的,因爲該函數關心排順序,而不是任何特定因素。記住

就這樣,我工作在一個巨大的數據表和運行時絕對是一個問題,因此任何解決方案必須避免重新排序行。

想法如何做到這一點?提前致謝。

編輯:考慮時間是一個週期,例如在一天小時 - 並且例如,如果開始時間爲2,這意味着觀察在時間2和結束一個實例開始在下一時間1.

+0

'結果的邏輯不清楚 – akrun

+0

@akrun'value'列的累計開始於'時間==開始'和'時間==開始-1'的地方。如果開始時間不是1,則累積應該繞回該區域的第一行。 – ctenochaetus

+0

在這種情況下,預期的輸出似乎不正確。如果我們把區域'A',那麼時間==開始是第二行,並且時間==開始-1是第3行, – akrun

回答

2

我們可以以高效的方式與做data.table

library(data.table) 
setDT(wt)[time>=start, result := seq_len(.N), region] 
wt[, Max := max(result, na.rm = TRUE), region] 
wt[is.na(result), result := Max +seq_len(.N) , region][, Max := NULL][] 
# region time start value result 
#1:  A 1  2  1  5 
#2:  A 2  2  1  1 
#3:  A 3  2  1  2 
#4:  A 4  2  1  3 
#5:  A 5  2  1  4 
#6:  B 1  4  1  3 
#7:  B 2  4  1  4 
#8:  B 3  4  1  5 
#9:  B 4  4  1  1 
#10:  B 5  4  1  2 
+0

這看起來很有效!代碼中的哪個位置是爲了計算結果而選擇的「值」列? – ctenochaetus

+1

沒關係,是否處理過(見下面我的回答) – ctenochaetus

+0

@ctenochaetus好的,我看到你的'價值'欄是一個序列,所以是的,如果你有其他值,你可以將它改爲'cumsum' – akrun

1

akrun的解決方案適用於我給的例子(因此我接受了它的答案),但在這裏,在value列的任何值兼容版本:

library(data.table) 
setDT(wt)[time>=start, result := cumsum(value), region] 
wt[, Max := max(result, na.rm = TRUE), region] 
wt[is.na(result), result := Max +cumsum(value) , region][, Max := NULL][] 

只需添加...不幸名爲cumsum函數代替計算的序列。