Tom*_*mmy 12 r ggplot2 non-standard-evaluation tidyverse rlang
我正在尝试创建一个用于创建棒棒糖图的函数ggplot2。我想将所有参数传递...到aes()inside geom_point()。但是,我想排除size传递到aes()内部的参数geom_segment()(如果您查看a()下面的输出,原因很明显)。因此,我捕获...usingrlang::enquos()而不是按原样传递它。在功能上a(),我传递dots到aes()内ggplot()这个作品没有问题。但在功能上b()我得到了错误Can't use '!!!' at top level.
我被困在这一点上,并感谢任何输入来解决这个问题。
library(ggplot2)
data("mtcars")
d <- dplyr::count(mtcars, cyl, am)
a <- function(data, x, y, ...) {
x <- rlang::enquo(x)
y <- rlang::enquo(y)
dots <- rlang::enquos(...)
ggplot(data, aes(!!x, !!y, !!!dots)) +
geom_segment(aes(y = 0, xend = !!x, yend = !!y)) +
geom_point()
}
b <- function(data, x, y, ...) {
x <- rlang::enquo(x)
y <- rlang::enquo(y)
dots <- rlang::enquos(...)
segment_args <- dots[names(dots) != "size"]
ggplot(data, aes(!!x, !!y)) +
geom_segment(aes(y = 0, xend = !!x, yend = !!y, !!!segment_args)) +
geom_point(aes(!!!dots))
}
a(d, cyl, n, color = factor(am), size = am)
Run Code Online (Sandbox Code Playgroud)

b(d, cyl, n, color = factor(am), size = am)
#> Error: Can't use `!!!` at top level.
Run Code Online (Sandbox Code Playgroud)
这是我的sessionInfo():
R version 3.5.2 (2018-12-20)
Platform: x86_64-apple-darwin16.7.0 (64-bit)
Running under: macOS Sierra 10.12.1
Matrix products: default
BLAS: /System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/libBLAS.dylib
LAPACK: /usr/local/Cellar/openblas/0.3.5/lib/libopenblasp-r0.3.5.dylib
locale:
[1] en_US.UTF-8/en_US.UTF-8/en_US.UTF-8/C/en_US.UTF-8/en_US.UTF-8
attached base packages:
[1] stats graphics grDevices utils datasets methods
[7] base
other attached packages:
[1] ggplot2_3.2.1
loaded via a namespace (and not attached):
[1] Rcpp_1.0.3 digest_0.6.18 withr_2.1.2
[4] assertthat_0.2.0 crayon_1.3.4 dplyr_0.8.3
[7] grid_3.5.2 R6_2.3.0 gtable_0.2.0
[10] magrittr_1.5 scales_1.0.0 pillar_1.4.2
[13] rlang_0.4.2 lazyeval_0.2.1 rstudioapi_0.10
[16] labeling_0.3 tools_3.5.2 glue_1.3.0
[19] purrr_0.3.3 munsell_0.5.0 compiler_3.5.2
[22] pkgconfig_2.0.2 colorspace_1.4-0 tidyselect_0.2.5
[25] tibble_2.1.3
Run Code Online (Sandbox Code Playgroud)
Tom*_*mmy 10
显然,这是一个已知问题,aes()您可以在此处验证。解决方法是这样的:
b <- function(data, x, y, ...) {
x <- rlang::enquo(x)
y <- rlang::enquo(y)
dots <- rlang::enquos(...)
segment_args <- dots[names(dots) != "size"]
ggplot(data, aes(!!x, !!y)) +
geom_segment(aes(, y = 0, xend = !!x, yend = !!y, !!!segment_args)) +
geom_point(aes(, , !!!dots))
}
Run Code Online (Sandbox Code Playgroud)
注意 中的单逗号geom_segment()和 中的双逗号geom_point()。