Ggplot2: combine legends for geom_line, geom_point and geom_bar

In ggplot2 graphics ggplot2 I combine geom_line and geom_point with geom_bar , and I am having problems combining legends into one box.

The code for the main plot is below. The data used is even lower.

 # Packages library(ggplot2) library(scales) # Basic Plot ggplot(data = df1, aes(x = Year, y = value, group = variable, colour = variable, shape = variable)) + geom_line() + geom_point(size = 3) + geom_bar(data = df2, aes(x = Year, y = value, fill = variable), stat = "identity", alpha = 0.8) + ylab("Current Account Transactions (Billion $)") + xlab(NULL) + theme_bw(14) + scale_x_discrete(breaks = seq(1999, 2013, by = 2)) + scale_y_continuous(labels = dollar, limits = c(-1, 4), breaks = seq(-1, 4, by = .5)) + geom_hline(yintercept = 0) + theme(legend.key = element_blank(), legend.background = element_rect(colour = 'black', fill = 'white'), legend.position = "top", legend.title = element_blank()) + guides(col = guide_legend(ncol = 1), fill = NULL, colour = NULL) 

enter image description here

My goal is to bring legends together. For some reason, the “Current Account Balance” appears in the upper legend (I don’t understand why), while the “Export” and “Import” legend are corrupted by a black background and missing figures.

If I take fill outside aes , I can get the legend for “Import” and “Export” to display with the correct shapes and colors and no black background, but then I lose fill for “Current account balance”.

The trick I used before with some success, which should use scale_colour_manual , scale_shape_manual and scale_fill_manual (and possibly scale_alpha ) doesn't seem to work here. It would be good to do his job. But note that with this trick, as far as I know, you need to manually specify the colors, shapes and fills, which I really do not want to do, since I'm quite happy with the standard colors / shapes / bays.

I would usually do something similar, but this does not work:

 library(RColorBrewer) cols <- colorRampPalette(brewer.pal(9, "Set1"))(3) last_plot() + scale_colour_manual(name = "legend", values = cols) + scale_shape_manual(name = "legend", values = c(0,2,1)) + scale_fill_manual(name = "legend", values = "darkred") 

In the above I do not specify labels, because in my problem I will deal with a lot of data, and it would be impractical to specify labels manually. I would like ggplot2 to use default tags. For the same reason, I would like to use standard colors / shapes / fills.

Similar difficulties were described elsewhere, for example, here. Build a manual legend for a complex plot , but I could not apply solutions to my problem.

Any ideas?

 # Data df1 <- structure(list(Year = structure(c(1L, 2L, 3L, 4L, 5L, 6L, 7L, 8L, 9L, 10L, 11L, 12L, 13L, 14L, 15L, 1L, 2L, 3L, 4L, 5L, 6L, 7L, 8L, 9L, 10L, 11L, 12L, 13L, 14L, 15L), .Label = c("1999", "2000", "2001", "2002", "2003", "2004", "2005", "2006", "2007", "2008", "2009", "2010", "2011", "2012", "2013"), class = "factor"), variable = structure(c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L), .Label = c("Exports of goods and services", "Imports of goods and services"), class = "factor"), value = c(1.304557, 1.471532, 1.345165, 1.31879, 1.409053, 1.642291, 1.895983, 2.222124, 2.569492, 2.751949, 2.285922, 2.630799, 2.987571, 3.08526, 3.178744, 1.600087, 1.882288, 1.740493, 1.776877, 1.930395, 2.276059, 2.641418, 3.028851, 3.288135, 3.43859, 2.666714, 3.074729, 3.446914, 3.546009, 3.578998)), .Names = c("Year", "variable", "value"), row.names = c(NA, -30L), class = "data.frame") df2 <- structure(list(Year = structure(1:15, .Label = c("1999", "2000 ", "2001", "2002 ", "2003", "2004 ", "2005", "2006 ", "2007", "2008 ", "2009", "2010 ", "2011", "2012 ", "2013"), class = "factor"), variable = structure(c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L), .Label = "Balance on current account", class = "factor"), value = c(-0.29553, -0.410756, -0.395328, -0.458087, -0.521342, -0.633768, -0.745434, -0.806726, -0.718643, -0.686641, -0.380792, -0.44393, -0.459344, -0.460749, -0.400254)), .Names = c("Year", "variable", "value"), row.names = c(NA, -15L), class = "data.frame") 

EDIT

After posting my question and reading to Scott, I experimented with a different approach. He approaches the desired result in some way, but in others. The idea is to combine data into a single data block and transfer the color / shape / fill to aes inside the first ggplot call. The problem is that I get an unwanted slash according to legend. I could not remove the slashes without deleting all the colors. Another problem with this approach that I mentioned right away is that I need to specify a bunch of things manually, while I would like to keep the default values ​​where possible.

 df <- rbind(df1, df2) ggplot(data = df, aes(x = Year, y = value, group = variable, colour = variable, shape = variable, fill = variable)) + geom_line(data = subset(df, variable %in% c("Exports of goods and services", "Imports of goods and services"))) + geom_point(data = subset(df, variable %in% c("Exports of goods and services", "Imports of goods and services")), size = 3) + geom_bar(data = subset(df, variable %in% c("Balance on current account")), aes(x = Year, y = value, fill = variable), stat = "identity", alpha = 0.8) cols <- c(NA, "darkgreen", "darkblue") last_plot() + scale_colour_manual(name = "legend", values = cols) + scale_shape_manual(name = "legend", values = c(32, 15, 17)) + scale_fill_manual(name = "legend", values = c("orange", NA, NA)) + ylab("Current Account Transactions (Billion $)") + xlab(NULL) + theme_bw(14) + scale_x_discrete(breaks = seq(1999, 2013, by = 2)) + scale_y_continuous(labels = dollar, limits = c(-1, 4), breaks = seq(-1, 4, by = .5)) + geom_hline(yintercept = 0) + theme(legend.key = element_blank(), legend.background = element_rect(colour = 'black', fill = 'white'), legend.position = "top", legend.title = element_blank()) + guides(col = guide_legend(ncol = 1)) 

adding + guides(fill = guide_legend(override.aes = list(colour = NULL))) removes slashes as well as dark green / dark colors (it retains the orange fill).

enter image description here

+7
r ggplot2
source share
1 answer

To exclude "Current account balance" from the top legend, you can move the group , colour and shape aesthetics from the parent call to ggplot() and to geom_line() and geom_point() respectively. This gives you concrete control over which aesthetics are applied to each of your two datasets that use variable names. enter image description here

 ggplot(data = df1, aes(x = Year, y = value)) + geom_line(aes(group = variable, colour = variable)) + geom_point(aes(shape = variable, colour = variable), size = 3) + geom_bar(data = df2, aes(x = Year, y = value, fill = variable), stat = "identity", position = 'identity', alpha = 0.8, guide = 'none') + ylab("Current Account Transactions (Billion $)") + xlab(NULL) + theme_bw(14) + scale_x_discrete(breaks = seq(1999, 2013, by = 2)) + scale_y_continuous(labels = dollar, limits = c(-1, 4), breaks = seq(-1, 4, by = .5)) + geom_hline(yintercept = 0) + guides(col = guide_legend(ncol = 1)) + theme(legend.key = element_blank(), legend.background = element_rect(colour = 'black', fill = 'white'), legend.position = "top", legend.title = element_blank(), legend.box.just = "left") 

There are some flaws in this answer. To name a couple: 1) There are two separate legends that can be masked if you decide not to embed them (for example, without setting legend.background , as you have). 2) Removing the df2 variable from the upper legend means that it does not consume the first color by default (as before, by coincidence), so now the "Balance ..." and "Export ..." both look pink, because fill legend Recycle the default color scale.

+3
source share

All Articles