Remove a layer from a ggplot2 chart

ggplot layer order
ggplot remove group
ggplot2 remove elements
delete label ggplot
remove ggplot layer
ggplot remove axis lines
remove title from ggplot
remove y axis label ggplot2

I'd like to remove a layer (in this case the results of geom_ribbon) from a ggplot2 created grid object. Is there a way I can remove it once it's already part of the object?

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()

# This has the geom_ribbon
p

# This overlays another ribbon on top
p + geom_ribbon(aes(ymin=ymin, ymax=ymax, fill=NA))

I'd like this functionality to allow me to build more complicated plots on top of less complicated ones. I am using functions that return a grid object and then printing out the final plot once it is fully assembled. The base plot has a single line with a corresponding error bar (geom_ribbon) surrounding it. The more complicated plot will have several lines and the multiple overlapping geom_ribbon objects are distracting. I'd like to remove them from the plots with multiple lines. Additionally, I'll be able to quickly create alternative versions using facets or other ggplot2 functionality.


Edit: Accepting @mnel's answer as it works. Now I need to determine how to dynamically access the geom_ribbon layer, which is captured in the SO question here.


Edit 2: For completeness, this is the function I created to solve this problem:

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
}

Edit 3: See the accepted answer below for the latest versions of ggplot (>=2.x.y)

For ggplot2 version 2.2.1, I had to modify the proposed remove_geom function like this:

remove_geom <- function(ggplot2_object, geom_type) {
  # Delete layers that match the requested type.
  layers <- lapply(ggplot2_object$layers, function(x) {
    if (class(x$geom)[1] == geom_type) {
      NULL
    } else {
      x
    }
  })
  # Delete the unwanted layers.
  layers <- layers[!sapply(layers, is.null)]
  ggplot2_object$layers <- layers
  ggplot2_object
}

Here's an example of how to use it:

library(ggplot2)

set.seed(3000)
d <- data.frame(
  x = runif(10),
  y = runif(10),
  label = sprintf("label%s", 1:10)
)

p <- ggplot(d, aes(x, y, label = label)) + geom_point() + geom_text()

Let's show the original plot:

p

Now let's remove the labels and show the plot again:

p <- remove_geom(p, "GeomText")
p

Remove geom(s) from an existing ggplot chart?, You can access / manipulate g 's elements the way you would do with other R object. g$layers #[[1]] #geom_point: na.rm = FALSE  I'd like to remove a layer (in this case the results of geom_ribbon) from a ggplot2 created grid object. Is there a way I can remove it once it's already part of the object?

If you look at

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)

You will see that you want to remove the first layer

You can do this by redefining the layers as just the second component in the list.

p$layer <- p$layer[2]

Now build and plot p

p

Note that p$layer[[1]] <- NULL would work as well. I agree with @Andrie and @Joran's comments regarding in wehat cases this might be useful, and would not expect this to be necessarily reliable.

remove_geom: Remove a layer from a compiled ggplot2 object. in , p. ggplot2 plot object. geom. character string of the name of the layer to remove. idx. numeric of which index of geom to remove, Default: 1  Loading required package: shiny Loading required package: shinyBS Loading required package: ggplot2 Loading required package: dplyr Attaching package: 'dplyr' The following objects are masked from 'package:stats': filter, lag The following objects are masked from 'package:base': intersect, setdiff, setequal, union.

As this problem looked interesting, I have expanded my 'ggpmisc' package with functions to manipulate the layers in a ggplot object (currently in package 'gginnards'). The functions are more polished versions of the example in my earlier answer to this same question. However, be aware that in most cases this is not the best way of working as it violates the Grammar of Graphics. In most cases one can assemble different variations of the same figure in the normal way with operator +, possibly "packaging" groups of layers into lists to have combined building blocks that can simplify the assembly of complex figures. Exceptionally we may want to edit an existing plot or a plot output by a higher level function that whose definition we cannot modify. In such cases these layer manipulation functions can be useful. The example above becomes.

library(gginnards)
p1 <- delete_layers(p, match_type = "GeomText")

See the documentation of the package for other examples, and for information on the companion functions useful for modifying the ordering of layers, and for inserting new layers at arbitrary positions.

User Guide: 2 Manipulating ggplots, autoplot() or other functions that automatically produce a full plot using 'ggplot2' internally, one may need to add, move or delete layers so as  Of course, removing unused data means that they will not be available at a later time if we want to add more layers to the same saved ggplot object. It was not clear to me when R does make a copy of the data embedded in a ggplot object and when not. R’s policy is to copy data objects lazily, or only when modified.

@Kamil Slowikowski Thanks! Very useful. However I could not stop myself from creating a new variation on the same theme... hopefully easier to understand than that in the original post or the updated version by Kamil, also avoiding some assignments.

remove_geoms <- function(x, geom_type) {
  # Find layers that match the requested type.
  selector <- sapply(x$layers,
                     function(y) {
                       class(y$geom)[1] == geom_type
                     })
  # Delete the layers.
  x$layers[selector] <- NULL
  x
}

This version is functionally identical to Kamil's function, so the usage example above does not need to be repeated here.

As an aside, this function can be easily adapted to select the layers based on the class of the stat instead of the class of the geom.

remove_stats <- function(x, stat_type) {
  # Find layers that match the requested type.
  selector <- sapply(x$layers,
                     function(y) {
                       class(y$stat)[1] == stat_type
                     })
  # Delete the layers.
  x$layers[selector] <- NULL
  x
}

Remove a layer from a compiled ggplot2 object., p. ggplot2 plot object. geom. character string of the name of the layer to remove. idx. numeric of which index of geom to remove  I'm trying to keep the legend of one layer (smooth) and remove the legend of the other (point). I have tried shutting off the legends with guides (colour = FALSE) and geom_point (aes (color = vs), show.legend = FALSE). Edit: As this question and its answers are popular, a reproducible example seems in order: A minimal reproducible example would

@Kamil and @Pedro Thanks a lot! For those interested, one can also augment Pedro's function to select only specific layers, as shown here with a last_only argument:

remove_geoms <- function(x, geom_type, last_only = T) {
  # Find layers that match the requested type.
  selector <- sapply(x$layers,
                     function(y) {
                       class(y$geom)[1] == geom_type
                     })
  if(last_only) 
    selector <- max(which(selector))
  # Delete the layers.
  x$layers[selector] <- NULL
  x
}

Coming back to @Kamil's example plot:

set.seed(3000)
d <- data.frame(
  x = runif(10),
  y = runif(10),
  label = sprintf("label%s", 1:10)
)

p <- ggplot(d, aes(x, y, label = label)) + geom_point() + geom_point(color = "green") + geom_point(size = 5, color = "red")

p

p %>% remove_geoms("GeomPoint")

p %>% remove_geoms("GeomPoint")  %>% remove_geoms("GeomPoint")

Remove and replace ggplot2 layers., Removes specified layers from a ggplot object and gives the option to replace them ggplot2 plot object. oldGeom. character string of the name of the layer to remove. oldGeomIdx. numeric of which index of OldGeom to remove (default is 1)​. The basic concept of a ggplot2 graphic in R is that you combine different elements into layers. Each layer of a ggplot2 graphic contains information about the following: The data that you want to plot: For ggplot(), this must be a data frame. A mapping from the data to your plot: This usually is as […]

Remove elements from ggplot, Remove elements from ggplot. Ubiqum Code Academy. 1 Goal; 2 Drawing with ggplot; 3 Removing elements from the plot  A layer is a combination of data, stat and geom with a potential position adjustment. Usually layers are created using geom_* or stat_* calls but it can also be created directly using this function.

remove_geom function, Removes specified layers from a ggplot object. Remove a layer from a compiled ggplot2 object. Removes specified layers from a ggplot2 plot object. geom. # Bar charts are automatically stacked when multiple bars are placed # at the same location. The order of the fill is designed to match # the legend g + geom_bar ( aes ( fill = drv )) # If you need to flip the order (because you've flipped the orientation) # call position_stack() explicitly: ggplot ( mpg , aes ( y = class )) + geom_bar ( aes ( fill = drv ), position = position_stack ( reverse = TRUE )) + theme ( legend.position = "top" )

[PDF] Package 'gginnards', Delete, move or append one or more layers in a ggplot object. ://stackoverflow.​com/questions/13407236/remove-a-layer-from-a-ggplot2-chart. This is part 3 of a three part tutorial on ggplot2, an aesthetically pleasing (and very popular) graphics framework in R. This tutorial is primarily geared towards those having some basic knowledge of the R programming language and want to make complex and nice looking charts with R ggplot2.

Comments
  • Can you please describe a use case where you would use this?
  • Finding the particular layer inside p$layers and then obliterating it by assigning NULL to it would probably "work" but I make no predictions about reliability.
  • I guess I don't understand this right. If you have to have it, but don't want to see it, why not alpha = 0?
  • @Largh, the ggplot2 object has already been created with a geom_ribbon with an alpha value > 0. I need to dynamically access that layer and set alpha to 0 or remove it.
  • In principle, I think geom_blank should do this, but in practice that doesn't work for me.
  • This was my thought too, but I haven't tested it in more complex situations where the layer you're deleting may have had associated scales, legends, etc.
  • If you look at how ggplot_build works, it bases everything on the layers component of the plot, so it should be reasonably robust (unless you were using qplot, the inner workings of which I haven't investigated.)
  • I think you may be right; at least my initial tests with some more complicated plots seemed to all work out ok.
  • Thanks. Is there a way to dynamically find the geom_ribbon layer? I'm not used to working with proto objects.
  • I see you've asked the layer identification as another question. A good idea. My experience with proto is limited at best.
  • I have moved the low level functions from 'ggpmisc' into a new package 'gginnards' accepted today in CRAN.