title: Select columns based on classes/types with compatibility for dplyr::select
body: <h2>Actual question</h2>
  
  <p>How do I define a select helper that selects columns based on their class/type and that is also compatible with <code>dplyr</code>'s architecture? </p>
  
  <h2>Due dilligence</h2>
  
  <p>I've looked at <a href="https://cran.r-project.org/web/packages/dplyr/vignettes/introduction.html" rel="nofollow noreferrer">https://cran.r-project.org/web/packages/dplyr/vignettes/introduction.html</a> and the help for <code>dplyr::select_helpers</code> but didn't find anything that would allow me to select based on classes/types</p>
  
  <h2>Example</h2>
  
  <p>Bring in some variation WRT classes/types:</p>
  
  <pre><code>dat &lt;- mtcars
  dat &lt;- dat %&gt;% mutate(
    mpg = as.character(mpg),
    wt = as.factor(wt),
    vs = as.character(vs)
  )
  </code></pre>
  
  <p>In short, I would like to make this a generic approach for <em>all</em> possible classes/types (and combinations of them) in R:</p>
  
  <pre><code>dat[ , sapply(dat, is.character)]
  # mpg    wt vs
  # 1    21  2.62  0
  # 2    21 2.875  0
  # 3  22.8  2.32  1
  # 4  21.4 3.215  1
  </code></pre>
  
  <p>Based on <a href="https://stackoverflow.com/questions/17964513/subset-variables-in-data-frame-based-on-column-type">Subset variables in data frame based on column type</a> I could do it like this:</p>
  
  <pre><code>select_on_class &lt;- function(.data, cls = "numeric") {
    dat[ , names(.data)[sapply(.data,
      function(vec, clss) class(vec) %in% clss, clss = cls)]]
  }
  dat %&gt;% select_on_class(c("character", "factor"))
  # mpg    wt vs
  # 1    21  2.62  0
  # 2    21 2.875  0
  # 3  22.8  2.32  1
  # 4  21.4 3.215  1
  </code></pre>
  
  <p>But I would like to be able to use it in calls to <code>dplyr::select</code>, so I tried this:</p>
  
  <pre><code>has_class &lt;- function(.data, cls = "numeric") {
    nms &lt;- names(.data)[sapply(.data,
      function(vec, clss) class(vec) %in% clss, clss = cls)]
    sapply(nms, as.name)
  }
  dat %&gt;% has_class(c("character", "factor"))
  # $mpg
  # mpg
  # 
  # $wt
  # wt
  # 
  # $vs
  # vs
  </code></pre>
  
  <p>The problem is that <code>sapply(nms, as.name)</code> returns a <code>list</code> and that doesn't play nicely with the internals of <code>select</code> (which I don't completely understand yet, BTW):</p>
  
  <pre><code>dat %&gt;% select(has_class(c("character", "factor")))
  # Error: All select() inputs must resolve to integer column positions.
  # The following do not:
  #   *  has_class("character")
  
  dat %&gt;% select_(has_class(c("character", "factor")))
  # Error in UseMethod("as.lazy") : 
  #   no applicable method for 'as.lazy' applied to an object of class "list"
  </code></pre>
  
  <hr>
  
  <h2>EDIT</h2>
  
  <p>Based on the answer using <code>select_if</code> I tried to generalize and got stuck:</p>
  
  <pre><code>has_class &lt;- function(.data, cls) {
    sapply(.data, function(vec, clss) class(vec) %in% clss, clss = cls)
  }
  dat %&gt;% has_class(c("character", "factor"))
  # mpg   cyl  disp    hp  drat    wt  qsec    vs    am  gear  carb
  # TRUE FALSE FALSE FALSE FALSE  TRUE FALSE  TRUE FALSE FALSE FALSE
  dat %&gt;% select_if(has_class, c("character", "factor"))
  # Error in vapply(tbl, p, logical(1), ...) : values must be length 1,
  # but FUN(X[[1]]) result is length 32
  </code></pre>
  
  <p>AFAIU, the <code>.predicate</code> functions just needs to return a logical vector (which <code>has_class</code> does) and I can pass additional arguments to the <code>.predicate</code> functions via <code>...</code> (which I did). So where am I still going wrong?</p>