在R自定义ggplot函数中指定...参数仅作用于指定图层的方法
解决ggplot自定义函数中参数仅作用于指定图层的问题
问题原因
你当前的函数把...同时传给了stat_summary和geom_jitter,所有通过...传入的参数(比如size=10)会被两个图层同时接收,导致stat_summary的线条和geom_jitter的点都变大。
解决方案
方案1:给指定图层单独设置参数列表(推荐)
通过给stat_summary单独定义一个参数列表,把需要传给它的参数放在列表里,和geom_jitter的参数完全隔离,实现精准控制:
library(ggplot2) library(rlang) jitter_graph_mm1 <- function(data, x, y, xlab = NULL, ylab = NULL, stat_summary_params = list(), ...) { ggplot(data, aes({{x}}, {{y}})) + # 用!!!拼接stat_summary的自定义参数 stat_summary(fun = median, show.legend = FALSE, geom="crossbar", !!!stat_summary_params) + # ...仅传递给geom_jitter的参数 geom_jitter(show.legend = FALSE, width = 0.25, ...) + labs(x=xlab, y=ylab) } # 使用示例:分别控制两个图层的参数 jitter_graph_mm1( data=iris, x=Species, y=Sepal.Width, ylab = "hi", stat_summary_params = list(size = 10, color = "darkblue"), # 给geom_jitter传递独立参数 color = "red", alpha = 0.6 )
这个方法的优势是完全区分两个图层的参数空间,你可以分别给它们传递任意参数,不会互相干扰。
方案2:硬编码geom_jitter的size参数
如果只是不想让size影响geom_jitter,可以直接在geom_jitter里明确指定size的默认值,覆盖...中传入的同名参数:
library(ggplot2) jitter_graph_mm1 <- function(data, x, y, xlab = NULL, ylab = NULL, ...) { ggplot(data, aes({{x}}, {{y}})) + stat_summary(fun = median, show.legend = FALSE, geom="crossbar", ...) + # 明确指定geom_jitter的size,忽略...中的size值 geom_jitter(show.legend = FALSE, width = 0.25, size = 1, ...) + labs(x=xlab, y=ylab) } jitter_graph_mm1(data=iris, x=Species, y=Sepal.Width, ylab = "hi", size = 10)
注意:这个方法会固定geom_jitter的size,之后无法通过...给它传递size参数,适合需求固定的场景。
方案3:拆分...中的参数
如果你想保留原有的调用方式,不想新增参数列表,可以通过rlang工具拆分...中的参数,把指定参数传给stat_summary,剩下的传给geom_jitter:
library(ggplot2) library(rlang) jitter_graph_mm1 <- function(data, x, y, xlab = NULL, ylab = NULL, ...) { # 把...转换为列表 dots <- dots_list(...) # 提取size参数给stat_summary stat_size <- dots$size # 移除size后,剩余参数传给geom_jitter jitter_dots <- dots[names(dots) != "size"] ggplot(data, aes({{x}}, {{y}})) + stat_summary(fun = median, show.legend = FALSE, geom="crossbar", size = stat_size) + geom_jitter(show.legend = FALSE, width = 0.25, !!!jitter_dots) + labs(x=xlab, y=ylab) } jitter_graph_mm1(data=iris, x=Species, y=Sepal.Width, ylab = "hi", size = 10)
这个方法无需修改调用格式,但如果需要区分多个参数,就得逐个处理,灵活性不如方案1。
内容的提问来源于stack exchange,提问作者MM1
相关产品推荐
相关产品推荐

