Ggplot2: Different Legend Symbols for Points and Lines

ggplot2: Different legend symbols for points and lines

override.aes is definitely a good start for customizing the legend. In your case you may remove unwanted shape in the legend by setting them to NA, and set unwanted linetype to blank:

ggplot(data = NDVI2, aes(x = LAI2, y = NDVI, colour = Legend)) + 
geom_point(size = 3) +
geom_smooth(aes(group = 1, colour = "Trendline"),
method = "loess", se = FALSE, linetype = "dashed") +
geom_smooth(aes(group = 1, colour = "Regression (log)"),
method = "lm", formula = y ~ log(x), se = FALSE, linetype = "solid") +
scale_colour_manual(values = c("purple", "green", "blue", "yellow", "magenta","orange", "cyan", "red", "black"),
guide = guide_legend(override.aes = list(
linetype = c(rep("blank", 7), "solid", "dashed"),
shape = c(rep(16, 7), NA, NA))))

Sample Image

ggplot2: Creating a legend which includes multiple symbols, line types, and colors

If you combine r1 and r2 into r3 for plotting and add shape + linetype to aes , it will work

library(ggplot2)

r1$variable <- factor(r1$variable)
r2$variable <- factor(r2$variable)
r3 <- rbind(r1, r2)

ggplot(data = r3, aes(x=ReturnPeriod, y=value, color=variable, shape=variable)) +
geom_point()+
geom_line(aes(linetype=variable))+
ylab("Max Yearly Flow (cfs)") +
xlab("Return Interval (years)") +
scale_shape_manual(name = "Legend",
labels = c("Obs 15-min", "Obs 24-hour", "15-min P3", "24-hr P3"),
values = c("Peak_cfs"=16, "Daily_cfs"=17, "PeakEst"=NA,
"DailyEst" = NA)) +
scale_colour_manual(name = "Legend",
labels = c("Obs 15-min", "Obs 24-hour", "15-min P3", "24-hr P3"),
values = c("Peak_cfs"="grey", "Daily_cfs"="black", "PeakEst"="dark grey",
"DailyEst" = "black")) +
scale_linetype_manual(name = "Legend",
labels = c("Obs 15-min", "Obs 24-hour", "15-min P3", "24-hr P3"),
values = c("Peak_cfs"="blank", "Daily_cfs"="blank", "PeakEst"="solid",
"DailyEst" = "dashed"))+
guides(colour = guide_legend(override.aes = list(
linetype = c("blank", "blank", "solid", "dashed"),
shape = c(16,17,NA,NA),
color = c("grey","black", "dark grey", "black")))) +
theme(legend.position=c(0.8, 0.6),
legend.background = element_rect(fill="white"),
legend.key = element_blank(),
legend.box = "horizontal")
#> Warning: Removed 12 rows containing missing values (geom_point).

Sample Image

Changing the style of symbols in the legend so they are identical to those shown on the plot

If I understood your question correctly, you could just modify the the answer to your previous question by @dc37 Moving error bars in a line graph with three factors. I only added two lines for linetype.

library(Rmisc)
library(ggplot2)
tglf3 <- summarySE(df, measurevar="form",
groupvars=c("P","cultivar","Waterlogging"),na.rm=TRUE)
pd <- position_dodge(0.5)
ggplot(tglf3,aes(x=P, y=form,
shape = interaction(cultivar, Waterlogging),
color = interaction(cultivar, Waterlogging),
linetype = interaction(cultivar, Waterlogging)))+
geom_errorbar(aes(ymin=form-se, ymax=form+se), width=.6,position=pd) +
geom_point(size=3.5,position=pd) +
geom_line(position=pd) +
theme_bw() +
theme(legend.position = 'top') +
guides(color=guide_legend(ncol=2, title = "Legend"),
shape = guide_legend(ncol =2, title = "Legend"),
linetype = guide_legend(ncol =2, title = "Legend"))

Sample Image

Edit

Initially, I thought it cannot be done in ggplot2, but I have managed to trick ggplot2 to get what you want(?). I have learned some new tricks through this.

p <-ggplot(tglf3, aes(x=P, y=form, 
color = interaction(cultivar, Waterlogging),
shape = interaction(cultivar, Waterlogging),
linetype = interaction(cultivar, Waterlogging)))+
geom_errorbar(aes(ymin=form-se, ymax=form+se), width=.6,position=pd) +
geom_point(size=3.5,position=pd) +
geom_line(position=pd) +
theme_bw() +
theme(legend.position = 'top') +
guides(linetype = guide_legend(ncol=2, title = "Riverina \nYarloop"),
shape = guide_legend(ncol =2, title = "Riverina \nYarloop"),
color = guide_legend(ncol =2, title = "Riverina \nYarloop"))
df <- droplevels(df)
brks <- levels(interaction(df$cultivar, df$Waterlogging))
lbs <- c("Non-waterlogged", "Non-waterlogged", "Waterlogged", "Waterlogged")
p + scale_shape_discrete(breaks=brks, labels=lbs) +
scale_color_discrete(breaks=brks, labels=lbs) +
scale_linetype_discrete(breaks=brks, labels=lbs)

Sample Image

Data

> dput(df)
structure(list(pot = c(41L, 42L, 43L, 44L, 61L, 62L, 63L, 64L,
45L, 46L, 47L, 48L, 65L, 66L, 67L, 68L, 49L, 50L, 51L, 52L, 69L,
70L, 71L, 72L, 53L, 54L, 55L, 56L, 73L, 74L, 75L, 76L, 57L, 58L,
59L, 60L, 77L, 78L, 79L, 80L, 81L, 82L, 83L, 84L, 101L, 102L,
103L, 104L, 85L, 86L, 87L, 88L, 105L, 106L, 107L, 108L, 89L,
90L, 91L, 92L, 109L, 110L, 111L, 112L, 93L, 94L, 95L, 96L, 113L,
114L, 115L, 116L, 97L, 98L, 99L, 100L, 117L, 118L, 119L, 120L
), rep = c(1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L, 1L,
2L, 3L, 4L, 1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L, 1L,
2L, 3L, 4L, 1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L, 1L,
2L, 3L, 4L, 1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L, 1L,
2L, 3L, 4L, 1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L, 1L,
2L, 3L, 4L), cultivar = structure(c(4L, 4L, 4L, 4L, 4L, 4L, 4L,
4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L,
4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L,
4L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L,
2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L,
2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L), .Label = c("Dinninup", "Riverina",
"Seaton Park", "Yarloop"), class = "factor"), Waterlogging = structure(c(2L,
2L, 2L, 2L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 1L, 1L, 1L, 1L, 2L,
2L, 2L, 2L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 1L, 1L, 1L, 1L, 2L,
2L, 2L, 2L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 1L, 1L, 1L, 1L, 2L,
2L, 2L, 2L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 1L, 1L, 1L, 1L, 2L,
2L, 2L, 2L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 1L, 1L, 1L, 1L), .Label = c("Non-waterlogged",
"Waterlogged"), class = "factor"), P = c(12.1, 12.1, 12.1, 12.1,
12.1, 12.1, 12.1, 12.1, 15.17, 15.17, 15.17, 15.17, 15.17, 15.17,
15.17, 15.17, 18.24, 18.24, 18.24, 18.24, 18.24, 18.24, 18.24,
18.24, 24.39, 24.39, 24.39, 24.39, 24.39, 24.39, 24.39, 24.39,
48.35, 48.35, 48.35, 48.35, 48.35, 48.35, 48.35, 48.35, 12.1,
12.1, 12.1, 12.1, 12.1, 12.1, 12.1, 12.1, 15.17, 15.17, 15.17,
15.17, 15.17, 15.17, 15.17, 15.17, 18.24, 18.24, 18.24, 18.24,
18.24, 18.24, 18.24, 18.24, 24.39, 24.39, 24.39, 24.39, 24.39,
24.39, 24.39, 24.39, 48.35, 48.35, 48.35, 48.35, 48.35, 48.35,
48.35, 48.35), form = c(2.81, 2.64, 2.59, 3.28, 3.18, 2.57, 2.9,
3, 2.38, 2.72, 2.58, 2.73, 3.06, 3.01, 3.01, 2.77, 2.95, 2.36,
2.91, 2.38, 3.33, 3.19, 3.17, 3.16, 3.16, 3.2, 2.58, 3.71, 3.11,
2.7, 2.92, 1.93, 2.95, 2.57, 2.68, 2.48, 3.34, 2.75, 2.52, 1.88,
1.19, 0.57, 0.64, 0.66, 1.13, 1.28, 0.85, 0.96, 1.34, 2.14, 0.63,
1.27, 1.13, 0.64, 1.21, 1.95, 1.11, 0.91, 0.75, 0.63, 1.06, 1.07,
1.05, 0.8, 1.41, 1.13, 0.75, 0.89, 1.98, 1.27, 1.01, 1, 1.16,
0.64, 0.64, 1.02, 1.03, 1.13, 0.79, 0.6)), row.names = 41:120, class = "data.frame")

ggplot2 with points and lines with different legends

With the comment from @kitman0804 you can also add a linetype = factor(v4) to the aes()

p <- ggplot()+
geom_point(aes(v3,v2,color=factor(v1)),myData)+
scale_colour_manual(values = c(1,2,3,4,5,6),name="Property A")+
scale_linetype_discrete(name = "Property B") +
xlab("X Values")+
ylab("Y Values")+
theme(legend.position="bottom")
p + geom_line(aes(v3, v2, group=factor(v4), linetype = factor(v4)), myData)

Sample Image

UPDATE: Add annotations instead different line types

At first, you create a data.frame which contains all min (or max) values using this function. You can also adjust the x and y position of the values with the adjustx and adjusty parameters.

xyForAnnotation <- function(data, xColumn, yColumn, groupColumn, 
min = TRUE, max = FALSE,
adjustx = 0.05, adjusty = 100) {
xs <- c()
ys <- c()
is <- c()
for (i in unique(data[ , c(as.character(groupColumn))])){
tmp <- data[data[, c(groupColumn)] == i,]
if (min){
wm <- which.min(tmp[, c(xColumn)])
tmpx <- tmp[wm, c(xColumn)]
tmpy <- tmp[wm, c(yColumn)]
}
if (max){
wm <- which.max(tmp[, c(xColumn)])
tmpx <- data[wm, c(yColumn)]
tmpy <- data[wm, c(yColumn)]
}

xs <- c(xs, tmpx)
ys <- c(ys, tmpy)
is <- c(is, i)
}
df <- data.frame(lab = is, x = xs, y = ys)
df$x <- df$x + adjustx
df$y <- df$y + adjusty
df
}

df <- xyForAnnotation(myData, "v3", "v2", "v4")

p <- ggplot()+
geom_point(aes(v3,v2,color=factor(v1)),myData)+
scale_colour_manual(values = c(1,2,3,4,5,6, 7, 8, 9),name="Property A")+
scale_linetype_discrete(guide = F) +
xlab("X Values")+
ylab("Y Values")+
theme(legend.position="bottom") +
geom_line(aes(v3, v2, group=factor(v4)), myData)
p + annotate("text", label = as.character(df$lab), x = df$x, y = df$y)

The plot then looks like this:

Sample Image

As mentioned above, you can adjust the position of the annotations.

Is there a way to change the symbol shape in a ggplot2 legend?

You can simply add the show.legend = F argument inside geom_label_repel. This will avoid creating a legend for geom_label_repel and leave intact the other two legends (geom_point and geom_line).

geom_label_repel(
label = mtcars$cyl,
nudge_x = .3,
nudge_y = 0,
show.legend = F)

How to add line to point shapes in ggplot2 legend

I would suggest this approach:

#Plot
ggplot(data = dat, mapping = aes(x = time_period, y = y,group = category,shape = category)) +
geom_line(color='gray',show.legend = T) +
geom_point(size = 2) +
theme_bw()

Output:

Sample Image

ggplot multiple legend with points and lines

You need to map a colour in aes to have it appear in the legend:

fg <- ggplot(datpoint, aes(conc, resp,  color = factor(mortality))) + 
geom_point(size = 2.5) +
geom_line(aes(X,Y, color = "fit"), datline ,
linetype = fitlty, size = fitlwd) +
scale_colour_hue(legend.title, breaks = c("1","19", "fit"),
labels = c("dead", "alive", "fit")) +
labs(x = "conc", y = "resp")

fg

Sample Image

R 4.0.0 : I am trying to change symbols of legend for a plot in ggplot2, at the moment I have overlapping symbols

Try this:

library(ggplot2)

ggplot(NULL, aes(x=0, y=0)) + geom_point(alpha = 0) +
coord_cartesian(xlim = c(-2.5,2.5),ylim = c(-2.5,2.5)) +
geom_segment(aes(x=0, xend=1, y=0, yend=-2, linetype ="Vector a"),
colour = "blue",
arrow = arrow(length = unit(0.5, "cm"))) +
geom_abline(aes(intercept=1, slope=1/2, color = "Line 1")) +
scale_y_continuous(breaks=c(-2:2)) +
scale_x_continuous(breaks=c(-2:2)) +
scale_color_manual(values = c("green", "blue")) +
labs(title = "plot (a) line",
x = "X Axis",
y = "Y Axis",
linetype = NULL,
colour = "colour")

Commentary

You cannot easily use one aesthetic for two different geom levels in ggplot; so you need to fiddle with the build up of your data and call to ggplot to use different aesthetics to create the legend you want. I can't find an explicit statement to this effect. In Hadley Wickham (2015) ggplot2 Elegant Graphics for Data Analysis it states:

“A legend may need to draw symbols from multiple layers. For example,
if you’ve mapped colour to both points and lines, the keys will show
both points and lines.”

and

"ggplot2 tries to use the fewest number of legends to accurately convey
the aesthetics used in the plot. It does this by combining legends
where the same variable is mapped to different aesthetics."

Which goes some way to explaining the issues you were having with your plot.

Created on 2020-05-24 by the reprex package (v0.3.0)

How Insert an expression in legend in ggplot2?:: correct color + multiple lines and point

Ironically, setting this up with conventional ploting is rather simple:

Given all the data above:


linetypes4 <- c( Xb_exp=NA, Xb_dw="solid", Xb_f="dotted", Xb_s="longdash" )

plot(
NA, type="n", xlim=c(0,30), ylim=c(0,0.8),
xlab = "Crank position (ºCA)", ylab = bquote('Burn fraction ('~X[b]~')'),
panel.first = grid()
)
with( dat, {
points( x=CA, y=Xb_exp, pch=19, col=color4["Xb_exp"], size=3 )
for( n in c("Xb_dw", "Xb_f", "Xb_s")) {
lines( x=CA, y=get(n), lty=linetypes[n], col=color4[n], lwd=2 )
}
})
legend(
x = "right",
legend = labels,
col = color4,
lty = linetypes4,
pch = c(19,NA,NA,NA),
box.lwd = 0,
inset = .02
)

with proper labels



Related Topics



Leave a reply



Submit