2016-12-07 1 views
1

ゲームデータを分析しようとしていますが、指定した行の後にすべての行を削除する必要があります。指定された行のすべての行を時系列で削除する

次のケースでは、各ユーザーのEVENT "Die"の後にすべての行を削除したいと考えています。データはUID、TIME.HOURでソートされます。

DF:

UID TIME.HOUR EVENT 
    1  5  Run 
    1  5  Run 
    1  6  Run 
    1  7  Die 
    1  8  Run 
    1  9  Run 
    2  14  Jump 
    2  15  Die 
    2  16  Run 
    2  17  Run 

期待される結果:

UID TIME.HOUR EVENT 
    1  5  Run 
    1  5  Run 
    1  6  Run 
    1  7  Die 
    2  14  Jump 
    2  15  Die 

私は、私は以下のコードで右のトラックにだと思うが、次のステップに苦しんではありません。

args <- which(df$EVENT== "Die") 
df[,c(sapply(args, function(x) ???), by = UID] #seq? range? 

ありがとうございます。

答えて

3

data.tableを使用できます。 'data.frame'を 'UID'でグループ化された 'data.table'に変換し、論理ベクトル(EVENT == "Die")の倍数cumsumを取得し、2未満であるかどうかをチェックしてください。

library(data.table) 
setDT(df)[, .SD[cumsum(cumsum(EVENT=="Die"))<2] , UID] 
# UID TIME.HOUR EVENT 
#1: 1   5 Run 
#2: 1   5 Run 
#3: 1   6 Run 
#4: 1   7 Die 
#5: 2  14 Jump 
#6: 2  15 Die 

Or a faster approach:データ

setDT(df)[df[, .I[cumsum(cumsum(EVENT=="Die"))<2] , UID]$V1] 

や@ Psidomのアプローチの変形をサブセットにその列($V1)を抽出し、行インデックスを取得する

setDT(df)[df[, .I[seq(match("Die", EVENT, nomatch = .N))] , UID]$V1] 

あるいは場合dplyr

library(dplyr) 
df %>% 
    group_by(UID) %>% 
    slice(seq(match("Die", EVENT, nomatch = n()))) 
# UID TIME.HOUR EVENT 
# <int>  <int> <chr> 
#1  1   5 Run 
#2  1   5 Run 
#3  1   6 Run 
#4  1   7 Die 
#5  2  14 Jump 
#6  2  15 Die 

を使用し、我々はR.S @から%>% as.data.framedata.frame出力、チェーンを(必要があります。コメント)

+0

これは 'dplyr'部分について - これはすてきで、非常に柔軟です。 'slice'部分は' seq'を必要とします。そうでなければ、一致する行のみを返します。私はそれを正しく得たか?そして、 'nomatch = n()'は、マッチしなかった場合に終了することを意味しますか?ところで、最後に '%>%ungroup()%>%as.data.frame()'を追加して、クリーンアップされたデータフレームを取得することをお勧めします。 –

+0

@ R.S。 'seq'を使わない場合は一致する行しか得られません。また、' nomatch = n() 'は特定のUIDにマッチしない特殊な場合に使用されます。 tbl_dfとして出力することを好む人もいます。だから、私はそれをそのまま残し、あなたのコメントを追加します – akrun

+1

ああ。ありがとう。洞察は助けになります。 –

2

別のオプション、あなたは(最初Dieインデックスを見つける。)match()head()を使用することができます。おそらく

dt[, head(.SD, match("Die", EVENT, nomatch = .N)), UID] # if no match is found within the 
                  # group, return the whole group 

# UID TIME.HOUR EVENT 
#1: 1   5 Run 
#2: 1   5 Run 
#3: 1   6 Run 
#4: 1   7 Die 
#5: 2  14 Jump 
#6: 2  15 Die 
3

これはそれほど効率的ではありませんが、あなたは空想に参加行うことができます:

mdf = df[EVENT == "Die", head(.SD, 1L), by=UID, .SDcols = "TIME.HOUR"] 
df[!mdf, on=.(UID, TIME.HOUR > TIME.HOUR)] 

    UID TIME.HOUR EVENT 
1: 1   5 Run 
2: 1   5 Run 
3: 1   6 Run 
4: 1   7 Die 
5: 2  14 Jump 
6: 2  15 Die 

もちろん、別のオブジェクトとしてmdfテーブルを保存する必要はありません。それはiは別のdata.tableまたはベクトルのリストである

  • x[!i]を、仕組み


    iに基づいてxの行を除外するためにRを言って、-参加アンチですこれはベクトルでどのように動作するかに似ています(iは論理ベクトルでなければなりません)。

  • on=.(ID, v >= v)オプションは、Rに「非等結合」を実行していることを通知します。「v >= v部分は、これら二つを組み合わせる

。(左側)iからvは(右側)xからvより大きくなければならないことを意味し、我々は除いていますon=で指定された基準を満たす行


サイドノート私はわからないんだけどカップルの事があります。なぜvがあり、我々は非エクイ参加するよりも、より良い名前を持っていますか〜にx[i]iの左側にxを持っていても、iから左に移動しましたか?

私はPsidomとakrunの答えの両方からheadと不等式を使って借りました。 1つ(多分?)優位性はhead(.SD, 1L)is optimizedですが、head(.SD, expr)はまだありません。

+0

非等価結合の有効な使用 – akrun

関連する問題