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?
CodePudding user response:
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)
CodePudding user response:
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)
