在R ggplot自定义分面包装器中如何正确引用变量名
问题:ggplot自定义分面包装器的变量引用错误
我想为ggplot编写自定义分面包装器,但处理变量名时遇到问题。
我想要实现的效果如下:
mtcars %>% ggplot() + ggh4x::facet_manual(vars(cyl %>% recode('4' = "four", '6' = "six", '8' = "eight") %>% factor(levels = c("four", "six", "eight"))), design = matrix(c(1, 1, 2, 3), byrow = TRUE, nrow = 2), scales = "free") + geom_point(aes(x = disp, y = hp))
现在我尝试把这个复杂的分面逻辑封装成函数:
my_facet <- function(x) { ggh4x::facet_manual(vars(x %>% recode('4' = "four", '6' = "six", '8' = "eight") %>% factor(levels = c("four", "six", "eight"))), design = matrix(c(1, 1, 2, 3), byrow = TRUE, nrow = 2), scales = "free") } mtcars %>% ggplot() + my_facet(cyl) + geom_point(aes(x = disp, y = hp))
但运行时报错,提示找不到x:
Error in recode(., `4` = "four", `6` = "six", `8` = "eight") : object 'x' not found
我试过sym(x)、!!sym(x)、enquo(x)、{{x}}这些变量处理方式,但都没成功,请问该怎么解决?
解决方案
问题核心是vars()内部的表达式无法正确识别函数参数x对应的数据集变量,需要用rlang的准引用语法将变量引用注入到vars()的表达式中,以下两种方式均可解决:
方式1:使用enquo() + !!捕获并注入引用
先通过enquo()捕获参数的变量引用,再用!!将其注入到vars()的表达式中:
library(rlang) library(ggh4x) library(dplyr) my_facet <- function(x) { # 捕获参数对应的变量引用 x_var <- enquo(x) ggh4x::facet_manual( vars(!!x_var %>% recode('4' = "four", '6' = "six", '8' = "eight") %>% factor(levels = c("four", "six", "eight"))), design = matrix(c(1, 1, 2, 3), byrow = TRUE, nrow = 2), scales = "free" ) }
方式2:使用{{}}(整洁评估语法糖)
{{}}是enquo() + !!的简化写法,直接在vars()中替换x为{{x}}即可:
library(ggh4x) library(dplyr) my_facet <- function(x) { ggh4x::facet_manual( vars({{x}} %>% recode('4' = "four", '6' = "six", '8' = "eight") %>% factor(levels = c("four", "six", "eight"))), design = matrix(c(1, 1, 2, 3), byrow = TRUE, nrow = 2), scales = "free" ) }
调用时直接传入数据集变量名即可正常运行:
mtcars %>% ggplot() + my_facet(cyl) + geom_point(aes(x = disp, y = hp))
为什么之前的尝试无效?
sym(x):需要传入字符串形式的变量名(如"cyl"),但调用时传的是裸变量名,无法匹配。!!sym(x):同样依赖变量名字符串,且未结合vars()的准引用环境,无法正确解析。- 单独使用
enquo(x):仅捕获了变量引用,但未用!!注入到vars()表达式中,vars()仍将x视为普通变量。 - 之前用
{{x}}可能是写法位置错误,需确保{{x}}直接替换vars()内部的x变量。
内容的提问来源于stack exchange,提问作者mzuba
相关产品推荐
相关产品推荐

