12

Assume you are working with a large working environment and you aren't great about keeping up with your environment variables, or you have some process that generates a lot objects automatically. Is there a way to scan your ls() to identify all objects that have a given class? Consider the following simple example:

#Random objects in my environment
x <- rnorm(100)
y <- rnorm(100)
z <- rnorm(100)

#I estimate some linear models for fun.
lm1 <- lm(y ~ x)
lm2 <- lm(y ~ z)
lm3 <- lm(y ~ x + z)

#Is there a programmatic way to identify all objects in my environment 
#that are of the "lm" class? Or really, any arbitrary class?
outList <- list(lm1, lm2, lm3)

#I want to look at a bunch of plots for all the lm objects in my environment.
lapply(outList, plot)
Chase
  • 67,710
  • 18
  • 144
  • 161

2 Answers2

17

Use the class function:

Models <- Filter( function(x) 'lm' %in% class( get(x) ), ls() )
lapply( Models, function(x) plot( get(x) ) )

(Modified slightly to handle situations where objects can have multiple classes, as pointed out by @Gabor in the comments).

Update. For completeness, here is a refinement suggested by @Gabor's comment below. Sometimes we may want to only get objects that are of class X but not class Y. Or perhaps some other combination. For this one could write a ClassFilter() function that contains all of the class filterling logic, such as:

ClassFilter <- function(x) inherits(get(x), 'lm' ) & !inherits(get(x), 'glm' )

Then you get the objects that you want:

Objs <- Filter( ClassFilter, ls() )

Now you can process the Objs whatever way you want.

Prasad Chalasani
  • 19,912
  • 7
  • 51
  • 73
  • 1
    Thanks @Prasad! It was the `Filter` part of that I wasn't aware of previously. That's pretty slick. – Chase Mar 01 '11 at 19:05
  • Thanks, I just discovered `Filter` while looking at `?Reduce`, and it's nice because you don't need to first do `objs <- ls()`, and then extract the ones whose class is `lm`. – Prasad Chalasani Mar 01 '11 at 19:09
  • 1
    Note that the above assumes that all objects have a single class but some objects may have a vector of classes such as `"glm"` objects which have the class vector: `c("glm", "lm")`, i.e.`"glm"` objects are also `"lm"` objects. If you had such an object in your workspace the above would give an error. In addition, depending on whether you wanted to include or exclude `"glm"` objects the answer would be slightly different. – G. Grothendieck Mar 01 '11 at 20:25
  • Good point, I changed the code slightly to test for membership rather than equality, which should handle your first comment. Further refinements should be easy to do from this. – Prasad Chalasani Mar 01 '11 at 20:32
  • `inherits(get(x), "lm")` might be more generally applied than searching through the class of objects? – Gavin Simpson Mar 01 '11 at 20:49
  • @Prasad. To be complete I think you need to address both situations: the situation where `"lm`" is an element of the class vector and the situation where `"lm"` is the only class in the class vector. We don't know which one the poster wants but he may very well only want objects which are `"lm"` objects that are not `"glm"` objects. – G. Grothendieck Mar 01 '11 at 20:52
  • @Gabor - that is a good point, and I can imagine there are lots of other objects in the R-world that contain multiple `class`es, though I'm not that familiar with them. It seems we should be able to add other logical conditions into the anonymous function to suit our needs, right? Maybe something like: `function(x) 'lm' %in% class( get(x) ) & 'glm' %in% class( get(x) ) == FALSE`? I imagine there may be a more efficient way to say "not in", but I'm not familiar with that construct in R. – Chase Mar 01 '11 at 21:11
  • @Gavin, yes I like `inherits` better, thanks for pointing out. – Prasad Chalasani Mar 01 '11 at 22:02
0

You can use Filter with inherits and ls in mget to get a named list of in this case of lm objects.

L <- Filter(\(x) inherits(x, "lm"), mget(ls()))
#L <- Filter(\(x) inherits(x, "lm") & !inherits(x, "glm"), mget(ls())) #In case glm need to be excluded

identical(unname(L), outList)
#[1] TRUE

lapply(L, plot)
GKi
  • 37,245
  • 2
  • 26
  • 48