ggplot2的geom_point()函数中的splice运算符是什么?

5

我在使用 !!!(切片运算符 / 大感叹号运算符)来调用 ggplot2::geom_point() 函数,但却失败了。能否有人指出这段代码哪里出错了?以下代码试图从字符向量中执行 ggplot2 函数。

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)
  • 输出
Error in !params_lang : invalid argument type
Calls: <Anonymous> -> layer
Execution halted

(注意) 下面的代码是一个交互式等效代码,它展示了我想在上面的代码中做的事情。
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)

为了提高搜索性能,此运算符的官方名称现在是splice operator - Konrad Rudolph
2个回答

5
这些元编程运算符,包括{{…}}!!!!!,只能在准引用函数中使用。也就是说,函数的参数明确支持整洁评估。通常,这样的函数将在其文档中明确提到准引用的支持。
其中包括ggplot2::aes函数,因为它通常使用自己的参数评估方法。但其他“ggplot2”函数(包括ggplot2::geom_point)会执行标准的参数评估,因此不支持任何这些伪操作符。
如果您想动态构建对此函数的调用,则需要采用传统路线,例如通过(基本R)do.call或(‘rlang’)exec(或手动使用call+eval/call2+eval_tidy)。

谢谢您的解释。它真正澄清了为什么splice运算符(!!!)只适用于ggplot2::aes。最终,rlang::exec("geom_point", !!!params_lang)在我的情况下起作用了! - toshi-san

2

Konrad解释了函数失败的原因,做得非常好。我只想提一下rlang::inject(),它允许您将准引用/非标准评估引入任何函数:

gg = gg + rlang::inject(ggplot2::geom_point( !!! params_lang ))

plot(gg)   # Now works

作为一个旁注,你的"This works"例子实际上是一个非常优雅的回答相关问题的方法。

rlang::inject() 很好用,谢谢! - toshi-san
2
关于 ggplot2::ggplot(data, ggplot2::aes( ,, !!! assoc_lang )),我参考了这个帖子 https://github.com/tidyverse/ggplot2/issues/2675 。 - toshi-san

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接