Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to control label color depending on fill darkness of bars?

Tags:

r

ggplot2

I have a stacked bar plot, labelled with geom_text. To increase the visibility of the labels, I want to set the label color to either white or black depending of the 'darkness' of their background, i.e. the fill color of the bars. Thus, darker bars should have a white label, and lighter bars should have a black label.

I started with code from the question Showing data values on stacked bar chart in ggplot2, the answer to the question Is there a is light or is dark color function in R?. On top of that I'd like to show the label of the data value in 'white' or 'black' depending whether the stacked bar fill color is dark or not dark respectively.

I made two attempts. The first is using aes(colour=...) of the geom_text function but this one fails ... why?.

The second attempt is using the function scale_colour_manual. But here the stacked bar lines are also "coloured" using the black or white toggling setting.

library(ggplot2)
library(RColorBrewer)

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)

isDark <- function(color) {
  (sum(grDevices::col2rgb(color) *c(299, 587,114))/1000 < 123)
}

## control the color assignments
paletteName <- 'Set1' # 'Dark2'
colorsPerCat <- brewer.pal(name=paletteName,n=4)
names(colorsPerCat) <- c("A", "B", "C", "D")

## First attempt
Data$LabelColor <- as.character(as.vector(sapply(unlist(colorsPerCat)[Data$Category], function(color) { if (isDark(color)) 'white' else 'black' })))
Data
p <- ggplot(Data, aes(x = Year, y = Frequency, fill = Category, label = Frequency)) +
  geom_bar(stat = "identity") +
  geom_text(aes(colour=LabelColor), size = 3, position = position_stack(vjust = 0.5)) +
  scale_fill_manual(values = colorsPerCat)
p

## Second attempt
labelColoursPerCat <- sapply(as.vector(colorsPerCat), function(color) { if (isDark(color)) 'white' else 'black' })
names(labelColoursPerCat) <- c("A", "B", "C", "D")
p <- ggplot(Data, aes(x = Year, y = Frequency, fill = Category, label = Frequency, colour = Category)) +
  geom_bar(stat = "identity") +
  geom_text(size = 3, position = position_stack(vjust = 0.5)) +
  scale_fill_manual(values = colorsPerCat) +
  scale_colour_manual(values = labelColoursPerCat)
p
like image 722
SkyWalker Avatar asked Oct 28 '22 15:10

SkyWalker


1 Answers

Two ways to solve this issue by playing with geom_bar color or size:

Data$LabelColor <- as.factor(Data$LabelColor)
p <- ggplot(Data, aes(x = Year, y = Frequency, fill = Category, label = Frequency, colour = LabelColor)) +
              geom_bar(stat = "identity", color = "black") +
              geom_text(size = 3, position = position_stack(vjust = 0.5)) +
              scale_fill_manual(values = colorsPerCat) +  
              scale_colour_manual(values = levels(Data$LabelColor)) +
              guides(colour = FALSE)

enter image description here

Data$LabelColor <- as.factor(Data$LabelColor)
p <- ggplot(Data, aes(x = Year, y = Frequency, fill = Category, label = Frequency, colour=LabelColor)) +
              geom_bar(stat = "identity", size = 0) +
              geom_text(size = 3, position = position_stack(vjust = 0.5)) +
              scale_colour_manual(values = levels(Data$LabelColor)) +
              scale_fill_manual(values = colorsPerCat) +  
              guides(colour = FALSE)

enter image description here

like image 96
DJack Avatar answered Nov 15 '22 07:11

DJack