CptNemo
CptNemo

Reputation: 6755

How to dynamically and elegantly change colour of geom_text based on filling value

I have this heatmap with value labels added to each tile

require(ggplot2)
require(RColorBrewer)
require(dplyr)

jBuPuFun <- colorRampPalette(brewer.pal(n = 9, "BuPu"))
paletteSize <- 256
jBuPuPalette <- jBuPuFun(paletteSize)

nba <- read.csv("http://datasets.flowingdata.com/ppg2008.csv")
nba$Name <- with(nba, reorder(Name, PTS))
nba.m <- melt(nba)
nba.m <- ddply(nba.m, .(variable), transform,
               rescale = rescale(value))

ggplot(nba.m, aes(variable, Name)) + 
  geom_tile(aes(fill = rescale), colour = "white") + 
  scale_fill_gradient2(low = jBuPuPalette[1],
                       mid = jBuPuPalette[paletteSize/2],
                       high = jBuPuPalette[paletteSize],
                       midpoint = 0.5) +
  geom_text(aes(fill = rescale, label = round(rescale, 1)), colour = "white")

Nevertheless labels maintain a uniform colour (white) which make them difficult to read when the background is also light.

enter image description here

Is there any elegant way to dynamically define the color of each geom_text based on the filling value?

Upvotes: 2

Views: 1327

Answers (1)

Rorschach
Rorschach

Reputation: 32426

If you color the text in the reverse of the fill, you can get decent results. I changed the midpoint of the reverse coloring to "steelblue" because the colors will be hard to differentiate at the midpoint if you don't tweak it there.

p <- ggplot(nba.m, aes(variable, Name)) + 
  geom_tile(aes(fill = rescale), color="white") + 
  scale_fill_gradient2(low = jBuPuPalette[1],
                       mid = jBuPuPalette[paletteSize/2],
                       high = jBuPuPalette[paletteSize],
                       midpoint = 0.5) +
  scale_color_gradient2(low = jBuPuPalette[paletteSize],
                       mid = "steelblue",
                       high = jBuPuPalette[1],
                       midpoint = 0.5) +
  geom_text(aes(fill = rescale, color=rescale, label = round(rescale, 1)))

Upvotes: 1

Related Questions