1

The answers to another question explain how to match a string not containing a word.

The problem (for me) is that the solutions given don't work in R.

Often I create a data.frame() from existing vectors and want to clean up my workspace. So for example, if my workspace contains:

> ls()
[1] "A"   "B"   "dat" "V"
>

and I want to retain only dat, I'd have to clean it up with:

> rm(list=ls(pattern="A"))
> rm(list=ls(pattern="B"))
> rm(list=ls(pattern="V"))
> ls()
[1] "dat"
> 

(where A, B, and V are just examples of a large number of complicated names like my.first.vector that are not easy to match with rm(list=ls(pattern="[ABV]"))).

It would be most convenient (for me) to tell rm() to remove everything except dat, but the problem is that the solution given in the linked Q&A does not work:

> rm(list=ls(pattern="^((?!dat).)*$"))
Error in grep(pattern, all.names, value = TRUE) : 
  invalid regular expression '^((?!dat).)*$', reason 'Invalid regexp'
> 

So how can I match everything except dat in R?

Community
  • 1
  • 1

2 Answers2

4

Negative look-around requires perl=TRUE argument in R. So, you won't be able to directly use ls(pattern = ...) with that regular expression. Alternatively you can do:

rm(list = grep("^((?!dat).)*$", ls(), perl=TRUE, value=TRUE))

This is if you're looking for inexact matches. If you're looking for exact match, you should just do what Ferdinand has commented:

rm(list=ls()[ls() != "dat"])
Arun
  • 116,683
  • 26
  • 284
  • 387
  • 2
    First sentence seems to be ignoring the fact that the R `grep` function has an invert parameter: `rm(list=grep("dat", ls(), value=TRUE, invert=TRUE))`. This would keep any that had "dat" in the name or you could use the "^dat$" pattern if you wanted to be less inclusive. (I would think one would need to be more selective and only remove non-functions.) – IRTFM Jul 03 '13 at 18:38
  • @DWin, very much true. I was just taking his regular expression and showing how to do it in R. I did not put effort in formulating a regexp. – Arun Jul 03 '13 at 19:57
4

This will remove all objects except dat . (Use the ls argument all.names = TRUE if you want to remove objects whose names begin with a dot as well.)

rm( list = setdiff( ls(), "dat" ) )

Replace "dat" with a vector of names, e.g. c("dat", "some.other.object"), if you want to retain several objects; or, if the several objects can all be readily matched by a regular expression try something like this which removes all objects whose names do not start with "dat":

rm( list = setdiff( ls(), ls( pattern = "^dat" ) ) )

Another approach is to save the data, save("dat", file = "dat.RData"), exit R, start a new R session and load the data, 1oad("dat.RData"). Also note this method of restarting R.

Community
  • 1
  • 1
G. Grothendieck
  • 254,981
  • 17
  • 203
  • 341
  • I would not want to exit R just to clear my work space. –  Jul 03 '13 at 17:01
  • @what, Personally, I try not to use `rm` and prefer to start a clean R session. If you write your software in a reproducible manner then its just a matter of rerunning your script. – G. Grothendieck Jul 03 '13 at 17:07
  • Yes, but some of my scripts load a lot of data (from an URL or from an Excel Workbook), or write a lot of files, and execution takes a couple of seconds. Also, I love the flexibility that your solution of adding a vector gives, because it allows me to delete everything left over from the creation of my `data.frame()` *and* keeping everything else I have kept up to that point, and those "leftovers" would be lost after exiting R, or I would have to save them also, which might make the whole process a bit cumbersome. –  Jul 03 '13 at 17:13