I have a workspace with lots of objects and I would like to remove all but one. Ideally I would like to avoid having to type rm(obj.1, obj.2... obj.n). Is it possible to indicate remove all objects but these ones?
Here is a simple construct that will do it, by using setdiff:
rm(list=setdiff(ls(), "x"))
And a full example. Run this at your own risk - it will remove all variables except x:
x <- 1
y <- 2
z <- 3
ls()
[1] "x" "y" "z"
rm(list=setdiff(ls(), "x"))
ls()
[1] "x"
Using the keep function from the gdata package is quite convenient.
> ls()
[1] "a" "b" "c"
library(gdata)
> keep(a) #shows you which variables will be removed
[1] "b" "c"
> keep(a, sure = TRUE) # setting sure to TRUE removes variables b and c
> ls()
[1] "a"
I think another option is to open workspace in RStudio and then change list to grid at the top right of the environment(image below). Then tick the objects you want to clear and finally click on clear.
I just spent several hours hunting for the answer to a similar but slightly different question - I needed to be able to delete all objects in R (including functions) except a handful of vectors.
One way to do this:
rm(list=ls()[! ls() %in% c("a","c")])
Where the vectors that I want to keep are named 'a' and 'c'.
Hope this helps anyone searching for the same solution!
To keep all objects whose names match a pattern, you could use grep, like so:
to.remove <- ls()
to.remove <- c(to.remove[!grepl("^obj", to.remove)], "to.remove")
rm(list=to.remove)
Replace v with the name of the object you want to keep
rm(list=(ls()[ls()!="v"]))
hat-tip: http://r.789695.n4.nabble.com/Removing-objects-and-clearing-memory-tp3445763p3445865.html
To keep a list of objects, one can use:
rm(list=setdiff(ls(), c("df1", "df2")))
This takes advantage of ls()'s pattern option, in the case you have a lot of objects with the same pattern that you don't want to keep:
> foo1 <- "junk"; foo2 <- "rubbish"; foo3 <- "trash"; x <- "gold"
> ls()
[1] "foo1" "foo2" "foo3" "x"
> # Let's check first what we want to remove
> ls(pattern = "foo")
[1] "foo1" "foo2" "foo3"
> rm(list = ls(pattern = "foo"))
> ls()
[1] "x"
require(gdata)
keep(object_1,...,object_n,sure=TRUE)
ls()
From within a function, rm all objects in .GlobalEnv except the function
initialize <- function(country.name) {
if (length(setdiff(ls(pos = .GlobalEnv), "initialize")) > 0) {
rm(list=setdiff(ls(pos = .GlobalEnv), "initialize"), pos = .GlobalEnv)
}
}
assuming you want to remove every object except df from environment:
rm(list = ls(pattern="[^df]"))
let's think in different way, what if we wanna remove a group?
try this,
rm(list=ls()[grep("xxx",ls())])
I personally don't like too many tables, variables on my screen, yet I can't avoid using them. So I name the temporary things starting with "xxx", so I can remove them after it is no longer used.
# remove all objects but selected
rm(list = ls()[which("key_function" != ls())])
How about this?
# Removes all objects except the specified & the function itself.
rme <- function(except=NULL){
except = ifelse(is.character(except), except, deparse(substitute(except)))
rm(list=setdiff(ls(envir=.GlobalEnv), c(except,"rme")), envir=.GlobalEnv)
}
The following will remove all the objects from your console
rm(list = ls())
Related
Within a loop, I try to remove a list of data frames simply with
rm(a,b,c,d)
However, in case an data-frame (e.g. b) does not exist in the global environment, I get a warning
In rm(a,b,c,d,...:
object 'b' not found
How can I suppress this warning to not pop-up?
Use suppressWarnings
suppressWarnings(rm(a,b,c,d))
#RonakShah has the correct answer here, though it is possible to avoid generating a warning at all by defining a function that checks for the existence of variables before trying to remove them:
rm2 <- function(...)
{
names <- sapply(as.list(match.call()[-1]), deparse);
rm(list = names[sapply(names, exists)], envir = parent.frame())
}
So you can do:
x <- 1; y <- 2;
ls()
#> [1] "rm2" "x" "y"
rm2(x, y, z) # Note no warning generated since no attempt made to remove z
ls()
[1] "rm2"
I feel like i've forgotten something very obvious here...
Let's say we have two lists, a and b, with differing lengths:
a <- list(me = "you1", they = "our1", our = "till1", grow = "NOPE1")
b <- list(me = "my2", their = "his2", our = "aft2", new = "noise2",
they = "now2", b_names = "thurs2")
We want to replace the items in a with corresponding items from b, if an item in b has the same name as an item in a.
Manually, essentially this would equate to replacing: me, our, they in list a from those items in list b.
For the life of me the only approach i'm coming up with is using Reduce rather than match or %chin% etc, to find the intersection of names and then always using the last list object as the look-up table. I suppose you really don't need to Reduce since intersect would work find on it's own.. but regardless...
Isn't there a simpler, more straight forward way that I am simply forgetting?
Here's my code.. it works..but that's not the point.
reduce.names <- function(...){
vars <- list(...)
if(length(vars) > 2){
return("only 2 lists allowed...")
}else {
Reduce(intersect, Map(names,vars))
}
}
> matched_names <- reduce.names(a,b)
> matched_names
[1] "me" "they" "our"
a[matched_names] <- b[matched_names]
> a
$me
[1] "my2"
$they
[1] "now2"
$our
[1] "aft2"
$grow
[1] "NOPE1"
here's another approach that works... but just seems redundant and sketchy...
> merge(a,b) %>% .[names(a)]
$me
[1] "my2"
$they
[1] "now2"
$our
[1] "aft2"
$grow
[1] "NOPE1"
Any advice/alternate approach/reminder of some base function I have completely forgotten would be greatly appreciated. Thanks.
This just took me two hours of debugging to identify:
> list1 = list() # empty list
> list1['first'] = list(a=list(a1='goat', a2='horse'), b=42) # double-nested
> print(list1$first$b)
NULL # Should be 42?
> print(list1) # let's check the actual contents of list1
$first
$first$a1 # how did the contents of the innermost a-list end up here?
[1] "goat"
$first$a2
[1] "horse"
In this case, the list assigned to 'first' becomes the list in a so b just disappears without warning. What is happening here, and where did the bvalue go?
I'm using R 3.0.2. How can I do something like this when R prevents me from doing the above?
As joran pointed out in a comment, the solution is to use double-brackets in the assignment:
list1[['first']] = list(a=list(a1='goat', a2='horse'), b=42)
Apparently you get a warning in newer R versions but not in older, if you use single-brackets.
i am trying to create a function in which i want to remove one of the variables passed to it.
now R works in annoying ways in that it copies the object instead of giving a reference.
(technically the copying only happens if you make a change... but meh...)
a=function(b){
rm(b)
# rm(b)
}
test=123
a(test) # will remove b, not test
# you can verify that by adding the 2nd rm(b)
i tried
a=function(b){
rm(match.call()[[2]])
}
but that gives the error:
Error in rm(match.call()[[3]]) :
... must contain names or character strings
Try this:
Foo <- function(x){
Sx <- deparse(substitute(x))
rm(list=Sx,envir=sys.frame(-1))
}
##
Z <- 123
ls()
##
[1] "Foo" "Z"
##
Foo(x=Z)
ls()
[1] "Foo"
similar to nrussell's answer, here's the line from cgwtools::askrm which does an arbitrary function call on the selected object:
call(fn, as.name(thenam)), envir = parent.frame(1))
(and, yes, I'm plugging my own toolkit here :-) )
Using a basic function such as this:
myname<-function(z){
nm <-deparse(substitute(z))
print(nm)
}
I'd like the name of the item to be printed (or returned) when iterating through a list e.g.
for (csv in list(acsv, bcsv, ccsv)){
myname(csv)
}
should print:
acsv
bcsv
ccsv
(and not csv).
It should be noted that acsv, bcsv, and ccsvs are all dataframes read in from csvs i.e.
acsv = read.csv("a.csv")
bcsv = read.csv("b.csv")
ccsv = read.csv("c.csv")
Edit:
I ended up using a bit of a compromise. The primary goal of this was not to simply print the frame name - that was the question, because it is a prerequisite for doing other things.
I needed to run the same functions on four identically formatted files. I then used this syntax:
for(i in 1:length(csvs)){
cat(names(csvs[i]), "\n")
print(nrow(csvs[[i]]))
print(nrow(csvs[[i]][1]))
}
Then the indexing of nested lists was utilized e.g.
print(nrow(csvs[[i]]))
which shows the row count for each of the dataframes.
print(nrow(csvs[[i]][1]))
Then provides a table for the first column of each dataframe.
I include this because it was the motivator for the question. I needed to be able to label the data for each dataframe being examined.
The list you have constructed doesn't "remember" the expressions it was constructed of anymore. But you can use a custom constructor:
named.list <- function(...) {
l <- list(...)
exprs <- lapply(substitute(list(...))[-1], deparse)
names(l) <- exprs
l
}
And so:
> named.list(1+2,sin(5),sqrt(3))
$`1 + 2`
[1] 3
$`sin(5)`
[1] -0.9589243
$`sqrt(3)`
[1] 1.732051
Use this list as parameter to names, as Thomas suggested:
> names(mylist(1+2,sin(5),sqrt(3)))
[1] "1 + 2" "sin(5)" "sqrt(3)"
To understand what's happening here, let's analyze the following:
> as.list(substitute(list(1+2,sqrt(5))))
[[1]]
list
[[2]]
1 + 2
[[3]]
sqrt(5)
The [-1] indexing leaves out the first element, and all remaining elements are passed to deparse, which works because of...
> lapply(as.list(substitute(list(1+2,sqrt(5))))[-1], class)
[[1]]
[1] "call"
[[2]]
[1] "call"
Note that you cannot "refactor" the call list(...) inside substitute() to use simply l. Do you see why?
I am also wondering if such a function is already available in one of the countless R packages around. I have found this post by William Dunlap effectively suggesting the same approach.
I don't know what your data look like, so here's something made up:
csvs <- list(acsv=data.frame(x=1), bcsv=data.frame(x=2), ccsv=data.frame(x=3))
for(i in 1:length(csvs))
cat(names(csvs[i]), "\n")