简体   繁体   中英

Map colors to labels in ggplot based on background color

How does one change the color of the text in ggplot? For example, I have a stacked bar plot. I want to make the labels black when the background is light blue or green.

Here is a meaningless dummy sample:

library(dplyr)
library(ggplot2)
df <- mpg %>% 
  mutate(cyl = as.character(cyl)) %>% 
  group_by(model, cyl) %>% 
  summarize(hwy = mean(hwy), .groups = "keep") %>% 
  ungroup() %>% 
  group_by(model) %>% 
  mutate(hwy = round(hwy / sum(hwy), 2)) %>% 
  ungroup() %>% 
  head(11) %>% 
  mutate(color = case_when(cyl == "4" ~ "white", 
                           cyl == "6" ~ "black", 
                           cyl == "8" ~ "black"))

df %>% 
  ggplot(data = ., aes(x = model, y = hwy, fill = cyl, label = hwy)) + 
  geom_bar(stat = "identity", position = "fill") + 
  geom_text(color = "white", position = position_stack(vjust = 0.5)) + 
  scale_fill_manual(values = c("dark blue", "light blue", "green"), 
                    name = "cyl",
                    breaks = c("4", "6", "8"),
                    labels = c("4", "6", "8"))

阴谋

I tried using scale_color_manual , as in this example ( More than 1 color in geom_text() ) but it didn't work. The solution in this example didn't even work for me on the sample in the question itself. Maybe because it's 8 years old, idk.

Either a solution that chooses colors dynamically in the ggplot call based on the fill color or one that maps the "color" variable to text colors would work.

Borrowing a code snippet from scales::show_col to set the label colors according to the luminance of the fill colors to either "black" or "white" one option to achieve your desired result may look like so:

library(dplyr)
library(ggplot2)
library(carver)

fill_colors <- c("dark blue", "light blue", "green")
# Borrowed from scales::show_col
hcl <- farver::decode_colour(fill_colors, "rgb", "hcl")
label_col <- ifelse(hcl[, "l"] > 50, "black", "white")

df %>% 
  ggplot(data = ., aes(x = model, y = hwy, fill = cyl, label = hwy)) + 
  geom_bar(stat = "identity", position = "fill") + 
  geom_text(aes(color = cyl), position = position_stack(vjust = 0.5), show.legend = FALSE) + 
  scale_fill_manual(values = fill_colors, 
                    name = "cyl",
                    breaks = c("4", "6", "8"),
                    labels = c("4", "6", "8")) +
  scale_color_manual(values = label_col)

Since you already have the colors you want, white and black, computed in the mutate statement, map color = cyl (the same as the fill aesthetics) and add a scale_color_manual with the required values.

df %>% 
  ggplot(aes(x = model, y = hwy, fill = cyl)) + 
  geom_bar(stat = "identity", position = "fill") + 
  geom_text(aes(color = cyl, label = hwy),
            position = position_stack(vjust = 0.5),
            show.legend = FALSE) + 
  scale_fill_manual(name = "cyl",
                    values = c("dark blue", "light blue", "green"), 
                    breaks = c("4", "6", "8"),
                    labels = c("4", "6", "8")) +
  scale_color_manual(values = c("white", "black", "black"),
                     breaks = c("4", "6", "8"))

在此处输入图像描述

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM