2016-07-08 79 views
1

假設我們有一個數據集,如:[R如何獲得所需使用data.table聚集行和dplyr

X = data.frame(
    ID = 1:9, 
    DRIVE_NUM = c("A","A","A","B","B","B","C","C","C"), 
    FLAG =c("PASS","FAIL","PASS","PASS","PASS","PASS","PASS","FAIL","FAIL") 
) 

ID DRIVE_NUM FLAG 
1   A PASS 
2   A FAIL 
3   A PASS 
----------------- 
4   B PASS 
5   B PASS 
6   B PASS 
----------------- 
7   C PASS 
8   C FAIL 
9   C FAIL 

我想通過以下規則來彙總這些數據由DRIVE_NUM設置:

對於特定DRIVE_NUM組,

如果在DRIVE_NUM組中的任何失敗的標誌,我想失敗標誌的第一行 。

如果組中沒有FAIL標誌,只需取 組中的第一行。

所以,我將得到以下一組:

wanted = data.frame(
    ID = c(2,4,8), 
    DRIVE_NUM = c("A","B","C"), 
    FLAG = c("FAIL","PASS","FAIL") 
) 

    ID DRIVE_NUM FLAG 
    2   A FAIL 
    4   B PASS 
    8   C FAIL 

現在我可以用ddply做到這一點,但它是非常緩慢的,因爲我的數據集通常是非常大的。

有沒有辦法使用data.table或dplyr來做到這一點。


更新:

似乎dplyr比plyr更慢。有沒有辦法比plyr更快地做任何事情?還是我不恰當地使用任何東西?

#Simulate Data 

X = data.frame(
    group = rep(paste0("NO",1:10000),each=2), 
    flag = sample(c("F","P"),20000,replace = TRUE), 
    var = rnorm(20000) 
) 



library(plyr) 
library(dplyr) 

#plyr 

START = proc.time() 
X2 = ddply(X,.(flag),function(df) { 
    if(sum(df$flag=="F")> 0){ 
    R = df[df$flag=="F",] 
    if(nrow(R)>1) {R = R[1,]} else {R = R} 
    } else{ 
    R = df[1,] 
    } 
    R 
}) 
proc.time() - START 

#user system elapsed 
#0.03 0.00 0.03 

#dplyr method 1 

START = proc.time() 
X %>% 
    group_by(group) %>% 
    slice(which.min(flag)) 
proc.time() - START 

#user system elapsed 
#0.22 0.02 0.23 

#dplyr method 2 

START = proc.time() 
X %>% 
    group_by(group, flag) %>% 
    slice(1) %>% 
    group_by(group) %>% 
    slice(which.min(flag)) 
proc.time() - START 

#user system elapsed 
#0.28 0.00 0.28 

回答

2

由於我們只希望過每個DRIVE_NUM第一行:FLAG組合,我們只選擇使用group_byslice的第一行開始。然後我們確保我們安排了FLAG,所以如果有FAIL它將是該DRIVE_NUM的第一排,但如果只有PASS,則沒有任何變化。然後我們再次slice選擇最上面一行。

library(dplyr) 
X %>% 
    group_by(DRIVE_NUM, FLAG) %>% 
    slice(1) %>% 
    group_by(DRIVE_NUM) %>% 
    slice(which.min(FLAG)) 

@Frank基本上解決了這個短得多,依靠which.min採取的第一個值(第一排)。

X %>% 
    group_by(DRIVE_NUM) %>% 
    slice(which.min(FLAG)) 
+0

哦,沒錯。它測試了他們的數據並得到了正確的結果,但不知何故錯過了。它仍然有效,因爲將使用字母順序。 – Axeman

+1

是的,非常好。謝謝。我傾向於忘記which.min'取第一個值。 – Axeman

+0

請參閱我的更新。 – John