Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

!!! (splice operator) for ggplot2 geom_point() function

Tags:

r

ggplot2

rlang

I am using !!! (splice operator/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)
like image 409
toshi-san Avatar asked Dec 02 '21 15:12

toshi-san


2 Answers

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).

like image 183
Konrad Rudolph Avatar answered Oct 23 '22 09:10

Konrad Rudolph


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.

like image 20
Artem Sokolov Avatar answered Oct 23 '22 10:10

Artem Sokolov