title: R: selecting rows of data frame based on several criteria
body: <p>I have created a data frame <code>my.df</code> and wish to select rows (or delete rows) based on several criteria.  With this example data frame I want to keep rows 1, 2, 4, 7 and 8.  Specifically, I want to: </p>
  
  <ol>
  <li>keep any row containing a number in columns 3, 4 or 5</li>
  <li>keep any row containing all missing observations in columns 3-5 if columns 1 and 2
  are not blank and do not contain junk</li>
  </ol>
  
  <p>I can do this, but my solution seems overly complex and I am hoping someone may suggest a more efficient approach.</p>
  
  <pre><code>my.df &lt;- data.frame(C1 = c("group1", "group1",     "",     "", "junk", "junk", "group2",       ""),
                      C2 = c(     "A",      "B",     "",     "",     "", "junk",      "B",      "C"),
                      C3 = c(     100,       NA,     NA,     10,     NA,     NA,       NA,       NA),
                      C4 = c(     200,       NA,     NA,     20,     NA,     NA,      100,       NA),
                      C5 = c(     100,       NA,     NA,     30,     NA,     NA,       NA,        5))
  
  my.df
  
  # the number of missing observations in columns 3-5 is &lt; 3 or
  # when the number of missing observations in columns 3-5 is 3 neither column 1 nor 2 is either blank or 'junk'
  
  df.2 &lt;- my.df[ (rowSums(is.na(my.df[,3:5]))  &lt; (ncol(my.df)-2)) | 
                 (rowSums(is.na(my.df[,3:5])) == (ncol(my.df)-2) &amp; my.df[,1] != 'junk' &amp; my.df[,2] != 'junk'  &amp; my.df[,1] != '' &amp; my.df[,2] != '') , ]
  df.2
  </code></pre>
  
  <p>With my actual data what qualifies as junk can be complex.  So, here I generalize <code>junk</code> to <code>junk1</code> and <code>junk2</code> and I still want to keep rows 1, 2, 4, 7 and 8.  The code below works.</p>
  
  <pre><code>my.df &lt;- data.frame(C1 = c("group1", "group1",     "",     "", "junk2", "junk1", "group2",       ""),
                      C2 = c(     "A",      "B",     "",     "",      "", "junk1",      "B",      "C"),
                      C3 = c(     100,       NA,     NA,     10,      NA,      NA,       NA,       NA),
                      C4 = c(     200,       NA,     NA,     20,      NA,      NA,      100,       NA),
                      C5 = c(     100,       NA,     NA,     30,      NA,      NA,       NA,        5))
  
  my.df
  
  df.3 &lt;- my.df[ (rowSums(is.na(my.df[,3:5]))  &lt; (ncol(my.df)-2)) | 
                 (rowSums(is.na(my.df[,3:5])) == (ncol(my.df)-2)  &amp; 
                  my.df[,1] != 'junk1' &amp; my.df[,2] != 'junk1'     &amp; 
                  my.df[,1] != 'junk2' &amp; my.df[,2] != 'junk2'     &amp;
                  my.df[,1] != '' &amp; my.df[,2] != '') 
  
          , ]
  df.3
  </code></pre>
  
  <p>Because strings that qualify as junk become quite varied and complex here I try to simplify the code a little using %in% to group junk, but I obtain an error.</p>
  
  <pre><code>all.junk &lt;- c("", "junk1", "junk2")
  
  my.df.1 &lt;- my.df[,1]
  my.df.2 &lt;- my.df[,2]
  
  my.df.1 &lt;- as.character(my.df.1)
  my.df.2 &lt;- as.character(my.df.2)
  
  df.4 &lt;- my.df[ (rowSums(is.na(my.df[,3:5]))  &lt; (ncol(my.df)-2)) | 
                 (rowSums(is.na(my.df[,3:5])) == (ncol(my.df)-2) &amp; 
                  my.df.1[!(my.df.1%in%all.junk)] &amp; my.df.2[!(my.df.2%in%all.junk)]) , ]
  df.4
  </code></pre>
  
  <p>I could proceed with the functional code I have, adding a new line to <code>df.3</code> for each character string that qualifies as junk, but I suspect there is a much more efficient solution.</p>
  
  <p>I have found similar questions on Stackoverflow, but none that I have found seem to be dealing with as many or as complicated selection criteria as in this example.</p>
  
  <p>Thank you for any suggestions, but particularly regarding the error in <code>df.4</code>.</p>