9

While testing a simulation in R using randomly generated input data, I have found and fixed a few bugs and would now like to re-run the simulation with the same data, but with all intermediate variables removed to ensure it's a clean test.

Is there a way to remove several dozen manually selected variables from the workspace without having to: a) clobber the entire workspace, e.g. rm(list=ls()), or b) type each variable name, e.g. remove(name1, name2, ...)?

Ideal solution would be to use ls() to inspect the definitions and then pick out the indices of the ones I want to remove, e.g.

ls()                        # inspect definitions
delme <- c(3,5,7:9,11,13)   # names selected for removal
remove(ls()[delme])         # DESIRED SOLUTION -- doesn't quite work this way

(In hindsight, I should have used a fixed seed to generate the random input data, which allow clearing everything and then re-running the test...)

braX
  • 11,506
  • 5
  • 20
  • 33
Assad Ebrahim
  • 6,234
  • 8
  • 42
  • 68
  • 5
    Why doesn't `rm(list=ls()[delme])` not work? – BrodieG Feb 10 '14 at 13:11
  • if you use the `gdata` package and then `keep(ls()[-delme], sure = TRUE)` what happens? – Mehdi Nellen Feb 10 '14 at 13:17
  • @BrodieG: Great that works! --- the key was `list=`. Just for information, why is the assignment to list required? (PS if you want to put it in an answer, I'm happy to accept it!) – Assad Ebrahim Feb 10 '14 at 13:19
  • 2
    @AssadEbrahim, because if you don't do that it `rm` thinks that the first argument is the actual object to remove, as opposed to a list of the names of objects to remove (compare `rm(a, b)` vs `rm(list=c("a", "b"))`) – BrodieG Feb 10 '14 at 13:21
  • Maybe it comes useful this function to select the objects you want to delete, from the last check you did: http://stackoverflow.com/a/20141107/2886003 So if it doesn't follow a pattern, or if you want to avoid creating the vector it is done. – llrs Feb 10 '14 at 13:42

4 Answers4

7

There is a much simpler and more direct solution:

vars.to.remove <- ls()
vars.to.remove <- temp[c(1,2,14:15)]
rm(list = vars.to.remove)

Or, better yet, if you are good about variable naming schemes, you can use the following pattern matching strategy:

E.g. I name all temporary variables with the starting string "Temp." ... so, you can have Temp.Names, Temp.Values, Temp.Whatever

The following produces the list of variables that match this pattern

ls(pattern = "^Temp\\.")

So, you can remove all unneeded variables using ONE line of code, as follows:

rm(list = ls(pattern = "^Temp\\."))

Hope this helps.

HoneyBuddha
  • 748
  • 8
  • 15
  • Clarification on the search pattern: (1) The "^" makes sure that you only select variables that start with Temp (so, a variable like "Not.Temp" would not show up. (2) To search for "Temp" followed by "." you need to escape the "." by using "\\." – HoneyBuddha Aug 27 '20 at 08:57
6

Assad, while I think the actual answer to the question is in the comments, let me suggest this pattern as a broader solution:

rm(list=
  Filter(
    Negate(is.na),                                  # filter entries corresponding to objects that don't meet function criteria   
    sapply(
      ls(pattern="^a"),                             # only objects that start with "a"
      function(x) if(is.matrix(get(x))) x else NA   # return names of matrix objects
) ) )

In this case, I'm removing all matrix object that start with "a". By modifying the pattern argument and the function used by sapply here, you can get pretty fine control over what you delete, without having to specify many names.

If you are concerned that this could delete something you don't want to delete, you can store the result of the Filter(... operation in a variable, review the contents, and then execute the rm(list=...) command.

BrodieG
  • 51,669
  • 9
  • 93
  • 146
  • Great addition -- I can see the power of this as a general pattern, including how to select using regular expressions (+1) (Though it's no longer a simple tool as you say.) – Assad Ebrahim Feb 10 '14 at 13:28
0

Try

eval(parse(text=paste("rm(",paste(ls()[delme],sep=","),")")))

Rufo
  • 524
  • 1
  • 3
  • 18
  • 4
    Except in very specific circumstances (i.e., if you must evaluate arbitrary user input), you should never use `eval(parse(...))`. – Roland Feb 10 '14 at 13:34
  • 3
    Because it usually results in code that is impossible to read and maintain and there are **always** better alternatives. – Roland Feb 10 '14 at 15:25
0

I had a similar requirement. I pulled all the elements I needed to a list:

varsToPurge = as.list(ls())

I then reassign the few values I wish to keep with new variable names which will not be in the variable varsToPurge. After that I looped through the elements

for (j in 1:length(varsToPurge)){
  rm(list = as.character(varsToPurge[j]))
}

Do a little garbage collecting, and you maintain a clean environment as you go through your code.

gc()

You can also use a vector of row numbers you wish to keep instead and run through the vector in the loop but it won't be as dynamic if you add rough work you wish to remove.

Wes Sauder
  • 39
  • 6