ggplot2中多geom_line图例不显示问题求助(含geom_ribbon场景)
Hey there! I see exactly what's going on here. The legend isn't showing up because you're setting the colour directly on each geom_line (outside the aes() mapping) instead of mapping it to a categorical variable in your data. ggplot needs that mapping to build a legend, and your wide-format data (with separate columns A/B/C) makes this tricky. Let's fix this properly!
Step 1: Convert Your Data to Tidy (Long) Format
First, we'll reshape your data so that all the line values (A, B, C) are in a single column, paired with a column that identifies which group each value belongs to. We'll use tidyr::pivot_longer for this:
library(ggplot2) library(tidyr) # For pivot_longer Year <- c(2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012) hi <- c(5.9, 5, 5, 4.9, 6.1, 5.9, 5.8, 6.2, 6.4) lo <- c(4, 4, 3.8, 3.9, 4.5, 4.3, 4.1, 3.9, 3.7) A <- c(4.4, 4.3, 4.7, 4.5, 5.5, 5.2, 5.4, 4.8, 4.4) B <- c(4.7, 4.6, 4, 4.1, 4.7, 4.6, 4.4, 4.6, 4.8) C <- c(0.61, 0.31, 0.13, 0.18, 0.24, 0.44, 0.32, 0.5, 0.4) test <- data.frame(Year, hi, lo, A, B, C) # Reshape to long format test_long <- pivot_longer(test, cols = c(A, B, C), names_to = "Group", values_to = "Value")
Step 2: Update Your ggplot Code
Now we can map the Group column to the colour aesthetic in a single geom_line layer. This tells ggplot to create a legend based on the Group variable, and your scale_colour_manual will work as expected. The geom_ribbon stays as-is since it's just a background element and doesn't need to be in the legend:
ggplot(test_long, aes(Year)) + geom_ribbon(aes(ymin = lo , ymax = hi), fill = "grey90") + geom_line(aes(y = Value, colour = Group), size = 1) + # Map colour to Group here ggthemes::theme_hc() + scale_x_continuous(labels = abs, limits = c(2004, 2012), breaks = seq(2004, 2012, 4)) + scale_colour_manual("", values = c("A" = "black", "B" = "#55BF3B", "C" = "#f15c80"))
Why This Works
- By moving
colourinto theaes()and mapping it to theGroupvariable, ggplot recognizes that it needs to create a legend to distinguish the groups. - Using long-format data is the standard ggplot approach—it makes your code cleaner (no need for multiple
geom_linelayers) and easier to maintain if you add more groups later.
Alternative (If You Don't Want to Reshape Data)
If you really don't want to convert to long format, you can explicitly set the colour inside aes() for each line. This will let ggplot pick up the mappings for the legend, but it's less efficient:
ggplot(test, aes(Year)) + geom_ribbon(aes(ymin = lo , ymax = hi), fill = "grey90") + geom_line(aes(y = A, colour = "A"), size = 1) + # colour inside aes() geom_line(aes(y = B, colour = "B"), size = 1) + geom_line(aes(y = C, colour = "C"), size = 1) + ggthemes::theme_hc() + scale_x_continuous(labels = abs, limits = c(2004, 2012), breaks = seq(2004, 2012, 4)) + scale_colour_manual("", values = c("A" = "black", "B" = "#55BF3B", "C" = "#f15c80"))
Either way, you'll get the legend you're looking for!
内容的提问来源于stack exchange,提问作者user3047435

