title: R How to get desired rows in aggregation using data.table and dplyr
body: <p>Suppose we have a data set like:</p>
  
  <pre><code>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
  </code></pre>
  
  <p>I want to aggregate this data set by DRIVE_NUM by the following rule:</p>
  
  <blockquote>
    <p>For a specific DRIVE_NUM group,</p>
    
    <p>If there is any FAIL flag in the DRIVE_NUM group, I want the first row
    with the FAIL flag.</p>
    
    <p>If there is no FAIL flag in the group, just take the first row in the
    group.</p>
  </blockquote>
  
  <p>So, I shall get the following set:</p>
  
  <pre><code>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
  </code></pre>
  
  <p>Now I could do it using ddply but it's extremely slow since my data set is usually very big.</p>
  
  <p>Is there any way to do it using data.table or dplyr.</p>
  
  <hr>
  
  <p>Update:</p>
  
  <p>It seems that dplyr is even slower than plyr. Is there any way to do anything faster than plyr. Or am I using anything inappropirately?</p>
  
  <pre><code>#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")&gt; 0){
      R = df[df$flag=="F",]
      if(nrow(R)&gt;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 %&gt;%
    group_by(group) %&gt;% 
    slice(which.min(flag))
  proc.time() - START  
  
  #user  system elapsed 
  #0.22    0.02    0.23 
  
  #dplyr method 2
  
  START = proc.time()
  X %&gt;%
    group_by(group, flag) %&gt;%
    slice(1) %&gt;%
    group_by(group) %&gt;% 
    slice(which.min(flag))
  proc.time() - START  
  
  #user  system elapsed 
  #0.28    0.00    0.28 
  </code></pre>