Reputation: 8523
I have a collection of ggplots that I want to explore. The creation of these ggplots is complicated, and it would be hard for me to change the way they are made.
My goal is to subset a plot to show only one color group, like it is done using plotly::ggplotly()
(HTML plots).
I expect it should be similar to the way we subset a plot to the x
dimension using xlim()
, but for the color
dimension.
However, it seems that it does not seem to work the same way.
Here is a reproducible example with expected output:
library(tidyverse)
p = ggplot(mtcars, aes(mpg, wt, color=factor(cyl))) +
geom_point()
#initial plot
p
#subset on x
p + lims(x=c(15,20)) #same as xlim(15, 20)
#> Warning: Removed 19 rows containing missing values (geom_point).
#subset on color (fail)
p + lims(color="6")
#expected output (without data manipulation)
ggplot(mtcars %>% filter(cyl==6),
aes(mpg, wt, color=factor(cyl))) +
geom_point()
Created on 2022-01-30 by the reprex package (v2.0.1)
As you can see, instead of subsetting on color, it only removed the color attribute.
Note that, with the x
dimension there was a warning about removing values, whereas there was not with the color
dimension.
Is there a way to subset the plot after its creation?
Upvotes: 1
Views: 394
Reputation: 8523
Using @Allan's answer and some other, I could make a one-liner out of my problem:
library(tidyverse)
p = ggplot(mtcars, aes(mpg, wt, color=factor(cyl))) +
geom_point()
p %+% filter(p$data, cyl==6)
Created on 2022-01-30 by the reprex package (v2.0.1)
Upvotes: 1
Reputation: 174348
Each ggplot
object has a member called data
, which is a data frame you can filter, so you could create a little function that filters based on existing variables:
filter_ggplot <- function(p, predicate) {
predicate <- match.call()$predicate
backup <- p$data
p$data <- p$data[with(backup, eval(predicate)),]
print(p)
p$data <- backup
invisible(p)
}
This allows:
p
p %>% filter_ggplot(cyl == 6)
p %>% filter_ggplot(cyl == 4)
Created on 2022-01-30 by the reprex package (v2.0.1)
Upvotes: 3