首页 > 解决方案 > 使用 stat_summary 将 ggplot 转换为灰度

问题描述

我有一个 R 包作为 GUI (JASP) 的后端引擎。我希望能够让人们将他们的图像转换为灰度(用于出版物印刷)。对于大多数绘图,我可以使用scale_colour_grey(),但是当在 stats_summary 中指定颜色时,这不起作用。例如:

# simulate data
set.seed(1212)
y = rnorm(100)
g = sample(c("a", "b"), 100, T)
d = data.frame(y=y, g=g)

### create ggplot
plot = ggplot(data=d, aes(x=g, y=y)) +
  geom_jitter() + 
  stat_summary(fun="mean", geom="point", size=3, color="red") +
  stat_summary(geom="errorbar", size=3, color="red") +
  theme_bw()

### converting to greyscale doesn't work
plot + scale_colour_grey()

经过一番研究,我了解到您可以剖析 ggplot 对象然后重建它:

### can rebuilt ggplot object, but not ideal
q <- ggplot_build(plot)
q$data[[2]]$colour <- "black"
q$data[[3]]$colour <- "black"
q <- ggplot_gtable(q)
plot  = ggplotify::as.ggplot(q)
plot

这很好用,但我尝试在我的 R 包中包含尽可能少的依赖项。我真的必须求助于另一个包(ggplotify)来修改来自stat_summary的颜色吗?

几点注意事项:我不想修改原始的 stat_summary 语句。让我们假设无法修改。另外,假设我不能添加另一个包(除了已经加载的 ggplot2)。请记住,我是 JASP 框架中的“客人”,我不想将另一个包添加到他们必须存储的包列表中。

标签: rggplot2

解决方案


您实际上可以在构建 ggplot 对象之前访问它,进入具有彩色对象的层并更改它。这是一个完整的代表:

library(ggplot2)

#  simulate data
set.seed(1212)
y = rnorm(100)
g = sample(c("a", "b"), 100, T)
d = data.frame(y=y, g=g)

### create ggplot
p <- ggplot(data=d, aes(x=g, y=y)) +
  geom_jitter() + 
  stat_summary(fun="mean", geom="point", size=3, color="red") +
  stat_summary(geom="errorbar", size=3, color="red") +
  theme_bw()

p 


p$layers[[3]]$aes_params$colour <-  "gray50"

p

如果您想要一种更通用的方法来更改特定几何图形的颜色,您可以执行以下功能:

recolour_geom <- function(gg_plot, geom, colour = "gray50")
{
  ss <- which(sapply(p$layers, function(l) {
                       paste(gsub("GEOM|GG|PROTO", "", toupper(class(l$geom))),
                       collapse = "")}) %in% toupper(geom))
  
  if (length(ss) > 0)
  {
    for (i in ss)
    {
      p$layers[[i]]$aes_params$colour <- colour
    }
  }
  p
}

例如,这允许你做

recolour_geom(p, "errorbar", "blue")
recolour_geom(p, "point", "green")

在此处输入图像描述

请注意,虽然这会通过引用更改 ggplot,但p会作为函数的副作用而更改。

reprex 包(v0.3.0)于 2020 年 8 月 14 日创建


推荐阅读