Context: I have a function that takes an object created with stats::lm()
as its main argument. The goal of this function is to make ggplots with only this lm
object. Warning: variables used in the model are NOT arguments of the function i.e. if the model is lmobj <- lm(y ~ x, data = df)
then the function only takes lmobj
as an argument. Indeed it is different from question like this one. Moreover, I am not looking for "ggplot only" solutions that take the raw data and compute regression line and scatterplot (e.g. ggplot2::geom_smooth(method = "lm")
).
Problem: ggplot()
geom functions have a x
and y
argument that require unquoted variables (see reference manual); how can I recover these from lmobj
?
Expected output:
library(ggplot2)
lmobj <- lm(Petal.Width ~ Petal.Length, data = iris)
myfun <- function(.lm) {
# make a scatterplot with .lm using ggplot
ggplot(data = .lm[["model"]], aes(x = Petal.Width, y = Petal.Length))
geom_point()
}
myfun(lmobj)
Trials and errors
I tried to grab an unquoted variable name from lmobject
using cat()
:
> cat(names(lmobj[["model"]][2]))
Petal.Length
But it creates an error:
> myfuntest <- function(.lm) {
# make a scatterplot with .lm using ggplot
ggplot(data = .lm[["model"]], aes(x = cat(names(.lm[["model"]][2])),
y = cat(names(.lm[["model"]][1]))))
geom_point()
}
> myfuntest(lmobj)
Petal.LengthPetal.WidthPetal.LengthPetal.WidthError: geom_point requires the following missing aesthetics: x and y
CodePudding user response:
The following works:
myfun <- function(model) {
coefs <- names(model$model)
ggplot(data = model$model)
aes(x = !! rlang::sym(coefs[1L]), y = !! rlang::sym(coefs[2L])))
geom_point()
}
The relevant point here is that aes
uses ‘rlang’s tidy evaluation and as such requires the arguments to be injected via !!
as names.
CodePudding user response:
One way to do it is to evaluate first the arguments of aes
as symbols and then call aes
by wrapping it into a do.call
myfun <- function(.lm) {
ggplot(data = .lm[["model"]],
do.call(aes, list(x = sym(names(.lm[["model"]])[2]),
y = sym(names(.lm[["model"]])[1]))))
geom_point()
}