Adding a legend to a ggplot (unable to get scale_colour_manual to work)

Apologies, this was posted earlier but deleted as its is a duplicate question. The duplicate talks about using scale_colour_manual to add a legend to the plot however I could not get this to work, i have added my code below including this suggestion. Appreciate its probably frowned upon re-posting so feel free to delete once resolved.

I have the following plot and I wish to add a legend to the plot but cannot seem to be able too. I have included my code and plot below if anyone knows how to do this. I’m looking for red to be ‘east, blue to be ‘west and black to be ‘overall. Also included a small bit of data to be replicated. I’ve had a look at other posts on here suggesting things like scale_colour_manual but unable to get it to work.

code used;

ggplot(climate_df_year, aes(y = overall_sst, x = year)) +
  geom_line() +
  geom_line(aes(y = eastern_sst, x = year), col = 'red', linetype = 2, size = 0.6) +
  geom_line(aes(y = western_sst, x = year), col = 'blue', linetype = 2, size = 0.6) +
  scale_colour_manual("", 
                  breaks = c("Eastern", "Overall", "Western"),
                  values = c("red", "black", "blue")) +
  ylab("SST (°C)") +
  xlab("Year") +
  theme(plot.title = element_text(hjust = 0.5, size = 12, face = 'bold'))

data

year overall_sst eastern_sst     western_sst
1998        20.3        21.3        19.0         
1999        20.6        21.6        19.2        
2000        20.4        21.3        19.1 

plot

enter image description here

>Solution :

I suggest pivoting the data and using ggplot’s native aesthetics for controlling color and linetype.

tidyr::pivot_longer(climate_df_year, -year) |>
  ggplot(aes(year, value)) +
  geom_line(aes(color = name, linetype = !grepl("overall", name))) +
  scale_x_continuous(breaks = do.call(seq, as.list(range(dat$year)))) +
  scale_colour_manual(name = "Something", values = c(overall_sst="black", eastern_sst="red", western_sst="blue")) +
  labs(x = "Year", y = "SST (°C)") +
  scale_linetype_discrete(guide = NULL)

ggplot with legend

One can also use reshape2::melt(climate_df_year, "year", variable.name = "name") for pivoting, same code otherwise.


If you really prefer to not pivot/melt your data, however, the dupe link had several working changes, namely to bring the color= portions into the aes(..) call. Had you done just that from your original code (and removed or updated the scale_colour_manual call, since the breaks would be different), you would have seen a marked change:

ggplot(climate_df_year, aes(y = overall_sst, x = year)) +
  geom_line() +
  geom_line(aes(y = eastern_sst, x = year, col = 'red'), linetype = 2, size = 0.6) +
  geom_line(aes(y = western_sst, x = year, col = 'blue'), linetype = 2, size = 0.6) +
  scale_colour_manual("", 
                  breaks = c("red", "Overall", "blue"),
                  values = c("red", "black", "blue")) +
  ylab("SST (°C)") +
  xlab("Year") +
  theme(plot.title = element_text(hjust = 0.5, size = 12, face = 'bold'))

ggplot as suggested by dupe link

The two changes were bring col= (sic) into aes(..), and renaming two of the breaks= values. From that, a little play suggests adding color= to the original geom_line (for "Overall") and renaming all of the color= values (reverting back to the original scale_colour_manual.

ggplot(climate_df_year, aes(y = overall_sst, x = year)) +
  geom_line(aes(color = 'Overall')) +
  geom_line(aes(y = eastern_sst, x = year, color = 'Eastern'), linetype = 2, size = 0.6) +
  geom_line(aes(y = western_sst, x = year, color = 'Western'), linetype = 2, size = 0.6) +
  scale_colour_manual("", 
                  breaks = c("Eastern", "Overall", "Western"),
                  values = c("red", "black", "blue")) +
  ylab("SST (°C)") +
  xlab("Year") +
  theme(plot.title = element_text(hjust = 0.5, size = 12, face = 'bold'))

ggplot fixed, code suggested by dupe link

Having said all that, I highly recommend sticking with the melted (first) option, as it needs only one call to geom_line, handles all aesthetics natively, and scales better too (e.g., additional variables).

Leave a Reply