在R自定义函数中向ggpubr传递变量时报错的解决方法
解决dplyr分组汇总+ggpubr绘图函数封装的引号问题
问题描述
我想把以下包含dplyr分组汇总与ggpubr绘图的代码封装为函数:
df %>% group_by(a, b) %>% summarize(avg=mean(c)) %>% ggline(x="a", y="avg", color='b')
但调用自定义函数时,尽管is.factor(df$b) == TRUE,仍返回错误:Error in is.factor(x) : object 'b' not found。自定义函数代码如下:
graph_var <- function(data_source, var) { var2 <- enquo(var) data_source %>% group_by(a, !!var2 )%>% summarize(avg=mean(c)) %>% ggline(x="a", y="avg", color=shQuote(var) )+ grids(linetype = 'dashed') } graph_var(df, b)
可复现代码
library(tidyverse) library(ggpubr) set.seed(13) df <- data.frame( a = rep(1:10), b = as.factor(rep(LETTERS[24:26], each = 10)), c = rnorm(30) ) # 显式声明 - 可正常运行 df %>% group_by(a, b )%>% summarize(avg=mean(c)) %>% ggline(x="a", y="avg", color="b" )+ grids(linetype = 'dashed') # works # 通过变量传递 - 也可正常运行 test_var <- "b" df %>% group_by(a, b )%>% summarize(avg=mean(c)) %>% ggline(x="a", y="avg", color=test_var )+ grids(linetype = 'dashed') # also works # 通过函数声明 - 返回错误"Error in is.factor(x) : object 'b' not found" graph_var_ex <- function(data_source, var) { var2 <- enquo(var) data_source %>% group_by(a, !!var2 )%>% summarize(avg=mean(c)) %>% ggline(x="a", y="avg", color=shQuote(var) )+ grids(linetype = 'dashed') } graph_var_ex(df, b)
问题原因
错误出在shQuote(var)的使用上:
- 当传入
b作为参数时,var是一个符号对象,shQuote(var)会将其转换为带单引号的字符串(即"'b'")。 - ggpubr的
color参数需要的是不带额外引号的列名字符串,此时它会尝试在数据框中寻找列名为'b'(包含单引号)的列,而实际列名是b,因此报错找不到对象。
解决方案
需要将传入的符号参数转换为纯净的列名字符串,而不是带额外引号的版本。可以用rlang::as_name()处理enquo()生成的quosure对象,得到正确的列名字符串。
修正后的函数
graph_var_ex <- function(data_source, var) { var2 <- enquo(var) # 将quosure转换为列名字符串 var_colname <- rlang::as_name(var2) data_source %>% group_by(a, !!var2 )%>% summarize(avg=mean(c)) %>% ggline(x="a", y="avg", color=var_colname )+ grids(linetype = 'dashed') }
简化版(使用{{}}语法)
如果想简化tidyeval的写法,可以用{{}}(curly-curly)代替enquo()和!!,同时获取列名字符串:
graph_var_ex <- function(data_source, var) { var_colname <- rlang::as_name(rlang::enquo(var)) data_source %>% group_by(a, {{var}} )%>% summarize(avg=mean(c)) %>% ggline(x="a", y="avg", color=var_colname )+ grids(linetype = 'dashed') }
测试
调用修正后的函数即可正常运行:
graph_var_ex(df, b)
内容的提问来源于stack exchange,提问作者Trevor Sutherland
相关产品推荐
相关产品推荐

