如何在ggplot2的scale_fill_brewer中仅更改一个值的颜色值?

29
我有一个R数据框(`df`),我正在使用ggplot2将其绘制为条形图,并基于数据框中的一列(`df$type`)进行颜色着色。目前,我正在使用默认的着色模式(`scale_fill_brewer`)来分配颜色。
如何将颜色黑色分配给一个值(`df$type == -1`),并使用`scale_fill_brewer`将其余颜色分配给其余部分?(所有其他`df$types`都在1到X的整数集合内,其中X是唯一值的数量)
到目前为止,我已经能够通过找出`scale_fill_brewer`用于N个不同项目的颜色集,然后假装颜色为黑色并将其传递给`scale_fill_manual`,手动完成此操作。
rhg_cols1<- c("#000000","#F8766D","#7CAE00","#00BFC4","#C77CFF" )
ggplot(y=values,data=df, aes(x=name, fill=factor(type))) + 
  geom_bar()+ scale_fill_manual(values = rhg_cols1)
问题在于我需要一种不需要手动分配颜色的解决方案,而是使用十六进制颜色计算器来确定scale_fill_brewer的十六进制值。

类似这样:

ggplot(y=values,data=df, aes(x=name, fill=factor(type))) +
  geom_bar()+ scale_fill_brewer(value(-1, "black")

谢谢!

编辑:该解决方案必须适用于超过30种颜色,并适用于ColorBrewer的“Set2”。


1
我也在想同样的问题。如果“scale_fill_manual()”和其他函数能够接受不完整的参数向量,例如“scale_fill_manual(values=c('-1'='black'))”,并且能够理解其他颜色按照通常的方式自动选择,那就太好了。 - Pierre D
2个回答

47

RColorBrewer中包含多种配色方案,您可以使用函数brewer.pal来返回所选的调色板。

例如,选择一个由5种蓝色组成的连续调色板:

library(RColorBrewer)
my.cols <- brewer.pal(5, "Blues")
my.cols

[1] "#EFF3FF" "#BDD7E7" "#6BAED6" "#3182BD" "#08519C"
你可以在?brewer.pal帮助文件中获取有效调色板名称列表。这些名称对应于ColorBrewer网站上的名称。
你现在可以使用或修改结果,并通过使用你建议的scale_manual_fill将其传递给ggplot
my.cols[1] <- "#000000"

library(ggplot2)
df <- data.frame(x=1:5, type=1:5)
ggplot(df, aes(x=x, fill=factor(type))) +
    geom_bar(binwidth=1)+ 
    scale_fill_manual(values = my.cols)

输入图像描述


感谢您提供非常详细的回复。不幸的是,Set2仅返回8种颜色,在某些情况下我需要更多的颜色。 - wespiserA
是的,据我所知,几乎所有的ColorBrewer调色板都有8种颜色的上限。您也可以尝试使用scale_fill_hue - Andrie
scale_fill_hue比我现在使用的颜色更难区分。我可能会从几个不同的集合中获取颜色,将它们全部组合在一起,加入黑色并使用它...我还不确定,这正在成为我的周末项目... - wespiserA

22
如果你需要区分这么多(30个以上的)不同类别,你可能需要退后一步,花更多时间从战略层面考虑项目:几乎不可能设计出一组能够真正区分开的30种颜色(尤其是在跨平台/渲染通道时)。
基本上没有解决方案可以使用 Set2 和 30个或以上的颜色。某些 CB 调色板(如 Set3 和 Paired;library(RColorBrewer); display.brewer.all(n=12))可支持高达12种颜色。
编辑:发帖者希望使用好的、可区分的颜色进行探索性数据分析,并且要求在有很多类别时也不会出问题。我建议采用以下方式:
library(RColorBrewer)
my.cols <- function(n) {
  black <- "#000000"
  if (n <= 9) {
    c(black,brewer.pal(n-1, "Set2"))
  } else {
    c(black,hcl(h=seq(0,(n-2)/(n-1),
                  length=n-1)*360,c=100,l=65,fixup=TRUE))
  }
}

library(ggplot2)
d <- data.frame(z=1:10)
g1 <- qplot(z,z,data=d,colour=factor(z))+opts(legend.position="none")
g1 + scale_colour_manual(values=my.cols(9))
g1 + scale_colour_manual(values=my.cols(10))
## check that we successfully recreated ggplot2 internals
## g1+scale_colour_discrete()

我认为这个方法效果还不错(如果你愿意的话,可以替换为Set3和13种颜色的截断)。唯一的缺点(我能想到的)是在使用9种和10种颜色时图表之间存在不连续性。

以编程方式自动选择N个可区分颜色集合的更好解决方案将会相当困难...


2
一个更有趣/具有挑战性的解决方案是找到一组点,它们都落在亮度=65的HCL楔形区域内,并且尽可能均匀/相距较远。这并不是一件简单的事情... - Ben Bolker
1
继@Ben上面的评论之后,colorspace包中的rainbow_hcl函数使得构建均匀间隔的HCL颜色调色板变得容易。例如:library(colorspace); plot(1:10, col=rainbow_hcl(n=10, c=100, l=65), pch=16, cex=6) - Josh O'Brien
2
http://tools.medialab.sciences-po.fr/iwanthue/ 是我上面随口一提的一个很好的实现。我认为 rainbow_hcl,就像 ggplot 的颜色方案一样,在适当的颜色空间的边缘给出了等间距的值...不错,但并不完全符合我的想法,我的想法是用均匀间距的点来填充颜色空间。 - Ben Bolker
这实际上并不是对问题的回答。这是重新分配整个颜色比例尺,可能与当前图形g1中使用的比例尺不同,而在添加scale_*_manual层之前。上面的例子肯定是有帮助的,但是否有办法获取当前的颜色比例尺,根据需要进行修改(如问题中所述的一个颜色),然后将该层添加回去呢?或者还有其他方法只改变当前比例尺的一个元素而不改变其他元素吗? - Paul 'Joey' McMurdie
1
“i want hue”的本地R实现可在https://github.com/johnbaums/hues找到。还有rwanthue,但它在V8中运行JavaScript,并且在OSX上不容易安装。 - Ido Tamir

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接