Home > front end >  !!! (big bang operator) for ggplot2 geom_point() function
!!! (big bang operator) for ggplot2 geom_point() function

Time:12-03

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.

  • Related