2017-08-24 62 views
3

我開始了一個新項目,其中包含一系列數據管理我以前從來沒有這樣做過,而且我似乎缺乏技能或適當的搜索條件來查找示例。我有一個非常大的數據集,包含一個分組變量和一個二進制事件變量。它可以推廣到一個工作示例:創建一個基於「N」連續出現的原始因子水平的新因子/變量

library('data.table') 
grp <- c("a", "a", "a", "a", "a", "a", "a", "b", "b", "b", "b", "b") 
v1 <- c(1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1) 
test<-data.frame(grp,v1) 
test 

    grp v1 
1 a 1 
2 a 0 
3 a 0 
4 a 1 
5 a 1 
6 a 1 
7 a 1 
8 b 1 
9 b 0 
10 b 0 
11 b 0 
12 b 1 

我一直在使用data.table爲「V1」的「GRP」獨特的水平之內用新的序數值的因素「事件」事件的標籤條紋:

setDT(test) 
test<-test[, .(v1 = v1, event = rleidv(v1)), by=grp] 

    grp v1 event 
1: a 1  1 
2: a 0  2 
3: a 0  2 
4: a 1  3 
5: a 1  3 
6: a 1  3 
7: a 1  3 
8: b 1  1 
9: b 0  2 
10: b 0  2 
11: b 0  2 
12: b 1  3 

在實際的數據集,其中的一些「玻璃鋼」的具體事件是很長,我需要打破他們分成更小的,可變的,ñ - 有限事件。例如,我所期望的新變量「sub.event」與ñ = 2的輸出是:

> test 
    grp v1 event sub.event 
1: a 1  1   1 
2: a 0  2   2 
3: a 0  2   2 
4: a 1  3   3 
5: a 1  3   3 
6: a 1  3   4 
7: a 1  3   4 
8: b 1  1   1 
9: b 0  2   2 
10: b 0  2   2 
11: b 0  2   3 
12: b 1  3   4 

我一直在拉我的頭髮試圖找出一個辦法做到這一點。這似乎很簡單,我必須錯過一些明顯的東西。爲了促進,在確定限定的「子事件」之前,可以將原始變量連接成新的變量。

預先感謝您的幫助。

回答

3

下面是一個與鏈接工作的方法。

setDT(test)[, new := rep(1:0, length.out=.N), by=.(grp, rleid(v1))][, 
       new := cumsum(new), by=grp] 

第一鏈返回1和0重複grp- rleid對的長度的向量。鏈條中的下一個鏈接將其與cumsum通過grp進行總結。

此返回

test 
    grp v1 new 
1: a 1 1 
2: a 0 2 
3: a 0 2 
4: a 1 3 
5: a 1 3 
6: a 1 4 
7: a 1 4 
8: b 1 1 
9: b 0 2 
10: b 0 2 
11: b 0 3 
12: b 1 4 

注意,作爲寫的,它不會自動延伸到n> 2。然而,產生它的片,1:0可以寫成rep(c(1L, rep(0L, n)), length.out=.N)其中n+1是重複值的數目你想要的。

在這種情況下,代碼看起來像

test[, new := rep(c(1L, rep(0L, 2L)), length.out=.N), by=.(grp, rleid(v1))][, 
     new := cumsum(new), by=grp] 
+0

非常感謝,今天栽嘗試這兩種。 –

+0

在這種情況下,我喜歡更改* n *的這些便利。它踢回了一堆警告。我只是在學習data.table,但我猜這是「事件」子組不能被我指定的「n」整除並且剩下的字符串被丟棄了? –

+1

對於示例數據,您可以將* n *設置爲更小或更大的數字,並且不應得到警告。我嘗試了1,2和12.沒有問題。 「rep」向量的最終長度由「length.out」控制,該長度設置爲組的長度。 – lmo

2

有點迂迴:

# make counters within v1, grp 
test[, v0 := rep(1:.N, each=2, length.out=.N), by=.(rleid(grp, v1))] 

# make overall counters 
test[, v := .GRP, by=rleid(grp, v1, v0)] 

# difference per grp 
test[, v := v - first(v) + 1L, by=grp] 

# drop internal counter 
test[, v0 := NULL ] 

    grp v1 v 
1: a 1 1 
2: a 0 2 
3: a 0 2 
4: a 1 3 
5: a 1 3 
6: a 1 4 
7: a 1 4 
8: b 1 1 
9: b 0 2 
10: b 0 2 
11: b 0 3 
12: b 1 4 
+1

非常感謝,今天早上要試試這兩個。 –