2017-06-15 115 views
1

在以下數據集中,我想要刪除從第一個實例開始的所有行,按Time排序並按ID分組,Var爲TRUE。換句話說,我想爲每個ID的所有行設置FALSE爲止的子集,直到第一個TRUE,按Time排序。刪除基於第一個實例的行以滿足條件

ID <- c('A','B','C','A','B','C','A','B','C','A','B','C') 
Time <- c(3,3,3,6,6,6,9,9,9,12,12,12) 
Var <- c(F,F,F,T,T,F,T,T,F,T,F,T) 
data = data.frame(ID, Time, Var) 

data 
    ID Time Var 
1 A 3 FALSE 
2 B 3 FALSE 
3 C 3 FALSE 
4 A 6 TRUE 
5 B 6 TRUE 
6 C 6 FALSE 
7 A 9 TRUE 
8 B 9 TRUE 
9 C 9 FALSE 
10 A 12 TRUE 
11 B 12 FALSE 
12 C 12 TRUE 

對於該數據幀的所期望的結果應該是:

ID Time Var 
    A 3 FALSE 
    B 3 FALSE 
    C 3 FALSE 
    C 6 FALSE 
    C 9 FALSE 

注意,溶液不應該只刪除行,其中Var == TRUE,但也應除去行,其中Var == FALSE但這跟在Time之後Var == 012爲真ID

我試過很多不同的東西,但似乎無法弄清楚這一點。任何幫助深表感謝!

回答

2

以下是使用group_bycumsumdplyr這樣做的方法。

基本原理是Var是一個邏輯向量,其中FALSE等於0,TRUE等於1. cumsum將保持爲0直到它遇到第一個TRUE。

library(dplyr) 
data%>% 
    group_by(ID)%>% 
    filter(cumsum(Var)<1) 

     ID Time Var 
    <fctr> <dbl> <lgl> 
1  A  3 FALSE 
2  B  3 FALSE 
3  C  3 FALSE 
4  C  6 FALSE 
5  C  9 FALSE 

這裏的等價代碼data.table

library(data.table) 
data[data[, .I[cumsum(Var) <1], by = ID]$V1] 
    ID Time Var 
1: A 3 FALSE 
2: B 3 FALSE 
3: C 3 FALSE 
4: C 6 FALSE 
5: C 9 FALSE 
+0

使用'cumsum'是那麼聰明!我一直在試圖找到一個「dplyr」解決方案,但沒有想到這種方法。我假設這需要數據首先按'時間'排序......以確保這種情況我想我會寫如下: 'data%>% group_by(ID)%>% 排列(時間)%>% 過濾器(cumsum(Var)<1)' – holastello

+0

@holastello是的,添加'arrange(Time)%'將確保它按時間排序。 –

0

data.table解決方案應該工作。

library(data.table) 
> setDT(data)[, .SD[1:(which.max(Var)-1)], by=ID] 
    ID Time Var 
1: A 3 FALSE 
2: B 3 FALSE 
3: C 3 FALSE 
4: C 6 FALSE 
5: C 9 FALSE 

既然你希望所有的值到第一真實價值,which.max是要走的路。