2016-07-12 9 views
2

によってラグ値に基づいて行を削除data.table:は、次の形式で、私は<code>data.table</code>を持っているグループ

DT <- data.table(tag = rep(c("A", "B"), each = 10), 
       value = c(0, 3, 3, 3, 0, 1, 1, 1, 3, 0, 
          0, 1, 3, 1, 0, 3, 0, 1, 1, 0)) 
> DT 
    tag value 
1: A  0 
2: A  3 
3: A  3 
4: A  3 
5: A  0 
6: A  1 
7: A  1 
8: A  1 
9: A  3 
10: A  0 
11: B  0 
12: B  1 
13: B  3 
14: B  1 
15: B  0 
16: B  3 
17: B  0 
18: B  1 
19: B  1 
20: B  0 

私は3の値を持っていますが、唯一のものは0に続くすべての行を削除したいと思います。つまり、行2,3,4、行16は削除したいが、行9と行13を保持する必要があります。

これを実行する方法はありますか?

答えて

5

可能溶液:

DT[, `:=` (threes = rleid(value==3), apz = value == 3 & shift(value) == 0) 
    ][, if (all(!apz)) .SD, by = threes 
    ][, c('threes','apz') := NULL] 

与える:

tag value 
1: A  0 
2: A  0 
3: A  1 
4: A  1 
5: A  1 
6: A  3 
7: A  0 
8: B  0 
9: B  1 
10: B  3 
11: B  1 
12: B  0 
13: B  0 
14: B  1 
15: B  1 
16: B  0 
3
DT[, prev.value := shift(value), by = tag][ 
    , prev.value := prev.value[1], by = .(tag, rleid(value))][ 
    !(value == 3 & prev.value == 0)] 
# tag value prev.value 
# 1: A  0   NA 
# 2: A  0   3 
# 3: A  1   0 
# 4: A  1   0 
# 5: A  1   0 
# 6: A  3   1 
# 7: A  0   3 
# 8: B  0   NA 
# 9: B  1   0 
#10: B  3   1 
#11: B  1   3 
#12: B  0   1 
#13: B  0   3 
#14: B  1   0 
#15: B  1   0 
#16: B  0   1 
2

をここでソート(改善のため@Procrastinatusの小道具)のワンライナーだ:

DT[setDT(rle(value))[, rep(!(values==3 & shift(values)==0), lengths)] ] 

どのように動作するかを理解するには、 DT[, setDT(rle(value))]を実行し、Rがどのように連続値の実行を要約するかを示し、?rleを読み込みます。


私の独創的なアプローチされました:

DT[ rleid(value) %in% setDT(rle(value))[ , .I[!(values==3 & shift(values)==0)]] ] 

DT[, rleid(value)]を試してみて、詳細については?rleid読みください。この第2のアプローチは、実行が(rlerleidの両方を使用して)2回評価されるため、悪化します。

+0

私は、実行を2回評価することなく(rleとrleidの両方で)これを書くことができますが、いい方法は考えられませんでした。 – Frank

+0

いいですね! 'rle'だけの代替方法:' DT [setDT(rle(value)]、rem:=!(values == 3&shift(values)== 0)]、[rep(rem、lengths)]] ' – Jaap

+1

さらに短く: 'DT [setDT(rle(value)] [、(値== 3とシフト(値)== 0)、長さ]]] – Jaap

関連する問題