Set a color to show clear the numbers
Asked Answered
M

2

5

In this bar chart for the specific viridis option is it possible to set of color which can show the numbers inside the chart clear even for the darker option of the scale?

library(ggplot2)
Year      <- c(rep(c("2006-07", "2007-08", "2008-09", "2009-10"), each = 4))
Category  <- c(rep(c("A", "B", "C", "D"), times = 4))
Frequency <- c(168, 259, 226, 340, 216, 431, 319, 368, 423, 645, 234, 685, 166, 467, 274, 251)
Data      <- data.frame(Year, Category, Frequency)
ggplot(Data, aes(x = Year, y = Frequency, fill = Category, label = Frequency)) +
  geom_bar(stat = "identity") +
  geom_text(size = 3, position = position_stack(vjust = 0.5)) +  scale_fill_viridis_d(option  = "magma")
Migraine answered 8/7, 2020 at 17:56 Comment(1)
F
11

Making use of a trick I learned from scales::show_col you can choose the text color automatically according to the fill like so:

library(ggplot2)
Year      <- c(rep(c("2006-07", "2007-08", "2008-09", "2009-10"), each = 4))
Category  <- c(rep(c("A", "B", "C", "D"), times = 4))
Frequency <- c(168, 259, 226, 340, 216, 431, 319, 368, 423, 645, 234, 685, 166, 467, 274, 251)
Data      <- data.frame(Year, Category, Frequency)

# Trick from scales::show_col
hcl <- farver::decode_colour(viridisLite::magma(length(unique(Category))), "rgb", "hcl")
label_col <- ifelse(hcl[, "l"] > 50, "black", "white")

ggplot(Data, aes(x = Year, y = Frequency, fill = Category, label = Frequency)) +
  geom_bar(stat = "identity") +
  geom_text(aes(color = Category), size = 3, position = position_stack(vjust = 0.5), show.legend = FALSE) +  
  scale_color_manual(values = label_col) +
  scale_fill_viridis_d(option  = "magma")

EDIT

A second option which I learned recently would be to make use of ggplot2::after_scale and prismatic::best_contrast to automatically pick the text color with best contrast like so:

library(prismatic)

ggplot(Data, aes(x = Year, y = Frequency, fill = Category, label = Frequency)) +
  geom_bar(stat = "identity") +
  geom_text(aes(color = after_scale(
    prismatic::best_contrast(fill, c("white", "black"))
  )),
  size = 3, position = position_stack(vjust = 0.5), show.legend = FALSE
  ) +
  scale_fill_viridis_d(option = "magma")
Fernando answered 8/7, 2020 at 18:8 Comment(2)
Great solution, and it does not mess up the positioning like geom_label or ggtext::geom_textbox tend to do with position_stack...Occlude
Second solution works great! Just a tip that you want the aes information in the main ggplot call not the geom call or it doesn't pick it upPacket
E
3

Try this:

Replace geom_text(...) with geom_label(fill = "white", ...) which automatically provides a label "box".


library(ggplot2)

ggplot(Data, aes(x = Year, y = Frequency, fill = Category, label = Frequency)) +
  geom_bar(stat = "identity") +
  geom_label(size = 3, position = position_stack(vjust = 0.5), fill = "white") +
  scale_fill_viridis_d(option  = "magma")

Created on 2020-07-08 by the reprex package (v0.3.0)

Edelweiss answered 8/7, 2020 at 18:6 Comment(2)
Please also comment on what you did in plain English.Bisayas
Note that if you're using a static value for fill, it can be called outside of aes.Bisayas

© 2022 - 2024 — McMap. All rights reserved.