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
p + scale_color_identity()
? – HenrikisDark
function – Henrikgeom_text
in a variable ("LabelColor") ("i.e. it already represents aesthetic values that ggplot2 can handle directly"; from?scale_color_identity
). See also Using a pre-defined color palette in ggplot and ggplot: colour points by groups based on user defined colours – Henrik