如何在ggformula包中使用引用变量(替代ggplot的aes_string)
在ggformula中实现动态变量映射(替代ggplot的aes_string)
问题重现
我可以在ggplot中使用aes_string实现动态美学映射,但不知道如何在ggformula包中实现类似功能。以下测试代码运行时出现object 'Species' not found错误:
pacman::p_load(ggformula) plot_list = list() names_y_axis = names(iris)[2:4] plot_list = lapply(names_y_axis, \(x){ gf_point(Sepal.Length ~ x, color = ~ Species) }) gridExtra::grid.arrange(grobs = plot_list)
错误信息:
Error in `FUN()`: ! Problem while computing aesthetics. ℹ Error occurred in the 1st layer. Caused by error in `FUN()`: ! object 'Species' not found Backtrace: ▆ 1. ├─gridExtra::grid.arrange(grobs = plot_list) 2. │ └─gridExtra::arrangeGrob(...) 3. │ └─base::lapply(grobs[toconv], ggplot2::ggplotGrob) 4. │ └─ggplot2 (local) FUN(X[[i]], ...) 5. │ ├─ggplot2::ggplot_gtable(ggplot_build(x)) 6. │ │ └─ggplot2:::attach_plot_env(data$plot$plot_env) 7. │ │ └─base::options(ggplot2_plot_env = env) 8. │ ├─ggplot2::ggplot_build(x) 9. │ └─ggplot2:::ggplot_build.ggplot(x) 10. │ └─ggplot2:::by_layer(...) 11. │ ├─rlang::try_fetch(...) 12. │ │ ├─base::tryCatch(...) 13. │ │ │ └─base (local) tryCatchList(expr, classes, parentenv, handlers) 14. │ │ │ └─base (local) tryCatchOne(expr, names, parentenv, handlers[[1L]]) 15. │ │ │ └─base (local) doTryCatch(return(expr), name, parentenv, handler) 16. │ │ └─base::withCallingHandlers(...) 17. │ └─ggplot2 (local) f(l = layers[[i]], d = data[[i]]) 18. │ └─l$compute_aesthetics(d, plot) 19. │ └─ggplot2 (local) compute_aesthetics(..., self = self) 20. │ └─ggplot2:::scales_add_defaults(...) 21. │ └─base::lapply(aesthetics[new_aesthetics], eval_tidy, data = data) 22. │ └─rlang (local) FUN(X[[i]], ...) 23. └─base::.handleSimpleError(...) 24. └─rlang (local) h(simpleError(msg, call)) 25. └─handlers[[1L]](cnd) 26. └─cli::cli_abort(...) 27. └─rlang::abort(...)
解决方案
ggformula基于tidy eval语法,可通过两种方式实现动态变量映射:
方法1:使用rlang的符号与非标准求值
将字符串变量转为符号,再用!!强制求值,同时显式指定数据源data = iris确保变量能被正确识别:
pacman::p_load(ggformula, gridExtra) plot_list = list() names_y_axis = names(iris)[2:4] plot_list = lapply(names_y_axis, \(x){ y_var <- rlang::sym(x) gf_point(Sepal.Length ~ !!y_var, color = ~ Species, data = iris) }) grid.arrange(grobs = plot_list)
方法2:构造公式字符串转成公式对象
直接拼接公式字符串,再转为公式对象传入gf_point:
pacman::p_load(ggformula, gridExtra) plot_list = list() names_y_axis = names(iris)[2:4] plot_list = lapply(names_y_axis, \(x){ plot_formula <- as.formula(paste("Sepal.Length ~", x)) gf_point(plot_formula, color = ~ Species, data = iris) }) grid.arrange(grobs = plot_list)
错误原因
原代码中Sepal.Length ~ x里的x被当作独立变量而非iris数据集的列名,导致ggformula无法解析;显式指定data = iris则能确保Species在正确的数据源环境中被查找。
内容的提问来源于stack exchange,提问作者Ramakrishna S
相关产品推荐
相关产品推荐

