Daniel Valencia C.
Daniel Valencia C.

Reputation: 2279

How to combine fill (columns) and color (points and lines) legends in a single plot made with ggplot2?

In a chart I have columns and points. I'm trying to unify the legend; I've already put the same name on the scales, but they still appear separate. Could someone please help me solve this issue?

library(ggplot2)

X <- factor(c("a", "b"))
Y1 <- c(10, 15)
Y2 <- c(22, 23)

df <- data.frame(X, Y1, Y2)

ggplot(data = df, aes(x = X,
                      group = 1)) +
  geom_col(aes(y = Y1,
               fill = "Y1")) +
  geom_line(aes(y = Y2,
                color = "Y2")) +
  geom_point(aes(y = Y2,
                 color = "Y2")) +
  scale_fill_manual(name = "Legend",
                    values = "blue") +
  scale_color_manual(name = "Legend",
                     values = "red")

enter image description here

Upvotes: 2

Views: 1223

Answers (2)

stefan
stefan

Reputation: 124013

To merge the legends you also have to use the same values in both the fill and color scale. Additionally you have to tweak the legend a bit by removing the fill color for the "Y2" legend key using the override.aes argument of guide_legend:

EDIT Thanks to the comment by @aosmith. To make this approach work for ggplot2 version <=3.3.3 we have to explicitly set the limits of both scales.

library(ggplot2)

X <- factor(c("a", "b"))
Y1 <- c(10, 15)
Y2 <- c(22, 23)

df <- data.frame(X, Y1, Y2)

ggplot(data = df, aes(x = X,
                      group = 1)) +
  geom_col(aes(y = Y1,
               fill = "Y1")) +
  geom_line(aes(y = Y2,
                color = "Y2")) +
  geom_point(aes(y = Y2,
                 color = "Y2")) +
  scale_fill_manual(name = "Legend",
                    values = c(Y1 = "blue", Y2 = "red"), limits = c("Y1", "Y2")) +
  scale_color_manual(name = "Legend",
                     values = c(Y1 = "blue", Y2 = "red"), limits = c("Y1", "Y2")) +
  guides(color = guide_legend(override.aes = list(fill = c("blue", NA))))

Upvotes: 2

aosmith
aosmith

Reputation: 36076

Another option would to make only one of the legends and then manually change that legend to have it represent all the layers.

In this case, I make a fill legend but set color to constants outside of aes(). I force the inclusion of the line/point layers by adding show.legend = TRUE.

Then I add the extra value to fill, setting both values and limits in scale_fill_manual(). Note I set the Y2 to have a transparent fill.

Finally I make manual changes to the legend to keep the lines and points only for the second legend key with override.aes in guide_legend().

ggplot(data = df, aes(x = X,
                      group = 1)) +
    geom_col(aes(y = Y1,
                 fill = "Y1")) +
    geom_line(aes(y = Y2), color = "red", show.legend = TRUE) +
    geom_point(aes(y = Y2), color = "red", show.legend = TRUE) +
    scale_fill_manual(name = "Legend",
                      values = c(Y1 = "blue", Y2 = "transparent"),
                      limits = c("Y1", "Y2")) +
    guides(fill = guide_legend(override.aes = list(shape = c(NA, 19),
                                                   linetype = c(0, 1))))

Created on 2021-06-29 by the reprex package (v2.0.0)

Upvotes: 2

Related Questions