Tom Francart
Tom Francart

Reputation: 53

Show letters as key glyphs for geom_text legend instead of default 'a'

I'm using geom_raster and geom_text to put a letter on each of the coloured rectangles in my plot. I'd like this letter to appear on top of the color boxes in the legend as well, but cannot figure out how.

I've tried adding show.legend=TRUE to the geom_text, but this results in the letter 'a' in each legend key, instead of the desired character.

The desired result looks as follows:

Desired result

Here is code to reproduce the basic plot:

library(tidyverse)
d <-tribble(
    ~a, ~b, ~c,
    "a", "l", "A",
    "a", "r", "F",
    "b", "l", "Q",
    "b", "r", "R"
)

ggplot(data=d, aes(x=a, y=b, fill=c)) +
    geom_raster(na.rm=TRUE) +
    geom_text(aes(label=c), size=3, na.rm=TRUE) 

And the output:

example without desired labels

This might be related to this issue: https://github.com/tidyverse/ggplot2/issues/2004, but perhaps there's a workaround?

Upvotes: 5

Views: 962

Answers (2)

Z.Lin
Z.Lin

Reputation: 29085

You can hack it after turning the ggplot object into a grob:

# store the original ggplot object as p
p <- ggplot(data=d, aes(x=a, y=b, fill=c)) +
  geom_raster(na.rm=TRUE) +
  geom_text(aes(label=c), size=3, na.rm=TRUE, show.legend = TRUE) 

# convert to grob
gp <- ggplotGrob(p)

grid::grid.draw(gp) # can verify the plot here. Should look the same as before.

Now we can examine the hierarchical structure of the grob object to find appropriate slots to change the legend keys. It's possible to do this programmatically as well, but unless your use case involves generating many different charts with different number of legend keys, I find it easier to read off the console output:

gp # this shows the 15th grob in gp corresponds to "guide-box" (i.e. legend)

gp$grobs[15][[1]] # this shows the the first grob of the above corresponds to "guides"

gp$grobs[15][[1]]$grobs[1][[1]] 
# this shows the 5th / 8th / 11th / 14th grobs of the above correspond to the text on legend keys

str(gp$grobs[15][[1]]$grobs[1][[1]]$grobs[5][[1]])
# each of the legend key texts is a list, with a slot for "label"

Change the legend keys accordingly:

gp$grobs[15][[1]]$grobs[1][[1]]$grobs[5][[1]]$label <- "A"
gp$grobs[15][[1]]$grobs[1][[1]]$grobs[8][[1]]$label <- "F"
gp$grobs[15][[1]]$grobs[1][[1]]$grobs[11][[1]]$label <- "Q"
gp$grobs[15][[1]]$grobs[1][[1]]$grobs[14][[1]]$label <- "R"

# check the amended plot
grid::grid.draw(gp)

plot

Upvotes: 2

pogibas
pogibas

Reputation: 28339

You can use geom_point instead and specify point shape as letters with scale_shape_manual(values = d$c).

# We have to remove legend text and label with theme
ggplot(d, aes(a, b, fill = c, shape = c)) +
    geom_raster() +
    geom_point(size = 3) +
    scale_shape_manual(values = d$c) +
    theme(legend.text = element_text(size = 0),
          legend.title = element_text(size = 0))

enter image description here

Upvotes: 5

Related Questions