2016-11-11 8 views
0

私は大量のデータセットを持っており、個体と日付の一意のIDを持ち、各個人は複数の出会いがあります。以下R:ヒストリを日付別に集計する

あるコードと、このデータがどのように見えるかの例:

strDates <- c("09/09/16", "6/7/16", "5/6/16", "2/3/16", "2/1/16", "11/8/16",  
"6/8/16", "5/8/16","2/3/16","1/1/16") 
Date<-as.Date(strDates, "%m/%d/%y") 
ID <- c("A", "A", "A", "A","A","B","B","B","B","B") 
Event <- c(1,0,1,0,1,0,1,1,1,0) 
sample_df <- data.frame(Date,ID,Event) 

sample_df 

     Date ID Event 
1 2016-09-09 A  1 
2 2016-06-07 A  0 
3 2016-05-06 A  1 
4 2016-02-03 A  0 
5 2016-02-01 A  1 
6 2016-11-08 B  0 
7 2016-06-08 B  1 
8 2016-05-08 B  1 
9 2016-02-03 B  1 
10 2016-01-01 B  0 

私は出会いあたり取り付けられているすべての情報を維持したいが、その後IDで次の履歴情報を集約

  1. 前回の出会いの回数
  2. 前回のイベントの回数

例として、行2を見てみましょう。

行2はID Aなので、Row 2 Encounterの前に発生した行3-5を参照します。この行グループ内で、行3 & 5に両方ともイベントがあることがわかります。行2 = 2

のための過去のイベントの行2 = 3

数の前の出会いの

ナンバー理想的には、私は次のような出力になるだろう。これまでのところ

  Date ID Event PrevEnc PrevEvent 
1 2016-09-09 A  1  4   2 
2 2016-06-07 A  0  3   2 
3 2016-05-06 A  1  2   1 
4 2016-02-03 A  0  1   1 
5 2016-02-01 A  1  0   0 
6 2016-11-08 B  0  4   3 
7 2016-06-08 B  1  3   2 
8 2016-05-08 B  1  2   1 
9 2016-02-03 B  1  1   0 
10 2016-01-01 B  0  0   0 

を、I dplyrでこの問題をmutateとsummaryだけでなく、特定のIDに対して以前に発生したイベントに集約させることはできませんでした。 If-thenステートメントを使っていくつかの面倒なForループを試しましたが、このプロセスを単純化するためのパッケージや技術が存在するかどうかは疑問です。

ありがとうございました!

答えて

1

最も大きな障害は、現在のソート順です。ここでは元のインデックスポイントを保存しました。後でデータを並べ替えてから削除しました。それ以外の基本的なアイデアは、出会いのために0からカウントアップし、発生したイベントをカウントするのにcumsumを使用することです。この目的のために、lagは、現在のイベントのカウントを避けるために使用されます。

sample_df %>% 
    mutate(origIndex = 1:n()) %>% 
    group_by(ID) %>% 
    arrange(ID, Date) %>% 
    mutate(PrevEncounters = 0:(n() -1) 
     , PrevEvents = cumsum(lag(Event, default = 0))) %>% 
    arrange(origIndex) %>% 
    select(-origIndex) 

は@Frankと@MarkPetersonが指摘するように、ここでの最大のハードルは、Date列が降順にソートされていることである

  Date  ID Event PrevEncounters PrevEvents 
     <date> <fctr> <dbl>   <int>  <dbl> 
1 2016-09-09  A  1    4   2 
2 2016-06-07  A  0    3   2 
3 2016-05-06  A  1    2   1 
4 2016-02-03  A  0    1   1 
5 2016-02-01  A  1    0   0 
6 2016-11-08  B  0    4   3 
7 2016-06-08  B  1    3   2 
8 2016-05-08  B  1    2   1 
9 2016-02-03  B  1    1   0 
10 2016-01-01  B  0    0   0 
+1

'0:(n()-1)'は 'row_number() - 1L'ですか?また、元のインデックスは 'row_number()'になると思います。 – Frank

+1

うん、@フランク - それらは同等でなければなりません。なぜ私は 'row_number()'をより頻繁に使用し始めていないのか分かりません。おそらく、前置きのアプローチからの怠惰なホールドオーバー。 –

+0

非常に参考になりました。ラグはdefです。私が知りませんでしたし、今それを持って満足して何か! – EntryLevelR

0

与えます。 Date列を頼る必要としない別のアプローチ:

library(dplyr) 
res <- sample_df %>% group_by(ID) %>% 
        mutate(PrevEnc=n()-row_number(), 
          PrevEvent=rev(cumsum(lag(rev(Event), default=0)))) 

ここでは、我々は(IDによってグループ化された)行の数を決定するために、行インデックスとn()を決定するrow_number()を使用します。 Dateは降順でソートされているため、以前の出会いの回数は単にn()-row_number()です。以前のイベントの数を計算するために、Date列が降順にソートされ、revを使用して、この逆の列のlagの前にEvent列の順序を逆にします。cumsumrevを再度使用して、結果を元の順序に戻します。

あなたのデータを使用して:あなたはdata.tableで試してみたい場合は、

print(res) 
##Source: local data frame [10 x 5] 
##Groups: ID [2] 
## 
##   Date  ID Event PrevEnc PrevEvent 
##  <date> <fctr> <dbl> <int>  <dbl> 
##1 2016-09-09  A  1  4   2 
##2 2016-06-07  A  0  3   2 
##3 2016-05-06  A  1  2   1 
##4 2016-02-03  A  0  1   1 
##5 2016-02-01  A  1  0   0 
##6 2016-11-08  B  0  4   3 
##7 2016-06-08  B  1  3   2 
##8 2016-05-08  B  1  2   1 
##9 2016-02-03  B  1  1   0 
##10 2016-01-01  B  0  0   0 
2

をそれとも、あなたがこれを使用することができます。

library(data.table) 

# Convert to data.table and sort 
sample_dt <- as.data.table(sample_df) 
sample_dt <- sample_dt[order(Date)] 

# Count only the previous Events with 1 
sample_dt[, prevEvent := ifelse(Event == 1, cumsum(Event) - 1, cumsum(Event)), by = "ID"] 

# .I gives the row number, and .SD contains the Subset of the Data for each group 
sample_dt[, prevEnc := .SD[,.I - 1], by = "ID"] 

print(sample_dt) 
      Date ID Event prevEvent prevEnc 
1: 2016-01-01 B  0   0  0 
2: 2016-02-01 A  1   0  0 
3: 2016-02-03 A  0   1  1 
4: 2016-02-03 B  1   0  1 
5: 2016-05-06 A  1   1  2 
6: 2016-05-08 B  1   1  2 
7: 2016-06-07 A  0   2  3 
8: 2016-06-08 B  1   2  3 
9: 2016-09-09 A  1   2  4 
10: 2016-11-08 B  0   3  4 

あなたはこのpackageを知らなかった場合には、優れていますほとんどの操作ではcheat sheetです。

+1

'cumsum(Event)'を2回引用するのではなく、 'cumsum(Event) - (Event == 1)' – MichaelChirico

+0

@MichaelChirico良い点。私はそれについて考えなかった。 –