colorspace包中scale_fill_continuous_diverging()在自定义函数内无法识别父函数参数的问题求助
问题原因与解决方案
这个问题我之前也碰到过!本质上是scale_fill_continuous_diverging()函数在处理palette参数时的非标准求值逻辑出了问题——它没有在你的自定义函数局部环境里查找传入的clrsp参数,反而默认去全局环境找了,而scale_color_continuous_diverging()的求值逻辑是正常的。
问题根源
colorspace包中,scale_fill_continuous_diverging()的palette参数采用了延迟求值的方式,但没有正确捕获函数的调用环境(也就是你的自定义函数plot_example_fill的局部环境),导致它跳过局部环境,直接到全局环境中寻找同名对象。如果全局环境没有该对象就报错,有就用全局的,完全忽略了你传入的参数。
可行解决方案
以下几种方法都能在不修改全局环境的前提下解决问题,选你习惯的方式就行:
方案1:用rlang::inject()强制局部环境求值
借助rlang包的inject()函数,把clrsp参数强制在局部环境中解析,避免延迟求值的坑:
library(tidyverse) library(colorspace) library(rlang) plot_example_fill <- function(df, clrsp){ p <- ggplot(df, aes(x = qsec, y = wt, fill = example_var)) + geom_point(shape = 21, size = 6) + inject(colorspace::scale_fill_continuous_diverging(palette = !!clrsp)) return(p) } # 测试:不需要全局clrsp,传入参数正常运行 plot_example_fill(df = df, clrsp = "Berlin")
方案2:用do.call()显式传递参数
通过do.call()来调用scale_fill_continuous_diverging(),这种方式会把参数直接传递给函数,绕开非标准求值的问题:
library(tidyverse) library(colorspace) plot_example_fill <- function(df, clrsp){ p <- ggplot(df, aes(x = qsec, y = wt, fill = example_var)) + geom_point(shape = 21, size = 6) + do.call(colorspace::scale_fill_continuous_diverging, list(palette = clrsp)) return(p) } # 测试 plot_example_fill(df = df, clrsp = "Berlin")
方案3:显式指定求值环境
scale_fill_continuous_diverging()其实有一个隐藏的envir参数,可以直接把当前函数的局部环境传递给它,让它在正确的环境里找参数:
library(tidyverse) library(colorspace) plot_example_fill <- function(df, clrsp){ p <- ggplot(df, aes(x = qsec, y = wt, fill = example_var)) + geom_point(shape = 21, size = 6) + colorspace::scale_fill_continuous_diverging(palette = clrsp, envir = environment()) return(p) } # 测试 plot_example_fill(df = df, clrsp = "Berlin")
额外提示
这个问题属于colorspace包的一个小bug,你可以考虑去包的GitHub仓库提issue反馈,帮助官方修复这个求值逻辑的问题。
内容的提问来源于stack exchange,提问作者kuecki95
相关产品推荐
相关产品推荐

