Matt Denwood
Matt Denwood

Reputation: 2583

Fine control of ggplot2 legend using guides() when mixing geom_point() and geom_rect()

I would like to fill ggplot facets with different background colours using geom_rect(), but am having trouble with some unwanted side-effects on the appearance of the legend. I've tried the help file for guides() as well as googling and searching for answers on here, but not found anything that solves the issue.

For example take this dataset:

library("tidyverse")

expand_grid(A=1:3, B=1:3, iter=seq_len(50)) |>
    filter(A!=B) |>
    mutate(C = sample(c("c1","c2"), n(), TRUE), D = rnorm(n(), mean=c(c1=0,c2=1)[C])) |>
    group_by(A, B, C) |>
    summarise(Dmu = mean(D), Dlci = quantile(D, 0.025), 
            Duci = quantile(D, 0.975), bgf="no", .groups="drop") |>
    bind_rows( tibble(A=1:3, B=1:3, C="c1", bgf = "yes")) ->
fakedata

The basic idea is that each combination of A and B has two values of C each with their own Dmu, except that D is missing when A==B. The dataset has bgf equal to "yes" where A==B and "no" otherwise.

I can plot Dmu in different colours depending on C, with a facet grid of A and B, like so:

ggplot(fakedata, aes(x=C, y=Dmu, ymin=Dlci, ymax=Duci, col=C, group=C, fill=bgf)) +
    geom_errorbar() + 
    geom_point() + 
    facet_grid(A ~ B) +
    scale_fill_manual(values=c(no="transparent", yes="hotpink")) +
    guides(fill="none", col=guide_legend("")) +
    theme_bw() +
    theme(legend.pos="bottom") ->
pt1

Plot 1

This aes() has fill which is (so far) ignored, so I need to limit the legend to only indicate col using guides(). That all works as expected.

But now I would like to give the diagonal facets a nice background colour, which I can do like so:

pt1 +
    geom_rect(xmin=-Inf, xmax=Inf, ymin=-Inf, ymax=Inf) ->
pt2

Plot 2

This gives what I want except that the legend appearance has changed: I now have grey squares instead of the lines/points on the legend of the first plot. I naively expected the legend to remain unchanged because I have already specified guides(fill="none") in the ggplot call.

I am sure I am doing something wrong, but am at a bit of a loss. Any pointers?

Otherwise, a workaround would also be gratefully received - for example I am vaguely aware that some kind of legend transplant from plot 1 to plot 2 may be possible by directly manipulating the grobs, but that kind of wizardry is somewhat beyond my current abilities...


For reference, I am using ggplot2 development version 3.3.5.9000 (obtained just now using devtools::install_github("tidyverse/ggplot2")) but the same behaviour is seen with the current CRAN version of ggplot2 (3.3.5).

Upvotes: 1

Views: 145

Answers (1)

Susan Switzer
Susan Switzer

Reputation: 1922

You can update geom_rect to add show.legend = F

geom_rect(xmin=-Inf, xmax=Inf, ymin=-Inf, ymax=Inf, show.legend = F)

Upvotes: 1

Related Questions