11

I often need to remove lists of columns from a data.frame.

I usually do this:

to.remove <- c("hp","drat","wt","qsec")
mtcars[,-which(names(mtcars) %in% to.remove)]

which works fine.

But I'd like to be able to do this in a cleaner way using subset. But it seems to be attaching the data.frame and then accessing the column names as variables rather than strings.

For instance this is what I would like to be able to do:

subset(mtcars,select=-to.remove)

Is there a way to force subset to use a vectors of strings in the select statement? Or is there another better alternative?

Joshua Ulrich
  • 173,410
  • 32
  • 338
  • 418
Jesse
  • 479
  • 1
  • 5
  • 13

2 Answers2

33

I would probably do this like so:

to.remove <- c("hp","drat","wt","qsec")
`%ni%` <- Negate(`%in%`)
subset(mtcars,select = names(mtcars) %ni% to.remove)

(I use %ni% a lot, so I have it built into my .Rprofile already.)

joran
  • 169,992
  • 32
  • 429
  • 468
  • Nice use of a binary operator created with negate +1 – Tyler Rinker Mar 23 '12 at 20:55
  • @TylerRinker I can't recall anymore where I picked that function up from. Must have been either SO or r-help. – joran Mar 23 '12 at 21:04
  • Very cool to learn about Negate. I rarely use things in `funprog` and this is a great use for it. – Jesse Mar 23 '12 at 21:09
  • 3
    +1, `Negate` looks like quite a useful hidden gem, as does `%ni%`. And your next task is to cut down the mightiest tree in the forest with... a herring! – James Mar 23 '12 at 21:46
  • For completeness you can also use the `!` operator just like: `mtcars[,!(names(mtcars) %in% to.remove)]` – Robert Hering Jul 15 '20 at 07:46
5

You can certainly use select, but you've got to pass in names, not characters. So this will work:

subset( mtcars, select = -c(hp, drat, wt, qsec) )
philadams
  • 353
  • 3
  • 8