2017-07-18 6 views
2

のイベントカウンタはデータフレームdfであり、1つの変数IDと500Kのデータポイントを持ちます。event counterに以下の条件を含める必要があります。
ID == A
event counterをインクリメントします。 ID == Aしかし、最初の3つのデータポイントはカウンタ増分のために考慮されるべきではありません。
以下は期待される出力を有するデータフレームdfを示す以下の条件

ID  Event Counter 
D   0 
F   0 
V   0 
A   0 
A   0 
A   0 
A   1 
A   1 
A   1 
V   1 
F   1 
A   1 
A   1 
A   1 
A   2 
F   2 
G   2 
A   2 
A   2 
A   2 
A   3 
A   3 

注意: - 行番号1,2および3 doesntの条件、Event Counterにおけるしたがってなし増分を満たします。行4,5,6のID ==Aが増分しません(条件2参照)。行番号12,13および14

の場合に同じ条件を満たし、私の実装条件が異なるデータポイントのすべての出会いのためのカウンタをインクリメント同様の問題を発見しました。

+0

別のケースを返します。A' 'の連続8(または6以上)の値とは何がありますか?それでも同じカウンターを続けますか? –

+0

@RonakShah連続した出現がある場合、6より大きい値「A」がある場合、カウンタは同じ値のままです。カウンタは、イベント「ID == A」からの逸脱があり、イベント「ID == A」に戻るときにのみインクリメントする。 – Tareva

答えて

5

あなたがrleと組み合わせたタスクのこの種のzoo::rollsumを使用することができます。この場合は

library(zoo) 
x <- rollsumr(df$ID == "A", k=4, fill = NA) 
df$new <- with(rle(!is.na(x) & x == 4), rep(cumsum(values), lengths)) 

k = 4x == 4はあなたがインクリメントしたい前にID == "A"の3例が必要であることを意味します。あなたはこの番号をあなたが望むように変えることができます。

all.equal(df$Event_counter, df$new) 
#[1] TRUE 

rle一部が戻る:

結果は、ご希望の出力に等しい

rle(!is.na(x) & x == 4) 
#Run Length Encoding 
# lengths: int [1:6] 6 3 5 1 5 2 
# values : logi [1:6] FALSE TRUE FALSE TRUE FALSE TRUE 

今、私たちはa)の値の累積合計を計算することができ、すなわち0 -1-1-2 ... b)repを使用して、これらの値のそれぞれを、各シーケンスが長い、すなわちlengthsという同じ回数繰り返す。ここ

+0

これは素敵です!私は 'rle'を介して取得しようとしていた – Sotos

+0

ありがとう、@Sotosはそれを感謝します –

+0

素晴らしいソリューションです。あなたはwith文の長さの一部がどのように機能するかを私に説明できますか? rle(!is.na(x)&x == 4)の値にrep(cumsum(values))を適用し、0を残します。1 2 2 3.この関数は、長さ? – Florian

1

これは、あなたがやりたいようだ:

ID Event_counter Event_counter_check 
1 D    0     0 
2 F    0     0 
3 V    0     0 
4 A    0     0 
5 A    0     0 
6 A    0     0 
7 A    1     1 
8 A    1     1 
9 A    1     1 
10 V    1     1 
11 F    1     1 
12 A    1     1 
13 A    1     1 
14 A    1     1 
15 A    2     2 
16 F    2     2 
17 G    2     2 
18 A    2     2 
19 A    2     2 
20 A    2     2 
21 A    3     3 
22 A    3     3 

は、この情報がお役に立てば幸い

df = read.table(text="ID Event_counter 
D   0 
F   0 
V   0 
A   0 
A   0 
A   0 
A   1 
A   1 
A   1 
V   1 
F   1 
A   1 
A   1 
A   1 
A   2 
F   2 
G   2 
A   2 
A   2 
A   2 
A   3 
A   3",header=TRUE) 

indices = df$ID=="A" 
reset.counter = indices!=c(NA,head(indices,-1))& indices==FALSE & c(NA,head(indices,-1))==TRUE 
indices <- unname(split(indices, cumsum(seq_along(indices) %in% which(reset.counter)))) 
indices=unlist(lapply(indices, function(x) cumsum(x)==4 & x==TRUE)) 
df$Event_counter_check = cumsum(indices) 

OUTPUT!

+1

@FlorianMassあなたのコードもうまくいきました。ありがとうございました。 – Tareva

+0

ありがとう、それはあなたのいいです。私は次回、Docendoのコードを勉強しました;) – Florian

0

splitlapplyを用いて基地Rの代替です。

dat$v3 <- 
    cumsum(unlist(lapply(split(dat$ID, 
          with(rle(as.character(dat$ID)), rep(seq_along(values), lengths))), 
         function(x) { 
         v <- length(x) 
         if(x[1] == "A" && v > 3) rep(c(0, 1, 0), c(3, 1, v-4)) 
         else rep(0, v) 
         }))) 

ID変数はdocendo-discimusの回答の場合と、同じIDのランに分割するのと同様の方法を使用して分割されます。このリストはlapplyに供給され、グループがAsで構成されているかどうか、グループに少なくとも3つの要素があるかどうかがチェックされます。そうであれば、3の0の後に1が続き、残りの0の要素がベクトルの長さに一致するように返されます。検査が失敗した場合は、適切な長さの0のベクトルが戻されます。

これは

dat 
    ID Event_Counter v3 
1 D    0 0 
2 F    0 0 
3 V    0 0 
4 A    0 0 
5 A    0 0 
6 A    0 0 
7 A    1 1 
8 A    1 1 
9 A    1 1 
10 V    1 1 
11 F    1 1 
12 A    1 1 
13 A    1 1 
14 A    1 1 
15 A    2 2 
16 F    2 2 
17 G    2 2 
18 A    2 2 
19 A    2 2 
20 A    2 2 
21 A    3 3 
22 A    3 3 
関連する問題