Home > Net >  How can I show legend of multiple layers (geom_point and geom_bar)?
How can I show legend of multiple layers (geom_point and geom_bar)?

Time:05-09

I have two data sets that I want to combine into one plot, one as a barplot (2 groups) and one as a point-line plot (1 group). I've managed to combine the plots and show the legend for the barplot, but whenever I try to show the legend for the points/line it doesn't work.

Here is an excerpt of my data sets (translated):

bargroup <- data.frame('Year' = as.numeric(rep(2001:2004, each = 2)),
                     'Group' = as.factor(rep(c('State', 'Country'), 4)),
                     'Share' = as.numeric(c(0.42, 0.41, 0.4, 0.4, 0.42, 0.4, 0.42, 0.38)))

plgroup <- data.frame('Year' = as.numeric(2001:2004),
                             'Group' = as.factor(rep('State', 4)),
                             'Value' = as.numeric(c(4.95, 5.31, 5.29, 4.96)))

Here's my current code:

ggplot()  
geom_bar(data = bargroup, aes(x = Year, y = Share, fill = Group, group = Group),
           stat = 'identity', position = position_dodge2(preserve = 'single'))  
  geom_point(data = plgroup, aes(y = Value*0.1, x = Year), size = 4, color = '#875DA3')  
  geom_line(data = plgroup, aes(y = Value*0.1, x = Year), size = 1, color = '#875DA3')  
  labs(x = 'Year')  
  scale_y_continuous(name = 'Share groups', labels = scales::percent,
                     sec.axis = sec_axis(~.*10, name = 'Cost'))  
  scale_fill_manual(labels = c('Share State', 'Share Country'), 
                    values = c('#659B7A', '#8CD7F0'))  
  scale_color_manual(labels = c('Total Cost'), 
                values = c('#875DA3'))  
  theme_minimal()  
  theme(legend.title = element_blank(),
        legend.position = 'bottom',
        plot.title = element_blank(),
        panel.grid.minor = element_blank(),
        axis.title.x = element_text(size = 18),
        axis.title.y = element_text(size = 18),
        axis.text = element_text(size = 16),
        legend.text = element_text(size = 18))  
  guides(fill = guide_legend(nrow = 2, byrow = T))
dev.off()

This is the graph I get:

Graph 1

As you can see, the point/line group is not displayed in the legend. I then tried removing the argument scale_color_manual() and adjusting the geom_point() and geom_line() arguments like so:

  geom_point(data = plgroup, aes(y = Value*0.1, x = Year, color = Group), 
             size = 4, color = '#875DA3', show.legend = T)
  geom_line(data = plgroup, aes(y = Value*0.1, x = Year, color = Group),
            size = 1, color = '#875DA3', show.legend = T)

The graph I got from this was:

Graph 2

I got that same graph when I combined the two data sets using the melt() function.

I also tried just making 3 groups out of it and not showing the point/line group. That showed all 3 groups but unfortunately the point/line group was now - obviously - labeled with a square instead of its point/line symbol (in the legend).

Does anyone have any idea how I can adjust my code to show the point/line group as a single bullet point next to or below the other two groups? Preferably also with the option to pick the label name ('Total Cost').

Thank you so much in advance!

CodePudding user response:

Rule of thumb: everything within aes() will produce a legend. So put size out of aes() AND color into aes():

ggplot()  
  geom_bar(data = bargroup, aes(x = Year, y = Share, fill = Group, group = Group),
           stat = 'identity', position = position_dodge2(preserve = 'single'))  
  geom_point(data = plgroup, aes(y = Value*0.1, x = Year, color = '#875DA3'),size = 4)  
  geom_line(data = plgroup, aes(y = Value*0.1, x = Year, color = '#875DA3'),size = 1)  
  labs(x = 'Year')  
  scale_y_continuous(name = 'Share groups', labels = scales::percent,
                     sec.axis = sec_axis(~.*10, name = 'Cost'))  
  scale_fill_manual(labels = c('Share State', 'Share Country'), 
                    values = c('#659B7A', '#8CD7F0'))  
  scale_color_manual(labels = c('Total Cost'), 
                     values = c('#875DA3'))  
  theme_minimal()  
  theme(legend.title = element_blank(),
        legend.position = 'bottom',
        plot.title = element_blank(),
        panel.grid.minor = element_blank(),
        axis.title.x = element_text(size = 18),
        axis.title.y = element_text(size = 18),
        axis.text = element_text(size = 16),
        legend.text = element_text(size = 18))  
  guides(fill = guide_legend(nrow = 2, byrow = T))

enter image description here

Changing the order of legend:

guides(fill = guide_legend(nrow = 2, byrow = T, order=1))

enter image description here

  • Related