I'm trying to create a wrapper around the ggplot
that allows me to add some aesthetics like the x variable or color but always prefills y
, ymin
and ymax
without having to work with quoted variable names.
Since ggplot2 cannot use tidy evaluation I have to use NSE for this but I'm stuck, the information I could find here and here and inspecting some functions made me try things like unlist(...)
and working with match.call()
. but they only throw different errors.
In the below function I'd basically like to be able to call ci_plot()
or for example ci_plot(color = cyl)
library(dplyr)
library(ggplot2)
library(purrr)
library(tidyr)
ci_plot <- function(data, ...) {
ggplot(data, aes(..., y = y, ymin = ymin, ymax = ymax))
}
mpg %>%
group_by(manufacturer) %>%
nest() %>%
mutate(x = map(data, ~mean_se(.x$hwy))) %>%
unnest(x) %>%
ci_plot() +
geom_pointrange()
After some more digging I found shadow's answer here and figured out how to adapt it for my purpose. I'll try to outline the solution as much as I understand it.
ci_plot <- function(data, ...) {
# Create a list of unevaluated parameters,
# removing the first two, which are the function itself and data.
arglist <- as.list(match.call()[-c(1,2)])
# We can add additional parameters to the list using substitute
arglist$ymin = substitute(ymin)
arglist$y = substitute(y)
arglist$ymax = substitute(ymax)
# I suppose this allows ggplot2 to recognize that it needs to quote the arguments
myaes <- structure(arglist, class="uneval")
# And this quotes the arguments?
myaes <- ggplot2:::rename_aes(myaes)
ggplot(data, myaes)
}
That function allows me to write the code like this
mpg %>%
group_by(manufacturer, cyl) %>%
nest() %>%
mutate(x = map(data, ~mean_se(.x$hwy))) %>%
unnest(x) %>%
ci_plot(x = cyl, color = manufacturer) +
geom_pointrange()