如何在不同的ggplot列图中为相同类别使用相同的填充颜色?

huangapple go评论157阅读模式
英文:

How can I use the same fill colour for same category on different ggplot column plots?

问题

这段代码创建了一个图表,但在两个不同的图中,"Kategorie 2" 和 "Kategorie 16" 共享相同的颜色,但它们应该有不同的颜色。您想要如何解决这个问题?

英文:

I have a dataset which has a variable "Kategorie". From that dataset I need to create different plots, based on some filter and grouping. I created a vector which maps the Kategorie values to the colours I have choosen for them, to be used as fill with scale_fill_manual. Additionally I want to reorder the X axis, depending on the categories value, like in a scree plot, biggest category left, smallest category right. As I have another variable with two values, I came across a facet_grid on that variable. But ordering of the X axis was not working. Thus I came across grid.arrange and subset. X axis ordering is fine now.
But the issue I face now is that the colour is not consistent on the categories on the two facets. How can I get consistent colours for categories amongst different plots, either created within one ggplot call with facets or with separate ggplot calls?

library(dplyr)
library(ggplot2)
library(ggthemes)
library(gridExtra)

options(dplyr.summarise.inform = FALSE)

human_numbers <- function(x = NULL,
                          smbl = "",
                          signif = 1) {
  humanity <- function(y) {
    if (!is.na(y)) {
      tn <- round(abs(y) / 1e12, signif)
      b <- round(abs(y) / 1e9, signif)
      m <- round(abs(y) / 1e6, signif)
      k <- round(abs(y) / 1e3, signif)
      
      if (y >= 0) {
        y_is_positive <- ""
      } else {
        y_is_positive <- "-"
      }
      
      if (k < 1) {
        paste0(y_is_positive, smbl, round(abs(y), signif))
      } else if (m < 1) {
        paste0 (y_is_positive, smbl,  k , "k")
      } else if (b < 1) {
        paste0 (y_is_positive, smbl, m , "m")
      } else if (tn < 1) {
        paste0 (y_is_positive, smbl, b , "bn")
      } else {
        paste0 (y_is_positive, smbl,  comma(tn), "tn")
      }
    } else if (is.na(y) | is.null(y)) {
      "-"
    }
  }
  
  sapply(x, humanity)
}

human_euro  <- function(x){human_numbers(x, smbl = "\u20AC")} 
human_num   <- function(x){human_numbers(x, smbl = "")} 

x <- structure(list(Wer = c("Abt1", "Abt1", "Abt1", "Abt1", "Abt1", 
                            "Abt1", "Abt1", "Abt1", "Abt1", "Abt1", "Abt1", "Abt1", 
                            "Abt1", "Abt1", "Abt1", "Abt2", "Abt2", "Abt2", "Abt2", 
                            "Abt2", "Abt2", "Abt2", "Abt2", "Abt2", "Abt2", "Abt2", 
                            "Abt2", "Abt2", "Abt2", "Abt2", "Abt2"), 
                    Kategorie = c("Kategorie 1", 
                                  "Kategorie 2", "Kategorie 3", "Kategorie 4", "Kategorie 5", "Kategorie 6", 
                                  "Kategorie 7", "Kategorie 8", "Kategorie 9", "Kategorie 10", "Kategorie 11", "Kategorie 12", 
                                  "Kategorie 13", "Kategorie 14", "Kategorie 15", "Kategorie 1", "Kategorie 16", "Kategorie 2", 
                                  "Kategorie 9", "Kategorie 5", "Kategorie 7", "Kategorie 13", "Kategorie 3", 
                                  "Kategorie 10", "Kategorie 6", "Kategorie 8", "Kategorie 17", "Kategorie 14", 
                                  "Kategorie 11", "Kategorie 15", "Kategorie 12"), 
                    Wert = c(9130, 8974.06, 
                             7973.7, 5151.84, 4442.31, 2199.6, 2174.53, 1694.6, 938.46, 587.85, 
                             441.1, 419.69, 196.54, 115.44, 16.85, 24775, 11660.44, 10666.48, 
                             6881.8, 3958.39, 2144.34, 1609.53, 1500.77, 1405, 986.4, 882.89, 
                             812.7, 798.68, 336.29, 235.12, 12.3), 
                    Anteil = c(20.5, 20.2, 
                               17.9, 11.6, 10, 4.9, 4.9, 3.8, 2.1, 1.3, 1, 0.9, 0.4, 0.3, 0, 
                               36.1, 17, 15.5, 10, 5.8, 3.1, 2.3, 2.2, 2, 1.4, 1.3, 1.2, 1.2, 
                               0.5, 0.3, 0)), 
               row.names = c(NA, -31L), 
               groups = structure(
                 list(
                   Wer = c("Abt1", "Abt2"), 
                   .rows = structure(
                     list(1:15, 16:31), 
                     ptype = integer(0), 
                     class = c("vctrs_list_of", "vctrs_vctr", "list"))
                 ), 
                 row.names = c(NA, -2L), 
                 class = c("tbl_df", "tbl", "data.frame"), 
                 .drop = TRUE
               ), 
               class = c("grouped_df", "tbl_df", "tbl", "data.frame")
)

color_palette <- c(
  "dodgerblue2", 
  "#E31A1C", # red
  "green4",
  "#6A3D9A", # purple
  "#FF7F00", # orange
  "black", 
  #"gold1",
  "skyblue2", 
  "#FB9A99", # lt pink
  "palegreen2",
  #"#CAB2D6", # lt purple
  "#FDBF6F", # lt orange
  "gray70", 
  #"khaki2",
  "maroon", 
  "orchid1", 
  #"deeppink1", 
  "blue1", 
  "steelblue4",
  "darkturquoise", 
  "green1", 
  #"yellow4", 
  "yellow3",
  #"darkorange4", 
  "brown4"
)

names(color_palette) <- levels(unique(x$Kategorie))

q1 <- x %>% subset(Wer == 'Abt1') %>%
  ggplot(aes(x=reorder(Kategorie, -Wert), y=Wert, fill=Kategorie)) +
  geom_col(width=0.6) +
  facet_grid(. ~ Wer) +
  geom_text(aes(label=scales::comma(Anteil, big.mark='.', decimal.mark=',', suffix='%')), vjust=-0.1, hjust=-0.1, angle=60, color="black", size=4) +
  scale_y_continuous(labels = human_euro) +
  scale_fill_manual(name = "Kategorie", values = color_palette) +
  coord_cartesian(clip = "off") +
  theme_minimal() +
  theme(plot.title = element_text(size = 16, hjust = 0.5)) +
  theme(axis.text = element_text(size = 12)) +
  theme(axis.text.x = element_text(angle = 60, hjust = 1)) +
  theme(axis.title.x = element_blank()) +
  theme(axis.title.y = element_blank()) +
  theme(legend.position = "none")

q2 <- q1 %+% subset(x, Wer == 'Abt2')

grid.arrange(q1, q2, nrow=1)

With this code the output looks like this. Notice that "Kategorie 2" and "Kategorie 16" share the same colour, but they should have different colours.

如何在不同的ggplot列图中为相同类别使用相同的填充颜色?

答案1

得分: 1

你可以像这样设置一个通用的比例尺(示例数据):

categories = c('a long label',
               'another long label',
               'not short either'
               )

d1 <- data.frame(source = 1, cat = head(categories, 2), value = 1:2)
d2 <- data.frame(source = 2, cat = tail(categories, 2), value = 4:5)

my_scale <- scale_fill_manual(
  breaks = categories,
  values = c('red', 'blue', 'green')
)

p1 <- ggplot(d1) +  geom_col(aes(cat, value, fill = cat)) + my_scale
p2 <- ggplot(d2) +  geom_col(aes(cat, value, fill = cat)) + my_scale

p1 + p2

注意,然而,这将使读者更难比较类别(甚至阅读标签),而不是简单地像这样对齐类别:

bind_rows(d1, d2) %>%
  ggplot() +
  geom_col(aes(cat, value)) +
  coord_flip() + 
  facet_wrap(~ source) 

如何在不同的ggplot列图中为相同类别使用相同的填充颜色?

英文:

you can set up a common scale like this (example data):

categories = c(&#39;a long label&#39;,
               &#39;another long label&#39;,
               &#39;not short either&#39;
               )

d1 &lt;- data.frame(source = 1, cat = head(categories, 2), value = 1:2)
d2 &lt;- data.frame(source = 2, cat = tail(categories, 2), value = 4:5)

my_scale &lt;- scale_fill_manual(
  breaks = categories,
  values = c(&#39;red&#39;, &#39;blue&#39;, &#39;green&#39;)
)

p1 &lt;- ggplot(d1) +  geom_col(aes(cat, value, fill = cat)) + my_scale
p2 &lt;- ggplot(d2) +  geom_col(aes(cat, value, fill = cat)) + my_scale

p1 + p2

如何在不同的ggplot列图中为相同类别使用相同的填充颜色?
note, however, that this will make it much harder for the reader to compare categories (or even read the labels) than simply aligning categories like this:

bind_rows(d1, d2) |&gt;
  ggplot() +
  geom_col(aes(cat, value)) +
  coord_flip() + 
  facet_wrap(~ source) 

如何在不同的ggplot列图中为相同类别使用相同的填充颜色?

huangapple
  • 本文由 发表于 2023年6月5日 00:47:44
  • 转载请务必保留本文链接:https://go.coder-hub.com/76401452.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定