In Ggplot2, How to Add Additional Legend

In ggplot2, how can I add additional legend?

I'm not 100% sure this is what you want, but here's how I'd approach the problem as I understand it. If we map some unused geom with any data from xx.sub1.df, but make it invisible on the plot, we can still get a legend for that geom. Here I've used geom_point, but you could make it others.

p <- ggplot(xx.sub2.df) + 
aes(long, lat, fill = (SID79/BIR79)*1000, group = group) +
geom_polygon() + geom_path(color="grey80") +
coord_equal() +
scale_fill_gradientn(colours = brewer.pal(7, "YlOrBr")) +
geom_polygon(data = xx.sub1.df, fill = "grey50") +
geom_path(data = xx.sub1.df, color="grey80") +
labs(fill = "Mapped value", title = "Title")

#Now we add geom_point() setting shape as NA, but the colour as "grey50", so the
#legend will be displaying the right colour

p2 <- p + geom_point(data = xx.sub1.df, aes(size="xx.sub1", shape = NA), colour = "grey50")

Sample Image

Now we just need to alter the size and shape of the point on the legend, and change the name of the legend (thanks to @DizisElferts who demonstrated this earlier).

p2 + guides(size=guide_legend("Source", override.aes=list(shape=15, size = 10)))

Sample Image

Of course you can change the way the labels work or whatever to highlight what you want to show.

If this isn't what you're after, let me know!

Creating a second legend with ggplot?

Move color inside aes, add scale_color_identity to get the right colors and to set the labels for the legend:

library(ggplot2)

ggplot() +
geom_rect(aes(xmin = 2006.90, xmax = 2009.15, ymin = -Inf, ymax = 10, fill = "blue"), alpha = 0.4) +
geom_rect(aes(xmin = 2019.80, xmax = Inf, ymin = -Inf, ymax = 10, fill = "orange"), alpha = 0.3) +
geom_rect(aes(xmin = 2009.90, xmax = 2013.15, ymin = -Inf, ymax = 10, fill = "lightgreen"), alpha = 0.4) +
geom_line(aes(x = x, y = y1, colour = "black")) +
geom_line(aes(x = x, y = y2, colour = "red")) +
geom_point(aes(x = x, y = y1, col = "black")) +
geom_point(aes(x = x, y = y2, col = "red")) +
scale_color_identity(name = NULL, labels = c(black = "Label 1", red = "Label 2"), guide = "legend") +
theme_classic() +
scale_fill_manual(name = "", values = c("lightblue", "lightgreen", "orange"), labels = c(" Rezession", "krise", "Corona 2020-")) +
theme(legend.position = "bottom") +
theme(axis.text.x = element_text(angle = 90)) +
geom_hline(yintercept = 0, color = "black", size = 1)

Sample Image

Create additional independent legends in ggplot2

A trick I learned from @tjebo is that you can use the ggnewscale package to spawn additional legends. At what point in plot construction you call the new scale is important, so you first want to make a geom/stat layer and add the desired scale. Once these are declared, you can use new_scale_colour() and all subsequent geom/stat layers will use a new colour scale.

library(ggplot2)
#> Warning: package 'ggplot2' was built under R version 4.0.5
library(ggnewscale)
#> Warning: package 'ggnewscale' was built under R version 4.0.3

sims = replicate(1000, sample(c(0,0,0,0,1,1,1,2,2,2), size=3, replace=FALSE))
df = data.frame(x=colSums(sims == 0),
y=colSums(sims == 1))
df$count <- 1
total_counts = aggregate(count ~ ., df, FUN = sum)

min_count = min(total_counts$count)
max_count = max(total_counts$count)

df2 = data.frame(x=c(0, 1, 2, 3),
y=c(1.5253165, 1.0291262, 0.4529617, 0))

df3 = data.frame(x=c(0, 1, 2, 3),
y=c(1.5, 1, 0.5, 0))

ggplot(df, aes(x, y)) +
geom_count(aes(colour = after_stat(n), size = after_stat(n)),
alpha = 0.5) +
scale_colour_gradient(
limits = c(min_count, max_count),
breaks = round(seq(min_count, max_count, length.out = 5)),
labels = round(seq(min_count, max_count, length.out = 5)),
guide = "legend"
) +
new_scale_colour() +
geom_point(aes(colour = "Simulated means"),
data = df2, alpha = 0.4) +
geom_point(aes(colour = "Theoretical means"),
data = df3, alpha = 0.4) +
scale_colour_discrete(
name = ""
) +
scale_size_continuous(range = c(3, 7.5), guide = "none")

Sample Image

Created on 2021-04-22 by the reprex package (v1.0.0)

(P.S. sorry for reformatting your code, it just read more easily for myself this way)

How to add a second group legend in ggplot (R)?

Hard to tell what you are trying to achieve, maybe this approach could be useful:

library(dplyr)
library(ggplot2)

ggplot(xc, aes(x = gender, y = prop, fill = group2)) +
geom_col(position = position_dodge2(preserve = "single", padding = 0.01), alpha = 0.85) +
scale_fill_manual(values = c("#466760", "#845574")) +
facet_wrap(~group, nrow = 1)+
theme_bw() +
theme(panel.border = element_blank()) +
ggtitle("") +
xlab("") +
ylab("Percentage %")

Sample Image

Created on 2022-02-07 by the reprex package (v2.0.1)

Adding an additional legend manually for different data.frames used in the same ggplot

It looks like you need a second color scale to do this. You can use the ggnewscale package:

library(ggnewscale)

dat %>%
ggplot() +
aes(x, y, color = groups, shape = groups) +
geom_point(size = 2) +
theme_classic() +
stat_ellipse(level = .6) +
geom_point(data = dat2,
mapping = aes(x = mean_x, y = mean_y),
size = 4, show.legend = FALSE, shape = 21, fill = "black") +
scale_color_discrete() +
new_scale_color() +
geom_smooth(data = dat2,
mapping = aes(x = mean_x, y = mean_y, group = 1, color = "black"),
method = "lm", se = FALSE, formula = 'y ~ x') +
geom_smooth(aes(group = 1, color = "red"),
method = "lm", se = FALSE, formula = 'y ~ x') +
scale_color_identity(name = "", labels = c("Between", "Within"),
guide = guide_legend())

Sample Image

How to modify and add an extra legend in a ggplot2 figure

See if the following works for you? The main idea is to convert the data frame from wide to long format for the geom_point layer, and map correlation as a shape aesthetic:

example.df %>%

ggplot(aes(x = phenotype, color = predictor, group = predictor)) +
geom_linerange(aes(ymin = corr1, ymax = corr3),
position = position_dodge(width = 0.5)) +
geom_point(data = . %>% tidyr::gather(corr, value, -phenotype, -predictor),
aes(y = value, shape = corr),
size = 3,
position = position_dodge(width = 0.5)) +
scale_color_manual(values = c("#4682B4", "#698B69", "#FF6347")) +
scale_shape_manual(values = c(4, 18, 16),
labels = paste("correlation", 1:3)) +
labs(x = NULL, y = NULL, color = "", shape = "") +
theme_minimal()

plot

Note: The colour legend is based on both geom_linerange and geom_point, hence the legend keys include both a line and a point shape. While it's possible to get rid of the second one, it does take some more convoluted code, and I don't think the plot would be much improved as a result...

How to add user defined legend to ggplot in R?

To clarify different colors in your legend, you can modify your Leg vector to assign colors to specific labels (renamed to CType). Then, you can provide the label directly in your geom_line and geom_point statements which will be the same as what shows up in your legend. As mentioned in the comment, I moved color to inside the aesthetic for the legend. To show the legend, you can use scale_color_manual.

Edit: To get the different linetypes - made a similar vector LType to indicate which linetype (dashed, solid, etc.). Instead of using geom_point for precipitation, used a dotted linetype - otherwise, it would be difficult combining color and linetype legends into one legend (unless you specify linetype for geom_point which would raise a warning but then ignore). Additional lines were added for the ribbon bounds so it would show up in legend.

library(tidyverse)
library(zoo)

set.seed(1)
N=184
A = runif(N, 50, 100)
G = seq(1:N)
FakeData = data.frame(A, B = A + 20, C = A + 40, D = A - 20, E = A + 10, F = A - 15, G)

lab=c("May", "Jun", "July", "Aug", "Sep", "Oct", "Nov")

CType = c("Upper and lower Quartile" = "grey75", "Maximum" = "red", "Minimum" = "black", "Median" = "darkblue", "Precipitation" = "blue")
LType = c("Upper and lower Quartile" = "solid", "Maximum" = "dashed", "Minimum" = "dashed", "Median" = "solid", "Precipitation" = "dotted")

ggplot(FakeData, aes(x = G))+
geom_ribbon(aes(ymin = A, ymax = B), fill= "grey75")+
geom_line(aes(y = A, colour = "Upper and lower Quartile", linetype = "Upper and lower Quartile"), size = 1.3)+
geom_line(aes(y = B, colour = "Upper and lower Quartile", linetype = "Upper and lower Quartile"), size = 1.3)+
geom_line(aes(y = C, colour = "Maximum", linetype = "Maximum"), size = 1.3)+
geom_line(aes(y = D, colour = "Minimum", linetype = "Minimum"), size = 1.3)+
geom_line(aes(y = E, colour = "Median", linetype = "Median"), size = 1.3)+
geom_line(aes(y = F, colour = "Precipitation", linetype = "Precipitation"), size = 1.3)+
scale_x_continuous(breaks = c(0,31,61,92,123,153,184), labels = lab)+
xlab("Month")+
ylab("Daily Cumulative Precipitation (mm)")+
theme_bw()+
scale_color_manual(name = "legend", values = CType)+
scale_linetype_manual(name = "legend", values = LType)+
theme(legend.position = c(.2, .8), legend.title = element_blank(), legend.key.width = unit(2, "cm"))

plot with custom legend

How add legend in ggplot

Here's an example on some data that everyone can run, since it uses built-in datasets that come with R. Here, I made color and size be dynamic aesthetics with the name of the series, and then mapped those series values to different aesthetic values using scale_*_manual, where * are the aesthetics you want to vary by series. This generates an automatic legend. By giving each aesthetic the same name ("source" here), ggplot2 knows to combine them into one legend.

(By the way, it's unnecessary and can lead to errors to refer to variables in ggplot2 aesthetics using the form retailer$MY; each geom will assume the variable is within the data frame referred to with data =, so you can just use MY in that case.)

ggplot() +
geom_point(data = mtcars,
aes(x = wt, y = mpg, color = "mtcars", size = "mtcars")) +
geom_point(data = attitude,
aes(x = rating/20, y = complaints/3, color = "attitude", size = "attitude")) +
scale_color_manual(values = c("mtcars" = "slateblue", "attitude" = "red"), name = "source") +
scale_size_manual(values = c("mtcars" = 3, "attitude" = 4.5), name = "source")

Sample Image

Adding a second legend for vertical lines in ggplot

A good way to do this could be to use mapping= to create the second legend in the same plot for you. The key is to use a different aesthetic for the vertical lines vs. your other lines and points.

First, the example data and plot:

library(ggplot2)
library(dplyr)
library(tidyr)

set.seed(8675309)
df <- data.frame(x=rep(1:25, 4), y=rnorm(100, 10, 2), lineColor=rep(paste0("col",1:4), 25))

base_plot <-
df %>%
ggplot(aes(x=x, y=y)) +
geom_line(aes(color=lineColor)) +
scale_color_brewer(palette="Greens")
base_plot

Sample Image

Now to add the vertical lines as OP has done in their question:

base_plot +
geom_vline(xintercept = c(1,9,11), linetype="dotted",
color = "red", size=1) +
geom_vline(xintercept = c(5,14,17), linetype="dotted",
color = "blue", size=1)

Sample Image

To add the legend, we will need to add another aesthetic in mapping=. When you use aes(), ggplot2 expects that mapping to contain the same number of observations as the dataset specified in data=. In this case, df has 100 observations, but we only need 6 lines. The simplest way around this would be to create a separate small dataset that's used for the vertical lines. This dataframe only needs to contain two columns: one for xintercept and the other that can be mapped to the linetype:

verticals <- data.frame(
intercepts=c(1,9,11,5,14,17),
Events=rep(c("Closure", "Opening"), each=3)
)

You can then use that in code with one geom_vline() call added to our base plot:

second_plot <- base_plot +
geom_vline(
data=verticals,
mapping=aes(xintercept=intercepts, linetype=Events),
size=0.8, color='blue',
key_glyph="path" # this makes the legend key horizontal lines, not vertical
)
second_plot

Sample Image

While this answer does not use color to differentiate the vertical lines, it's the most in line with the Grammar of Graphics principles which ggplot2 is built upon. Color is already used to indicate the differences in your data otherwise, so you would want to separate out the vertical lines using a different aesthetic. I used some of these GG principles putting together this answer - sorry, the color palette is crap though lol. In this case, I used a sequential color scale for the lines of data, and a different color to separate out the vertical lines. I'm showing the vertical line size differently than the lines from df to differentiate more and use the linetype as the discriminatory aesthetic among the vertical lines.

You can use this general idea and apply the aesthetics as you see best for your own data.



Related Topics



Leave a reply



Submit