R如何使用data.table和dplyr在聚合中获取所需的行

时间:2016-07-08 08:54:06

标签: 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标志,我想要第一行   与失败的旗帜。

     

如果组中没有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 

1 个答案:

答案 0 :(得分:2)

由于我们只想要每个DRIVE_NUMFLAG组合的第一行,我们首先选择使用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))