Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ggplot2 change fill for color legend when fill also used in aesthetic

Tags:

r

ggplot2

Is there a way to control the fill for the color legend when fill is also used in the aesthetic in ggplot2?

Ex.

dat<-data.frame(id=as.character(1:4), var1=rep(LETTERS[1:2], 2), var2=rep(LETTERS[3:4], 2))
dat
library(ggplot2)

ggplot(dat)+
  geom_bar(aes(id, color=var1, fill=var2))+
  scale_color_manual(values=c("A"="black", "B"="grey"))+
  theme_light()

In this legend it is very hard to see the light grey border around the darker gray fill in the color legend. I will admit it may not be a good practice to specify color and fill in the same plot as it can become difficult to understand which color means what and the colored borders around the filled objects can be hard to differentiate, but how would I do it if I wanted to?

Here the background color for the color variable makes it difficult to see the grey outline

By manually specifying fill in the plot, the fill color in the legend can be controlled when not also specifying fill.

ggplot(dat)+
  geom_bar(aes(id, color=var1), fill="white")+
  theme_light()

enter image description here I thought there would be a way to control this using an argument in theme, but theme(legend.background=element_rect()) controls the background of the whole legend (and rightly so)

ggplot(dat)+
  geom_bar(aes(id, color=var1, fill=var2))+
  scale_color_manual(values=c("A"="black", "B"="grey"))+
  theme_light()+
  theme(legend.background = element_rect(fill="blue"))

enter image description here

Also in theme, theme(legend.key = element_rect(fill="blue")) only adds a thin blue line around the var2 boxes in the legend, legend.box controls the arrangement of multiple legends ("horizontal" or "vertical"), and theme(legend.box.background = element_rect(fill="blue")) colors the background between the var1 and var2 legends.

I thought perhaps the legend was using the default value for NA for the fill, so I tried specifying this manually using scale_color_discrete()

ggplot(dat)+
  geom_bar(aes(id, color=var1, fill=var2))+
  scale_color_manual(values=c("A"="black", "B"="grey", 
                              na.translate=TRUE, na.value = "white"))+
  theme_light()

Looks the same as the first plot.

This seems like something that should be controlled by an argument in theme() or scale_color_manual, but I can't seem to figure it out.
Cheers

like image 789
Alex Thomas Avatar asked Sep 25 '19 00:09

Alex Thomas


1 Answers

For data-related aspects of the legend, theme() won't help you. Instead you need to use guides and override the fill for the color legend:

ggplot(dat)+
    geom_bar(aes(id, color=var1, fill=var2))+
    scale_color_manual(values=c("A"="black", "B"="grey"))+
    guides(color = guide_legend(override.aes = list(fill = "white"))) +
    theme_light()

The general rule is that theme() only controls the overall look of the plot, not the data-dependent parts like scales (maybe instead of "data-dependent" it should be "the parts of the plot that vary based on data").

like image 111
Marius Avatar answered Oct 24 '22 22:10

Marius