Search code examples
rggplot2layerprotoggproto

How to determine the geom type of each layer of a ggplot2 object?


As part of an effort to remove a specific geom from a plot I've already created (SO link here), I'd like to dynamically determine the geom type of each layer of a ggplot2 object.

Assuming I don't know the order in which I added layers, is there a way to dynamically find layers with a specific geom? If I print out the layers like I do below I can see that the layers are stored in a list, but I can't seem to access the geom type.

library(ggplot2)
dat <- data.frame(x=1:3, y=1:3, ymin=0:2, ymax=2:4)
p <- ggplot(dat, aes(x=x, y=y)) + geom_ribbon(aes(ymin=ymin, ymax=ymax), alpha=0.3) + geom_line()
p$layers

[[1]]
mapping: ymin = ymin, ymax = ymax 
geom_ribbon: na.rm = FALSE, alpha = 0.3 
stat_identity:  
position_identity: (width = NULL, height = NULL)

[[2]]
geom_line:  
stat_identity:  
position_identity: (width = NULL, height = NULL)

I'm not familiar with proto objects and things I've tried from the proto documentation don't seem to work (e.g. p$layers[[1]]$str()).


Thanks to the answers below I was able to come up with a function that removes a layer dynamically:

remove_geom <- function(ggplot2_object, geom_type) {
  layers <- lapply(ggplot2_object$layers, function(x) if(x$geom$objname == geom_type) NULL else x)
  layers <- layers[!sapply(layers, is.null)]

  ggplot2_object$layers <- layers
  ggplot2_object
}

Solution

  • ggplot 2.2 update: If what you want is a character string naming the geom type, you can use:

    sapply(p$layers, function(x) class(x$geom)[1])
    

    which yields the first class name for the geom object of each layer. In the OP's example:

    [1] "GeomRibbon" "GeomLine" 
    

    The code in the answers above no longer give the results shown for version 2.2 The accepted answer yields two NULL values, and the other answer yields full ggproto objects.