I am using !!! (big bang operator) for ggplot2::geom_point() function, and it fails. Could someone point out what is wrong with this code? The following code tries to execute ggplot2 functions from character vectors.
library(rlang)
library(ggplot2)
data(mtcars)
data = mtcars
assoc = c( "cyl" , "hp" )
names(assoc) = c("x", "y")
assoc_lang = rlang::parse_exprs(assoc)
gg = ggplot2::ggplot(data, ggplot2::aes( ,, !!! assoc_lang )) # This works
params = c( "10", "\"black\"" )
names(params) = c("size", "colour" )
params_lang = rlang::parse_exprs(params)
gg = gg ggplot2::geom_point( !!! params_lang ) # This fails
plot(gg)
- output
Error in !params_lang : invalid argument type
Calls: <Anonymous> -> layer
Execution halted
(NOTE) The following code is an equivalent one in an interactive manner, which shows what I want to do in the above code.
library(ggplot2)
data(mtcars)
data = mtcars
gg = ggplot2::ggplot(data, ggplot2::aes( x = cyl , y = hp ))
gg = gg ggplot2::geom_point( size = 10, colour = "black")
plot(gg)
CodePudding user response:
These metaprogramming operators, including {{…}}
, !!
and !!!
only work in quasiquotation functions. That is, functions whose arguments explicitly support tidy evaluation. In general, such function will explicitly mention quasiquotation support in their documentation.
Amongst these functions is ggplot2::aes
, because it generally uses non-standard evaluation of its arguments. But other ‘ggplot2’ functions (including ggplot2::geom_point
) perform standard evaluation of their arguments, and thus do not support any of these pseudo-operators.
If you want to dynamically construct a call to this function, you’ll need to go the conventional route, e.g. via (base R) do.call
, or (‘rlang’) exec
(or, manually, via call
eval
/call2
eval_tidy
).
CodePudding user response:
Konrad did an excellent job explaining why the function fails. I just want to make note of rlang::inject()
, which allows you to introduce quasiquotation / non-standard evaluation to any function:
gg = gg rlang::inject(ggplot2::geom_point( !!! params_lang ))
plot(gg) # Now works
As a side note, your "This works" example is actually a very elegant answer to a related question.