27

I need to select all columns that are not numeric. I can select all numeric columns easily using select_if:

mtcars %>% select_if(is.numeric)

What if I want to select non-numeric columns? I tried:

mtcars %>% select_if(!is.numeric)

But I got error message below:

Error in !is.numeric : invalid argument type

Thanks a lot for help!

MKR
  • 19,739
  • 4
  • 23
  • 33
zesla
  • 11,155
  • 16
  • 82
  • 147
  • 1
    Take a look at here: https://stackoverflow.com/questions/39592879/r-dpylr-select-if-with-multiple-conditions – Sean Lin Jan 24 '18 at 20:20

3 Answers3

43

You can use purrr's negate() which is included if you use library(tidyverse) rather than just library(dplyr)

library(tidyverse)
iris %>% select_if(negate(is.numeric))
MrFlick
  • 195,160
  • 17
  • 277
  • 295
9

You can use a purrr-style anonymous function, provided you have a reasonably recent version of dplyr:

library(dplyr)

iris %>% select_if(~!is.numeric(.x)) %>% head()
#>   Species
#> 1  setosa
#> 2  setosa
#> 3  setosa
#> 4  setosa
#> 5  setosa
#> 6  setosa

or the old-style funs notation still works, e.g.

iris %>% select_if(funs(!is.numeric(.))) %>% head()
#>   Species
#> 1  setosa
#> 2  setosa
#> 3  setosa
#> 4  setosa
#> 5  setosa
#> 6  setosa
alistaire
  • 42,459
  • 4
  • 77
  • 117
  • fantastic - even though @MrFlick 's solution works, I love that this solution more because you don't need to load another library. Just a tiny thing: the above code also works using the dot `(.)` instead of `(.x)` as in `iris %>% select_if(~!is.numeric(.))` – Agile Bean Oct 24 '18 at 04:08
  • Yeah, I use `.x` in purrr-style functions because it's easier to differentiate from using `.` to tell the pipes where to place the data. – alistaire Oct 24 '18 at 13:57
  • Oh, I see, I thought you must use the dplyr syntax for the piped object. Didn't know about the purr-style pipe identifier, thanks a lot – Agile Bean Oct 25 '18 at 01:50
2

One possible solution could be:

df[, !(names(df) %in% names(df %>% select_if(is.numeric)))]

Example:
df <- data.frame(
  name = c( "a", "b", "c", "d" ),
  last_name = c( "r", "t", "s", "b" ),
  x = c( 3, 2, 1, 2 ),
  y = c( 4, 3, 4, 3 ),
  z = c( 8, 9, 6, 7 ) , stringsAsFactors = FALSE)
> df[, !(names(df) %in% names(df %>% select_if(is.numeric)))]
#  name last_name
#1    a         r
#2    b         t
#3    c         s
#4    d         b
MKR
  • 19,739
  • 4
  • 23
  • 33