Suppose I have the following plot in ggplot:
It was generated using the code below:
x <- seq(0, 10, by = 0.2)
y1 <- sin(x)
y2 <- cos(x)
y3 <- cos(x + pi / 4)
y4 <- sin(x + pi / 4)
df1 <- data.frame(x, y = y1, Type = as.factor("sin"), Method = as.factor("method1"))
df2 <- data.frame(x, y = y2, Type = as.factor("cos"), Method = as.factor("method1"))
df3 <- data.frame(x, y = y3, Type = as.factor("cos"), Method = as.factor("method2"))
df4 <- data.frame(x, y = y4, Type = as.factor("sin"), Method = as.factor("method2"))
df.merged <- rbind(df1, df2, df3, df4)
ggplot(df.merged, aes(x, y, colour = interaction(Type, Method), linetype = Method, shape = Type)) + geom_line() + geom_point()
I would like to have only one legend that correctly displays the shapes, the colors and the line types (the interaction(Type, Method) legends is the closest to what I would like, but it does not have the correct shapes/line types).
I know that if I use scale_xxx_manual and I specify the same labels for all legends they will be merged, but I don't want to have to set the labels manually: if there are new Methods or Types, I don't want to have to modify my code: a want something generic.
Edit
As pointed in answers below, there are several ways to get the job done in this particular case. All proposed solutions require to manually set the legend line types and shapes, either by using scale_xxx_manual function
s or with guides
function.
However, the proposed solutions still don't work in the general case: for instance, if I add a new data frame to the data set with a new "method3" Method, it does not work anymore, we have to manually add the new legend shapes and line types:
y5 <- sin(x - pi / 4)
df5 <- data.frame(x, y = y5, Type = as.factor("sin"), Method = as.factor("method3"))
df.merged <- rbind(df1, df2, df3, df4, df5)
override.shape <- c(16, 17, 16, 17, 16)
override.linetype <- c(1, 1, 3, 3, 4)
g <- ggplot(df.merged, aes(x, y, colour = interaction(Type, Method), linetype = Method, shape = Type)) + geom_line() + geom_point()
g <- g + guides(colour = guide_legend(override.aes = list(shape = override.shape, linetype = override.linetype)))
g <- g + scale_shape(guide = FALSE)
g <- g + scale_linetype(guide = FALSE)
print(g)
This gives:
Now the question is: how to automatically generate the override.shape
and override.linetype
vectors?
Note that the vector size is 5 because we have 5 curves, while the interaction(Type, Method)
factor has size 6 (I don't have data for the cos/method3 combination)