How to merge color, line style and shape legends in ggplot
Here is the solution in the general case:
# Create the data frames
x <- seq(0, 10, by = 0.2)
y1 <- sin(x)
y2 <- cos(x)
y3 <- cos(x + pi / 4)
y4 <- sin(x + pi / 4)
y5 <- 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"))
df5 <- data.frame(x, y = y5, Type = as.factor("sin"), Method = as.factor("method3"))
# Merge the data frames
df.merged <- rbind(df1, df2, df3, df4, df5)
# Create the interaction
type.method.interaction <- interaction(df.merged$Type, df.merged$Method)
# Compute the number of types and methods
nb.types <- nlevels(df.merged$Type)
nb.methods <- nlevels(df.merged$Method)
# Set the legend title
legend.title <- "My title"
# Initialize the plot
g <- ggplot(df.merged, aes(x,
y,
colour = type.method.interaction,
linetype = type.method.interaction,
shape = type.method.interaction)) + geom_line() + geom_point()
# Here is the magic
g <- g + scale_color_discrete(legend.title)
g <- g + scale_linetype_manual(legend.title,
values = rep(1:nb.types, nb.methods))
g <- g + scale_shape_manual(legend.title,
values = 15 + rep(1:nb.methods, each = nb.types))
# Display the plot
print(g)
The result is the following:
- Sinus curves are drawn as solid lines and cosinus curves as dashed lines.
- "method1" data use filled circles for the shape.
- "method2" data use filled triangle for the shape.
- "method3" data use filled diamonds for the shape.
- The legend matches the curve
To summarize, the tricks are :
- Use the Type/Method
interaction
for all data representations (colour, shape,
linetype, etc.) - Then manually set both the curve styles and the legends styles with
scale_xxx_manual
. scale_xxx_manual
allows you to provide a values vector that is longer than the actual number of curves, so it's easy to compute the style vector values from the sizes of the Type and Method factors
merging ggplot legends with linetype, shape and color with different aes
Since you've got only 4 colours but 7 shapes, and you want to merge these in the same legend, use the same aesthetic (variable
) and repeat the first four colour values in the manual override. For the linetypes, you probably don't need them in the legend as you have the shapes (and colour) to distinguish the 7 different models.
ggplot(mock.df, aes(x=vec.dat, y=value, shape=variable, color=variable, linetype=variable)) +
geom_line()+
scale_linetype_manual(values = c(rep("dotted",4),"longdash","solid","solid"))+
geom_point(size=3) +
scale_color_manual(values=c(rep("#999999",4), "#E69F00", "#56B4E9","#008f39"))+
scale_shape_manual(values=c(15,16,17,18,19,3,8))
Combining linetype and color in ggplot2 legend
Here is one approach for you. I created a sample data given your data above was not enough to reproduce your graphic. I'd like to give credit to the SO users who posted answers in this question. The key trick in this post was to assign identical groups to shape and line type. Similarly, I needed to do the same for color and linetype in your case. In addition to that there was one more thing do to. I manually assigned specific colors and line types. Here, there are four levels (i.e., treatment1.AC, treatment1.AE, treatment2.EC, treatment2.EF) in the end. But I used interaction()
and created eight levels. Hence, I needed to specify eight colors and line types. When I assigned a name to the legend, I realized that I need to have an identical name in both scale_color_manual()
and scale_linetype_manual()
.
library(ggplot2)
set.seed(111)
mydf <- data.frame(year = rep(1999:2010, time = 4),
treatment.type = rep(c("AC", "AF", "EC", "EF"), each = 12),
treatment = rep(c("treatment1", "treatment2"), each = 24),
mean = c(runif(min = 0.3, max = 0.55, 12),
rep(NA, 5), runif(min = 0.3, max = 0.55, 7),
runif(min = 0.3, max = 0.55, 12),
rep(NA, 5), runif(min = 0.3, max = 0.55, 7)),
se = c(runif(min = 0.01, max = 0.03, 12),
rep(NA, 5), runif(min = 0.01, max = 0.03, 7),
runif(min = 0.01, max = 0.03, 12),
rep(NA, 5), runif(min = 0.01, max = 0.03, 7)),
stringsAsFactors = FALSE)
ggplot(data = mydf, aes(x = year, y = mean,
color = interaction(treatment, treatment.type),
linetype = interaction(treatment, treatment.type))) +
geom_point(show.legend = FALSE) +
geom_line() +
geom_errorbar(aes(ymin = mean-se, ymax = mean+se),width = 0.1, size = 0.5) +
scale_color_manual(name = "Treatment conditions", values = rep(c("blue", "blue", "red", "red"), times = 2)) +
scale_linetype_manual(name = "Treatment conditions", values = rep(c(1,2), times = 4))
How to merge legends in ggplot2? (keep shape, color and label)
Thanks to Ronak Shah, I found this: the R cook book
If you use both colour and shape, they both need to be given scale
specifications. Otherwise there will be two two separate legends.
Which gave me this:
ggplot(datapoidsmono, aes(x = time, y = weight)) +
stat_summary(aes(color = group), fun.data="mean_sdl", fun.args = list(mult=1), geom="errorbar", position = "identity", size=0.5, width=0.2) +
stat_summary(fun.y = "mean", geom = "point", size=3, aes(shape=group,color=group)) +
scale_x_discrete(name = "Days after injection") +
scale_y_continuous(name = "Weight (g)", limits=c(0, 4000), breaks = seq(0, 4000,500)) +
theme(axis.line.x = element_line(size = 0.5, color = "black"),axis.text.x = element_text(color="black", size = 12),axis.line.y = element_line(size = 0.5, color = "black"),axis.text.y = element_text(color="black", size = 12),axis.title = element_text(size =15, face="bold"),plot.title = element_text(size =20, face = "bold"),panel.grid.major = element_line(color = "#F1F1F1"),panel.grid.minor = element_blank(), panel.background = element_blank()) +
scale_color_manual(values=c("green", "blue", "red"), name="Treatment", labels=c("A","B","C")) +
scale_shape_manual(values=c(15,16,17), name ="Treatment", labels=c("A", "B", "C")) +
ggtitle("Weight variation over time") + theme(plot.title = element_text(hjust = 0.5)) +
theme(legend.position = "right") + #on peut choisir l'endroit précis en remplaçan par c(0.15,0.80)) ou supprimer la légende en remplaçant par none
theme(legend.background = element_rect(size=0.5, linetype="solid", color ="black", fill="white"))
How to merge color and fill aes on same legend in ggplot
This can be fixed by setting the linetype for the columns as follows:
ggplot(data = economics_long,aes(date,value01,col = variable,fill = variable))+
geom_col(data = subset(economics_long,variable!="pce"), linetype = 0)+
geom_line(data = subset(economics_long,variable=="pce"), size = 1.05)+
scale_colour_manual(values = some_cols)+
scale_fill_manual(values = some_fills)+
theme_minimal()
which produces
How can I combine legends for color and linetype into a single legend in ggplot?
Try this. Make a hash of the two fields you're using (mutate(hybrid = paste(Meteorological_Season_Factor, Treatment))
), and then use that for both color and line type (aes(...col = hybrid, linetype = hybrid)
), and then use named vectors for your values in both scale
functions.
Is that what you're looking for? (P.S. I believe I used the labels and values you used in the order in which you used them... maybe that was the only problem is that you'd transposed a couple of them!)
SOtestplot <- test %>%
mutate(hybrid = paste(Meteorological_Season_Factor, Treatment)) %>%
filter(Species == "MEK", binned_alt <= 8000) %>%
ggplot(aes(y = binned_alt/1000, x = `50%`, col = hybrid, linetype = hybrid)) +
geom_path(size = 1.2) +
theme_tufte(base_size = 22) +
geom_errorbarh(aes(xmin =`25%`, xmax = `75%`), height = 0) +
theme(axis.title.x = element_text(vjust=-0.5),
axis.title.y = element_text(vjust=1.5),
panel.grid.major = element_line(colour = "grey80"),
axis.line = element_line(size = 0.5, colour = "black")) +
scale_color_manual(name = "Treatment & Season",
values = c(
`Summer Clean Marine` = "cornflowerblue",
`Winter Clean Marine` = "goldenrod3",
`Summer All Data` = "cornflowerblue",
`Winter All Data` = "goldenrod3"
)) +
scale_linetype_manual(name = "Treatment & Season",
values = c(
`Summer Clean Marine` = "solid",
`Winter Clean Marine` = "dashed",
`Summer All Data` = "solid",
`Winter All Data` = "dashed")
) +
xlab("MEK (ppt)") +
ylab("Altitude (km)")
How to adjust legend for a colour-shape combiation in ggplot2?
You can use scale_color_discrete
and scale_shape_discrete
. Just supply the same name
and labels
argument to each. There is no need to stipulate values
.
You can see that this will retain the default shapes and colors:
data %>%
ggplot(aes(x, y, col = factor(group), shape = factor(group))) +
geom_point(size = 3) +
geom_line() +
scale_color_discrete(name = "Group", labels = c("A", "B")) +
scale_shape_discrete(name = "Group", labels = c("A", "B"))
How to combine linetype and color in legend when they are set by the same variables
Thanks to Roland, here is the answer:
require(ggplot2)
cbPalette <- c("#999999", "#E69F00", "#56B4E9", "#009E73", "#F0E442",
"#0072B2", "#D55E00", "#CC79A7")
cbPalette <- cbPalette[-1]
ggplot(subset(AR.df)) +
geom_line(aes(x = AR.coef, y = value, linetype = Type, colour = Type),size=1.25) +
xlab("AR(1) coefficient") +
ylab("Proportion") +
theme_bw() +
theme(legend.justification=c(1,-0.2),
legend.position=c(0.4,0.3),
legend.text=element_text(size=10),
legend.title=element_text(size=10),
axis.title.x=element_text(size=10),
axis.title.y=element_text(size = 10),
legend.key = element_blank(),
legend.background = element_rect(color="black",size = 0.1)) +
scale_colour_manual(values=cbPalette, name="Analysis Type") +
scale_linetype_manual(values=c("solid", "dashed"),name="Analysis Type") +
theme(legend.key.width=unit(3,"line"))
Combine legends for color and shape into a single legend
You need to use identical name
and labels
values for both shape and colour scale.
pd <- position_dodge(.65)
ggplot(data = data,aes(x= year, y = beta, colour = group2, shape = group2)) +
geom_point(position = pd, size = 4) +
geom_errorbar(aes(ymin = lcl, ymax = ucl), colour = "black", width = 0.5, position = pd) +
scale_colour_manual(name = "Treatment & State",
labels = c("Control, Non-F", "Control, Flwr", "Exclosure, Non-F", "Exclosure, Flwr"),
values = c("blue", "red", "blue", "red")) +
scale_shape_manual(name = "Treatment & State",
labels = c("Control, Non-F", "Control, Flwr", "Exclosure, Non-F", "Exclosure, Flwr"),
values = c(19, 19, 17, 17))
Add a combined legend that accounts for color, shape, and linetype, while keeping the original legends
You can do this through guide_legend
. Within that, you can override the default aes()
specified via the other ggplot2
commands to match what you want:
p + guides(color=guide_legend(
override.aes = list(linetype=c(1,3,1,3), shape=c(16,16,17,17))))
Related Topics
Table of Interactions - Case With Pets and Houses
Unlist Data Frame Column Preserving Information from Other Column
How to Quickly Form Groups (Quartiles, Deciles, etc) by Ordering Column(S) in a Data Frame
How to Get Week Numbers from Dates
Why Do I Get "Warning Longer Object Length Is Not a Multiple of Shorter Object Length"
R Shiny: Handle Action Buttons in Data Table
How to Suppress Warnings Globally in an R Script
Sample N Random Rows Per Group in a Dataframe
Dummify Character Column and Find Unique Values
Efficient Way to Rbind Data.Frames With Different Columns
Merge Two Data Frames While Keeping the Original Row Order
Dplyr Filter: Get Rows With Minimum of Variable, But Only the First If Multiple Minima
Converting Decimal to Binary in R
Get "Embedded Nul(S) Found in Input" When Reading a CSV Using Read.Csv()
Difference: "Compile Pdf" Button in Rstudio Vs. Knit() and Knit2Pdf()