在不同的分面之间更改颜色方案

12

我有一个 data.frame,大致如下:

set.seed(100)

df <- data.frame(year = rep(2011:2014, 3), 
                 class = rep(c("high", "middle", "low"), each = 4), 
                 age_group = rep(1:3, each = 4), 
                 value = sample(1:2, 12, rep = TRUE))

我希望生产出三个类似于以下代码所生成的图形,通过对变量 age_group 进行分面(facet)处理:

```{...} (code not provided) ```
library(ggplot2)
blue <- c("#bdc9e1", "#74a9cf", "#0570b0")
ggplot(df) + geom_bar(aes(x = year, y = value, 
                          fill = factor(class, levels = c("high", "middle", "low"))), 
                      stat = "identity") + 
  scale_fill_manual(values = c(blue)) +
  guides(fill = FALSE)

然而,每个方面都有不同的颜色方案,其中所有颜色都由我指定。

我似乎想要一个更具体的版本,即ggplot2: Change color for each facet in bar chart中所示的内容。

因此,使用我提供的数据,我希望获得三个分面图,按age_group拆分,其中每个图的填充由class的级别给出,并且所有颜色(总共9种)都将由我手动指定。

编辑:为了澄清,我最终想要的分面是以下代码提供的:

ggplot(df) + geom_bar(aes(x = year, y = value, 
                          fill = factor(class, levels = c("high", "middle", "low"))), 
                      stat = "identity") + 
  scale_fill_manual(values = c(blue)) +
  guides(fill = FALSE) + 
  facet_wrap(~ age_group)

通过 class 变量的颜色子集的附加控制级别。


这基本上是一个非常好的和可重复的问题(干得好!),但我需要澄清一下几个问题。 (a)我很惊讶您的示例图中没有包含您想要的facet...只需添加+ facet_wrap(〜age_group)是否符合您的意图?也许在您的示例中包括它。 (b)您对传说有什么想法?所有年龄组/类别交互作用的单个传说?还是每个子图的单独传说? - Gregor Thomas
我已经在我的问题中添加了最后一个方面。你的假设是正确的,我只是想包括facet(〜age_group)。你提到的图例很有趣,我没有想到过。一个类似图例的东西,其中我可以有三种颜色的块对应于“高”,“中”和“低”级别,这将是不错的,但我想象这已经超出了ggplot的控制范围。我欢迎建议。 - Ross
我有一个关于在“grid”系统中制作“网格”图例的旧问题 - 你可能可以适应它。至于颜色,我会在您的数据中添加一个由类和年龄组合成的列,然后通过该列进行填充(使用pasteinteraction创建新列)。我现在没有时间写一个好的答案,但如果没有其他人先回答,我会尽量找时间回答。 - Gregor Thomas
你的示例是否不太理想呢?对于每个年龄组,只有一个类别值(例如,年龄组1只有“高”类)。这意味着在每个小面板中,您将获得不同的颜色,而无需进行任何特殊处理。如果这不是您想要的,请创建一个更实际的可重现示例会很有用。(为了弥补所有的抱怨:正如Gregor已经提到的,您确实创建了一个可工作的可重现示例,这是非常好的!) - Stibu
我相信Mark Peterson在他的回答中生成的数据更能代表我正在处理的数据,正如你所提到的,你会得到许多不同年龄组的类别。感谢您的友善评论。 - Ross
1个回答

18

我不完全确定为什么你想这样做,因此有点难以知道我提出的方案是否真正解决了您的实际用例。

首先,我生成了一个不同的数据集,实际上将每个类别都分配到了每个年龄组中:

set.seed(100)

df <- data.frame(year = rep(2011:2014, 3), 
                 class = rep(c("high", "middle", "low"), each = 12), 
                 age_group = rep(1:3, each = 4), 
                 value = sample(1:2, 36, rep = TRUE))
如果你正在寻找在每个age_group内类似从深到浅的渐变,你可以直接使用alpha来实现,而不必担心添加额外的数据列:
ggplot(df) +
  geom_bar(aes(x = year, y = value, 
               fill = factor(age_group)
               , alpha = class ), 
           stat = "identity") + 
  facet_wrap(~age_group) +
  scale_alpha_discrete(range = c(0.4,1)) +
  scale_fill_brewer(palette = "Set1"
                    , name = "age_group")

在这里,我设置了alpha的范围以给出合理可见的颜色,并从RColorBrewer中选择了一个默认调色板来展示这个想法。它给出了:

enter image description here

它还提供了一个相对可用的图例作为起点,尽管您可以进一步修改它(这是我回答另一个问题时给出的类似图例解答:https://dev59.com/6e7zs4cB2Jgan1zn8WQj#39046977

或者,如果您真的非常希望自己指定颜色,您可以向数据添加一列,并基于该列创建颜色:

df$forColor <-
  factor(paste0(df$class, " (", df$age_group , ")")
         , levels = paste0(rep(c("high", "middle", "low"), times = 3)
                           , " ("
                           , rep(1:3, each = 3)
                           , ")") )

然后,将其用作填充颜色。请注意,我在此处使用RColorBrewer brewer.pal来选择颜色。我发现第一种颜色对于这样的条形图太浅了,所以我将其排除在外。

ggplot(df) +
  geom_bar(aes(x = year, y = value, 
               fill = forColor), 
           stat = "identity") + 
  scale_fill_manual(values = c(brewer.pal(4, "Blues")[-1]
                               , brewer.pal(4, "Reds")[-1]
                               , brewer.pal(4, "Purples")[-1]
                               )
                    , name = "Class (age_group)") +
  facet_wrap(~age_group)

提供:

在此输入图像描述

这个图例有些繁琐,但可以进行修改,类似于我链接到的另一个答案。这样就可以设置任何9种(或更多,针对不同用例)颜色。


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