每个条形图用颜色渐变呈现的堆积式条形图

7
我想为堆积条形图着色,使每个条形图都有自己的父级颜色,并且每个条形图内部的颜色是该父级颜色的渐变色。 示例: 这是一个最简单的示例。我想让每个条形图的颜色都不同,使用 `color`,并在每个条形图内设置由 `clarity` 设置的渐变色。
library(ggplot2)

ggplot(diamonds, aes(color)) + 
  geom_bar(aes(fill = clarity), colour = "grey")

enter image description here

在我的实际问题中,我有更多的组:每个组需要18个不同的条形图和39种不同的渐变颜色。


1
你能用dput()函数提供一下你的数据框吗?这应该是可行的! - Luke Hayden
我对R还很陌生,但我会尝试。需要几天时间。 - nicole
1
使用以下命令:dput(Rome),并将控制台输出的内容复制粘贴。 - Luke Hayden
4个回答

10

我已经编写了一个名为ColourPalleteMulti的函数,它可以让您基于数据子组创建多个颜色调色板:

ColourPalleteMulti <- function(df, group, subgroup){

  # Find how many colour categories to create and the number of colours in each
  categories <- aggregate(as.formula(paste(subgroup, group, sep="~" )), df, function(x) length(unique(x)))
  category.start <- (scales::hue_pal(l = 100)(nrow(categories))) # Set the top of the colour pallete
  category.end  <- (scales::hue_pal(l = 40)(nrow(categories))) # set the bottom

  # Build Colour pallette
  colours <- unlist(lapply(1:nrow(categories),
                          function(i){
                            colorRampPalette(colors = c(category.start[i], category.end[i]))(categories[i,2])}))
  return(colours)
}

本质上,该函数确定有多少不同的组,然后计算每个组中有多少颜色。然后将所有不同的调色板连接在一起。

要使用这个调色板,最简单的方法是添加一个新列group,将用于创建调色板的两个值粘贴在一起:

library(ggplot2)

# Create data
df <- diamonds
df$group <- paste0(df$color, "-", df$clarity, sep = "")

# Build the colour pallete
colours <-ColourPalleteMulti(df, "color", "clarity")

# Plot resultss
ggplot(df, aes(color)) + 
  geom_bar(aes(fill = group), colour = "grey") +
  scale_fill_manual("Subject", values=colours, guide = "none")

在这里输入图片描述


编辑:

如果您想让每个条形图内的条形颜色不同,只需更改用于绘制条形图的变量即可:

# Plot resultss
ggplot(df, aes(cut)) + 
  geom_bar(aes(fill = group), colour = "grey") +
  scale_fill_manual("Subject", values=colours, guide = "none")

enter image description here


注意:说实话,您想要绘制的数据集可能包含过多的子类别,因此这种方法可能不适用。

而且,尽管这种视觉效果非常好,但我建议避免使用这样的颜色比例尺。它更多是为了使图表看起来漂亮,但不同的颜色对于我们已经从X轴知道哪个组中的数据是多余的。


感谢您的帮助,但这改变了我原来问题的意思。我不想为18个条形图设置父级颜色。我有88个条形图,在这些条形图中,我有18个组(18个不同的门),和39个子组(类)。我试图让门成为父级颜色,而类则是门的不同渐变。 - nicole
@nicole 对于改变意思我很抱歉:它相当令人困惑,所以我的解释是这样的。然而,这个解决方案不应该是为了适应那个工作而进行的:请看我的编辑。 - Michael Harper
谢谢,这看起来非常不错!有没有一种方法可以随机化堆栈内18个组的父级颜色,而不是遵循彩虹调色板?由于我有很多颜色,所以区分它们很棘手。比如说,如果深红色组紧挨着浅蓝色和黄色,而不是在深蓝色和浅蓝色之间,那就太好了。 - nicole
颜色调色板是由函数中的scales::hue_pal(l = 100)(nrow(categories))参数选择的。您可以用与不同类别数量相同长度的颜色向量替换它,例如c("purple", "blue", "pink")。请参见此处以获取更多颜色。http://sape.inf.usi.ch/quick-reference/ggplot2/colour 如果您满意,请点赞并接受我的答案 :) - Michael Harper

4
实现颜色渐变的更简单方法是使用alpha来改变颜色的透明度。然而,这可能会产生意想不到的后果,因为透明度意味着您可以通过图表看到指南线。
library(ggplot2)

ggplot(diamonds, aes(color, alpha = clarity)) + 
  geom_bar(aes(fill = color), colour = "grey") +
  scale_alpha_discrete(range = c(0,1))

enter image description here


1

最近我创建了一个名为ggnested的软件包,它可以创建这样的图表。它本质上是ggplot2的一个包装器,可以在美学映射中使用main_groupsub_group,其中为main_group生成颜色,并为嵌套在每个main_group级别内的sub_group级别生成渐变。

devtools::install_github("gmteunisse/ggnested")
require(ggnested)
data(diamonds)
ggnested(diamonds, aes(main_group = color, sub_group = clarity)) +
  geom_bar(aes(x = color))

Example of a nested bar plot created with ggnested


0

另一个选项是使用任何自定义颜色调色板,并根据填充类别简单地加深/减淡颜色。在每个条形图中获得平滑渐变可能稍微棘手,但如果保持数据的自然顺序(无论是数据框中的外观还是因素级别),这不是一个大问题。

我正在使用 colorspace包 完成此任务。shades包 也有加深/减淡颜色的选项,但是语法略长。它更适合修改整个调色板而不指定特定颜色。

library(tidyverse)
library(colorspace)

## get some random colors, here n colors based on the Dark2 palette using the colorspace package.
## But ANY palette is possible
my_cols <- qualitative_hcl(length(unique(diamonds$color)), "Dark2")
## for easier assignment, name the colors
names(my_cols) <- unique(diamonds$color)

## assign the color to the category, by group
df_grad <-
  diamonds %>%
  group_by(color) %>%
  ## to keep the order of your stack and a natural gradient
  ## use order by occurrence in data frame or by factor
  ## clarity is an ordered factor, so I'm using a dense rank
  mutate(
    clarity_rank = dense_rank(as.integer(clarity)),
    new_cols = my_cols[color],
    ## now darken or lighten according to the rank
    clarity_dark = darken(new_cols, amount = clarity_rank / 10),
    clarity_light = lighten(new_cols, amount = clarity_rank / 10)
  )

## use this new color for your fill with scale_identity
## you additionally need to keep your ordering variable as group, in this case
## an interaction between color and your new rank
ggplot(df_grad, aes(color, group = interaction(color, clarity_rank))) +
  geom_bar(aes(fill = clarity_dark)) +
  scale_fill_identity()

ggplot(df_grad, aes(color, group = interaction(color, clarity_rank))) +
  geom_bar(aes(fill = clarity_light)) +
  scale_fill_identity()

reprex package (v2.0.1)于2022年7月3日创建


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