Reputation: 51
I have some x and y data that I would like to compare on a ggplot2 scatter plot. I would like to add a unity line (y = x), twofold (y = 2x), half (y = x/2) and smoother lines to help making sense of the data but I cannot find how to add theses lines to the plot's legend. Any idea?
set.seed(123)
x <- runif(20, 1, 10)
y <- 0.8 * x + runif(20, -1, 1)
cat <- factor(c(rep("high", 10), rep("low", 10)))
d <- data.frame(x, y, cat)
ggplot(data=d) +
geom_point(aes(x, y, colour=cat)) +
geom_abline(aes(intercept=0, slope=1), col = "red") +
geom_abline(aes(intercept=0, slope=0.5), col="blue", linetype="dotted") +
geom_abline(aes(intercept=0, slope=2), col="blue", linetype="dashed")+
geom_smooth(aes(x, y))
y vs x scatter plot in ggplot2
I would like the labels 'unity line', 'twofold', 'half', and 'smoother' to appear below the 'high' and 'low' labels in the legend.
Following User3640617's answer, I have tried the following code but the result is still not satisfying because the data points now have a linetype and a smoothing linetype linked to them in the legend.
ggplot(data=d) +
geom_point(aes(x, y, colour=cat)) +
geom_abline(aes(intercept=0, slope=1, colour="y = x")) +
geom_abline(aes(intercept=0, slope=.5, colour="y = x/2")) +
geom_abline(aes(intercept=0, slope=2, colour="y = 2x")) +
geom_smooth(aes(x,y, colour="smooth")) +
scale_color_manual(
values=c("red", "darkgreen", "black", "blue", "red", "blue")) +
scale_linetype_manual(
values=c("blank", "blank", "solid", "dashed", "solid", "dotted")) +
scale_shape_manual(values=c(1, 1, NA, NA, NA, NA))
Also, I do not seem to be able to manually change the tinetypes:
scatter plot with ablines and smoother
I know, I could simply choose other colors and there would be less confusion but it should be possible to have a legend with only points for points and lines for lines instead of having point and lines for both points and lines, or is it not?
ggplot2 seems to be bothered by the addition of color
or linetype
after the aes
. The order of the categories seems to be changed when adding the lines to the legend.
Upvotes: 4
Views: 7480
Reputation: 35242
You can just map a character value to an unused aesthetic to trick ggplot into making a legend for you:
ggplot(data=d) +
geom_point(aes(x, y, colour=cat)) +
geom_abline(aes(intercept=0, slope=1, lty='unity line'), col = "red")
Use + scale_linetype(name = NULL)
or labs(linetype = NULL)
to remove the linetype
legend title.
Upvotes: 9
Reputation: 10152
I guess there is no way around having a second dataset containing your lines.
One way to get a second legend for the lines, is to map the lines by linetypes and hardcode the colors (followed by manually adjusting the colors in the legend).
This could be done like so:
library(ggplot2)
# 1 recreate the data
set.seed(123)
x <- runif(20, 1, 10)
y <- 0.8 * x + runif(20, -1, 1)
cat <- factor(c(rep("high", 10), rep("low", 10)))
d <- data.frame(x, y, cat)
# create the lines-data
d_lines <- data.frame(int = rep(0, 3),
sl = c(1, 0.5, 2),
col = c("red", "blue", "blue"),
lty = c("solid", "dotted", "dashed"))
# extract the linetypes from the data.frame (with names to map the values correclty)
ltys <- as.character(d_lines$lty)
names(ltys) <- as.character(d_lines$lty)
# extract the colors in the order that ggplot will put the names of the lines (dashed, dotted, solid)
cols <- as.character(d_lines$col)
cols <- cols[order(as.character(d_lines$lty))]
# plot the data
ggplot() +
geom_point(data = d, aes(x, y, colour=cat)) +
geom_smooth(data = d, aes(x, y)) +
# add the two different line-colors
geom_abline(data = d_lines[d_lines$col == "red", ],
aes(intercept = int, slope = sl, lty = lty), color = "red") +
geom_abline(data = d_lines[d_lines$col == "blue", ],
aes(intercept = int, slope = sl, lty = lty), color = "blue") +
# change the color of the legend
scale_linetype_manual(name = "Linetype", values = ltys,
guide = guide_legend(override.aes = list(colour = cols)))
#> `geom_smooth()` using method = 'loess'
Upvotes: 3
Reputation: 1576
Not a very neat solution perhaps, but you can create an additional data frame with the information for your unity line as follows:
dfabline <- data.frame(intercept=0, slope=1, group="unity line")
ggplot(data=d) +
geom_point(aes(x, y, colour=cat)) +
geom_abline(data=dfabline, aes(intercept=intercept, slope=slope, colour=group))
You can specify the colour of the line and the points using scale_colour_manual
.
Upvotes: 0