【问题标题】:Is it possible to desaturate a ggplot easily?是否可以轻松地使 ggplot 去饱和?
【发布时间】:2015-11-15 19:27:54
【问题描述】:

是否可以轻松地将ggplot 去饱和?


原则上,可能有两种可能的策略。
首先,将一些函数应用于ggplot 对象(或者,可能是Grob 对象)以使所有颜色去饱和。其次,在渲染.rmd 文件时打印ggplot 去饱和的一些技巧。这两种策略对我来说都可以,但第一个当然更有希望。
从一开始就以灰色创建ggplot 并不是一个好的选择,因为这样做的目的是让情节与以灰色阴影打印的情节相同。


关于如何在 R 中进行去饱和,有一些类似的问题和非常好的答案。Here 是一种方便的方法来去饱和调色板。而here 是对光栅图像去饱和的方法。我正在寻找的是一种使整个ggplot 去饱和的简单方法。

【问题讨论】:

  • 您能否以高 DPI 将绘图导出到 PNG,通过光栅加载 PNG 并通过您链接到的解决方案去饱和?如果您要做的只是测试它的外观,这似乎是一种低成本的解决方案。
  • 我希望有一种简单的方法可以使 ggplot 对象本身去饱和。在 R 中将矢量图形转换为光栅感觉不对。
  • 好吧,如果您只是想将其保留为矢量格式,您可以使用colormodel="gray"ggplot 输出导出到PDF 设备,这可能会得到您想要的结果吗?
  • 酷!我不知道colormodel="gray" 选项。在knirt 中渲染绘图时是否有类似的东西?
  • 我和@ikashnitsky 在一起,对 ggplot 对象本身去饱和很有用。例如,它允许您直接从 R 中制作原始图和去饱和图的并排图,而无需将图写入文件并将其读回。如果您想这样做,它真的很有用编写有关去饱和和色盲影响的 R Markdown 文档。

标签: r colors ggplot2 markdown


【解决方案1】:

刚刚遇到这个问题。实验包 colorblindr(由 Claire McWhite 和我自己编写)包含一个可以以通用方式执行此操作的函数。我正在使用来自@hrbrmstr 的示例图:

library(ggplot2)
library(viridis)

gg <- ggplot(mtcars) + 
  geom_point(aes(x=mpg, y=wt, fill=factor(cyl), size=factor(carb)), 
             color="black", shape=21) + 
  scale_fill_viridis(discrete = TRUE) +
  scale_size_manual(values = c(3, 6, 9, 12, 15, 18)) +
  facet_wrap(~am)
gg

现在让我们使用 colorblindr 中的 edit_colors() 函数对该图进行去饱和处理:

library(colorblindr) # devtools::install_github("clauswilke/colorblindr")
library(colorspace) # install.packages("colorspace", repos = "http://R-Forge.R-project.org") --- colorblindr requires the development version
# need also install cowplot; current version on CRAN is fine.

gg_des <- edit_colors(gg, desaturate)
cowplot::ggdraw(gg_des)

edit_colors() 函数接受一个 ggplot2 对象或 grob,并将颜色转换函数(此处为 desaturate)应用于 grob 中的所有颜色。

我们可以为转换函数提供额外的参数,例如进行部分去饱和:

gg_des <- edit_colors(gg, desaturate, amount = 0.7)
cowplot::ggdraw(gg_des)

我们还可以进行其他转换,例如色盲模拟:

gg_des <- edit_colors(gg, deutan)
cowplot::ggdraw(gg_des)

最后,我们可以分别操作线条颜色和填充颜色。例如,我们可以将所有填充区域设为蓝色。 (不确定这是否有用,但无论如何。)

gg_des <- edit_colors(gg, fillfun = function(x) "lightblue")
cowplot::ggdraw(gg_des)

【讨论】:

    【解决方案2】:

    根据我上面的评论,这可能是实现ggplot2 对象去饱和的最快/最脏的方法:

    library(ggplot2)
    
    set.seed(1)
    p <- qplot(rnorm(50), rnorm(50), col="Class")
    print(p)
    

    pdf(file="p.pdf", colormodel="grey")
      print(p)
    dev.off()
    

    【讨论】:

      【解决方案3】:

      我用新的 viridis 调色板尝试了这个,因为它可以很好地去饱和(即在彩色和非彩色图之间应该很明显):

      library(ggplot2)
      library(grid)
      library(colorspace)
      library(viridis) # devtools::install_github("sjmgarnier/viridis") for scale_fill_viridis
      
      gg <- ggplot(mtcars) + 
        geom_point(aes(x=mpg, y=wt, fill=factor(cyl), size=factor(carb)), 
                   color="black", shape=21) + 
        scale_fill_viridis(discrete = TRUE) +
        scale_size_manual(values = c(3, 6, 9, 12, 15, 18)) +
        facet_wrap(~am)
      
      gb <- ggplot_build(gg)
      gb$data[[1]]$colour <- desaturate(gb$data[[1]]$colour)
      gb$data[[1]]$fill <- desaturate(gb$data[[1]]$fill)
      
      gt <- ggplot_gtable(gb)
      
      grid.newpage()
      grid.draw(gt)
      

      您最终不得不在 grob 级别上进行操作。

      这是预去饱和的情节:

      这是去饱和后的情节:

      我试图弄清楚为什么这个图例被跳过了,这可能会错过其他高度定制的 ggplot 美学和组件,所以即使它不是一个完整的答案,也许它可能有用(也许其他人可以附加到它或在另一个答案中扩展它)。只需替换gb 对象或gt 对象中的正确位即可。

      更新我设法为图例找到了正确的 grob 元素:

      gt$grobs[[12]][[1]][["99_9c27fc5147adbe9a3bdf887b25d29587"]]$grobs[[4]]$gp$fill <- 
          desaturate(gt$grobs[[12]][[1]][["99_9c27fc5147adbe9a3bdf887b25d29587"]]$grobs[[4]]$gp$fill)
      gt$grobs[[12]][[1]][["99_9c27fc5147adbe9a3bdf887b25d29587"]]$grobs[[6]]$gp$fill <- 
          desaturate(gt$grobs[[12]][[1]][["99_9c27fc5147adbe9a3bdf887b25d29587"]]$grobs[[6]]$gp$fill)
      gt$grobs[[12]][[1]][["99_9c27fc5147adbe9a3bdf887b25d29587"]]$grobs[[8]]$gp$fill <- 
          desaturate(gt$grobs[[12]][[1]][["99_9c27fc5147adbe9a3bdf887b25d29587"]]$grobs[[8]]$gp$fill)
      
      grid.newpage()
      grid.draw(gt)
      

      寻找其他需要去饱和的gp 元素的方法也不错。

      【讨论】:

      • 谢谢!这真是太棒了!您的解决方案可以很容易地在一个方便的功能中变形。是的,传奇标签的行为非常奇怪。我找不到问题所在。
      • 我设法为他们找出了 grobs。您只需要(小心地)遍历gt$grobs 树和desaturate() 所有gp fillcolor 元素(有些不存在)。
      • 非常感谢viridis调色板。太棒了!我是否理解它不仅对打印友好,而且对色盲友好?
      • 是的。我有一些扩展的 viridis 示例here。它对于离散情况并不完美,但效果很好,并且具有色盲、印刷和比迄今为止任何其他产品更“正常”的线性精度(也许 parula 接近,但它是专有的)。
      • 几个月前,我写了一个函数,它完全按照@hrbrmstr 的建议:“(小心地)遍历gt$grobs 树和desaturate() 所有gp fill 和@987654343 @元素。” (不过,在最一般的情况下,您还需要覆盖光栅 grobs,这有点棘手。)请参阅我发布的答案。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-02-02
      • 1970-01-01
      • 2021-12-31
      • 2018-11-02
      • 2019-11-21
      相关资源
      最近更新 更多