By pacomet


2012-04-27 10:45:25 8 Comments

I have a question about legends in ggplot2. I managed to plot three lines in the same graph and want to add a legend with the three colors used. This is the code used

library(ggplot2)    
require(RCurl)

link<-getURL("https://dl.dropbox.com/s/ds5zp9jonznpuwb/dat.txt")
datos<- read.csv(textConnection(link),header=TRUE,sep=";")
datos$fecha <- as.POSIXct(datos[,1], format="%d/%m/%Y")    

temp = ggplot(data=datos,aes(x=fecha, y=TempMax,colour="1")) + 
           geom_line(colour="red") + opts(title="TITULO") +
           ylab("Temperatura (C)") + xlab(" ") + 
           scale_y_continuous(limits = c(-10,40)) + 
           geom_line(aes(x=fecha, y=TempMedia,colour="2"),colour="green") + 
           geom_line(aes(x=fecha, y=TempMin,colour="2"),colour="blue") +
           scale_colour_manual(values=c("red","green","blue"))

temp

and the output

ggplot three lines

I'd like to add a legend with the three colours used and the name of the variable (TempMax,TempMedia and TempMin). I have tried

scale_colour_manual

but can't find the exact way.

Unfortunately original data were deleted from linked site and could not be recovered. But they came from meteo data files with this format

"date","Tmax","Tmin","Tmed","Precip.diaria","Wmax","Wmed"
2000-07-31 00:00:00,-1.7,-1.7,-1.7,-99.9,20.4,20.4
2000-08-01 00:00:00,22.9,19,21.11,-99.9,6.3,2.83
2000-08-03 00:00:00,24.8,12.3,19.23,-99.9,6.8,3.87
2000-08-04 00:00:00,20.3,9.4,14.4,-99.9,8.3,5.29
2000-08-08 00:00:00,25.7,14.4,19.5,-99.9,7.9,3.22
2000-08-09 00:00:00,29.8,16.2,22.14,-99.9,8.5,3.27
2000-08-10 00:00:00,30,17.8,23.5,-99.9,7.7,3.61
2000-08-11 00:00:00,27.5,17,22.68,-99.9,8.8,3.85
2000-08-12 00:00:00,24,13.3,17.32,-99.9,8.4,3.49

3 comments

@Justyna 2018-05-02 17:35:25

I really like the solution proposed by @Brian Diggs. However, in my case, I create the line plots in a loop rather than giving them explicitly because I do not know apriori how many plots I will have. When I tried to adapt the @Brian's code I faced some problems with handling the colors correctly. Turned out I needed to modify the aesthetic functions. In case someone has the same problem, here is the code that worked for me.

I used the same data frame as @Brian:

data <- structure(list(month = structure(c(1317452400, 1317538800, 1317625200, 1317711600, 
                                       1317798000, 1317884400, 1317970800, 1318057200, 
                                       1318143600, 1318230000, 1318316400, 1318402800, 
                                       1318489200, 1318575600, 1318662000, 1318748400, 
                                       1318834800, 1318921200, 1319007600, 1319094000), 
                                     class = c("POSIXct", "POSIXt"), tzone = ""),
                   TempMax = c(26.58, 27.78, 27.9, 27.44, 30.9, 30.44, 27.57, 25.71, 
                               25.98, 26.84, 33.58, 30.7, 31.3, 27.18, 26.58, 26.18, 
                               25.19, 24.19, 27.65, 23.92), 
                   TempMed = c(22.88, 22.87, 22.41, 21.63, 22.43, 22.29, 21.89, 20.52,
                                 19.71, 20.73, 23.51, 23.13, 22.95, 21.95, 21.91, 20.72, 
                                 20.45, 19.42, 19.97, 19.61), 
                   TempMin = c(19.34, 19.14, 18.34, 17.49, 16.75, 16.75, 16.88, 16.82, 
                               14.82, 16.01, 16.88, 17.55, 16.75, 17.22, 19.01, 16.95, 
                               17.55, 15.21, 14.22, 16.42)), 
              .Names = c("month", "TempMax", "TempMed", "TempMin"), 
              row.names = c(NA, 20L), class = "data.frame")  

In my case, I generate my.cols and my.names dynamically, but I don't want to make things unnecessarily complicated so I give them explicitly here. These three lines make the ordering of the legend and assigning colors easier.

my.cols <- heat.colors(3, alpha=1)
my.names <- c("TempMin", "TempMed", "TempMax")
names(my.cols) <- my.names

And here is the plot:

p <-  ggplot(data, aes(x = month))

for (i in 1:3){
  p <- p + geom_line(aes_(y = as.name(names(data[i+1])), colour = 
colnames(data[i+1])))#as.character(my.names[i])))
}
p + scale_colour_manual("", 
                        breaks = as.character(my.names),
                        values = my.cols)
p

enter image description here

@Axeman 2018-05-14 14:38:33

At this complexity, it really becomes much easier to just reshape your data into the long form that ggplot expects.

@Justyna 2018-05-15 17:42:34

I don't think it really adds complexity compare to the original answer posted by @Brian. Besides, some people might want to do it without reshaping the data.

@mac 2018-11-09 17:51:50

...and this approach allows different geoms (plot types) by variable

@csgillespie 2012-04-27 10:57:18

I tend to find that if I'm specifying individual colours in multiple geom's, I'm doing it wrong. Here's how I would plot your data:

##Subset the necessary columns
dd_sub = datos[,c(20, 2,3,5)]
##Then rearrange your data frame
library(reshape2)
dd = melt(dd_sub, id=c("fecha"))

All that's left is a simple ggplot command:

ggplot(dd) + geom_line(aes(x=fecha, y=value, colour=variable)) +
  scale_colour_manual(values=c("red","green","blue"))

Example plot

enter image description here

@Etienne Low-Décarie 2012-04-27 11:48:44

I am still curious about how to add legends associated with separate addition of elements such as geom_line, which I though was the original purpose of the question.

@Brian Diggs 2012-04-27 18:20:20

Since @Etienne asked how to do this without melting the data (which in general is the preferred method, but I recognize there may be some cases where that is not possible), I present the following alternative.

Start with a subset of the original data:

datos <-
structure(list(fecha = structure(c(1317452400, 1317538800, 1317625200, 
1317711600, 1317798000, 1317884400, 1317970800, 1318057200, 1318143600, 
1318230000, 1318316400, 1318402800, 1318489200, 1318575600, 1318662000, 
1318748400, 1318834800, 1318921200, 1319007600, 1319094000), class = c("POSIXct", 
"POSIXt"), tzone = ""), TempMax = c(26.58, 27.78, 27.9, 27.44, 
30.9, 30.44, 27.57, 25.71, 25.98, 26.84, 33.58, 30.7, 31.3, 27.18, 
26.58, 26.18, 25.19, 24.19, 27.65, 23.92), TempMedia = c(22.88, 
22.87, 22.41, 21.63, 22.43, 22.29, 21.89, 20.52, 19.71, 20.73, 
23.51, 23.13, 22.95, 21.95, 21.91, 20.72, 20.45, 19.42, 19.97, 
19.61), TempMin = c(19.34, 19.14, 18.34, 17.49, 16.75, 16.75, 
16.88, 16.82, 14.82, 16.01, 16.88, 17.55, 16.75, 17.22, 19.01, 
16.95, 17.55, 15.21, 14.22, 16.42)), .Names = c("fecha", "TempMax", 
"TempMedia", "TempMin"), row.names = c(NA, 20L), class = "data.frame")

You can get the desired effect by (and this also cleans up the original plotting code):

ggplot(data = datos, aes(x = fecha)) +
  geom_line(aes(y = TempMax, colour = "TempMax")) +
  geom_line(aes(y = TempMedia, colour = "TempMedia")) +
  geom_line(aes(y = TempMin, colour = "TempMin")) +
  scale_colour_manual("", 
                      breaks = c("TempMax", "TempMedia", "TempMin"),
                      values = c("red", "green", "blue")) +
  xlab(" ") +
  scale_y_continuous("Temperatura (C)", limits = c(-10,40)) + 
  labs(title="TITULO")

The idea is that each line is given a color by mapping the colour aesthetic to a constant string. Choosing the string which is what you want to appear in the legend is the easiest. The fact that in this case it is the same as the name of the y variable being plotted is not significant; it could be any set of strings. It is very important that this is inside the aes call; you are creating a mapping to this "variable".

scale_colour_manual can now map these strings to the appropriate colors. The result is enter image description here

In some cases, the mapping between the levels and colors needs to be made explicit by naming the values in the manual scale (thanks to @DaveRGP for pointing this out):

ggplot(data = datos, aes(x = fecha)) +
  geom_line(aes(y = TempMax, colour = "TempMax")) +
  geom_line(aes(y = TempMedia, colour = "TempMedia")) +
  geom_line(aes(y = TempMin, colour = "TempMin")) +
  scale_colour_manual("", 
                      values = c("TempMedia"="green", "TempMax"="red", 
                                 "TempMin"="blue")) +
  xlab(" ") +
  scale_y_continuous("Temperatura (C)", limits = c(-10,40)) + 
  labs(title="TITULO")

(giving the same figure as before). With named values, the breaks can be used to set the order in the legend and any order can be used in the values.

ggplot(data = datos, aes(x = fecha)) +
  geom_line(aes(y = TempMax, colour = "TempMax")) +
  geom_line(aes(y = TempMedia, colour = "TempMedia")) +
  geom_line(aes(y = TempMin, colour = "TempMin")) +
  scale_colour_manual("", 
                      breaks = c("TempMedia", "TempMax", "TempMin"),
                      values = c("TempMedia"="green", "TempMax"="red", 
                                 "TempMin"="blue")) +
  xlab(" ") +
  scale_y_continuous("Temperatura (C)", limits = c(-10,40)) + 
  labs(title="TITULO")

@DaveRGP 2015-01-20 15:56:57

I love this solution, but I think there may be a limitation. Is there an alphabetic sorting issue between the mapping of the 'breaks' and 'values' variables? TempM{a]x, TempM{e}dia and TempM{i}n sort neatly, though when I adapt this to my variable names, the colours seem to get matched in alphabetical order to the 'breaks', not in the order input. Can the above be clarified/refined to reflect/fix this?

@DaveRGP 2015-02-03 14:57:24

I've managed to find a fix to the issue I bought up earlier re: colour ordering. use the form scale_colour_manual("", values = c("TempMax" = "red", "TempMedia" = "green", "TempMin" = "blue")) where TempMax, TempMedia and TempMin are specified as the colour argument as in the answer above.

@Alessandro Jacopson 2015-06-16 08:30:56

@DaveRGP Could it be considered a bug of ggplot?

@Stella Biderman 2017-01-30 17:48:35

Very late to the party, but grateful for the answer to the question as asked, as this is the first google search result for custom legends.

@Brian Diggs 2017-01-30 18:06:16

@StellaBiderman Thank you. It's nice to know that this answer is still useful (nearly) 5 years (!) later.

@Stella Biderman 2017-01-30 18:12:32

@BrianDiggs You wouldn't happen to know how to make this show a dot in the scale as opposed to a line would you?

@Brian Diggs 2017-01-30 21:21:14

@StellaBiderman That is worthy of its own, separate question. stackoverflow.com/a/16529687/892313 is close to what you want, but that answer assumes you have points already on the graph as well as lines. In this example, that is not the case.

@Abhishek 2018-08-14 14:56:26

As @Brian Diggs states "The fact that in this case it is the same as the name of the y variable being plotted is not significant;". It is most important the values should be string Solution: Enclose each string with (tilde) i.e "Temp Max"

Related Questions

Sponsored Content

12 Answered Questions

[SOLVED] Order Bars in ggplot2 bar graph

  • 2011-03-06 04:20:48
  • Julio Diaz
  • 234814 View
  • 247 Score
  • 12 Answer
  • Tags:   r ggplot2 r-faq

5 Answered Questions

[SOLVED] Plotting two variables as lines using ggplot2 on the same graph

16 Answered Questions

[SOLVED] Plot two graphs in same plot in R

  • 2010-04-01 23:28:14
  • Sandra Schlichting
  • 1066850 View
  • 487 Score
  • 16 Answer
  • Tags:   r plot ggplot2 r-faq

16 Answered Questions

[SOLVED] How to put the legend out of the plot

5 Answered Questions

[SOLVED] Rotating and spacing axis labels in ggplot2

  • 2009-08-25 21:05:24
  • Christopher DuBois
  • 540169 View
  • 531 Score
  • 5 Answer
  • Tags:   r ggplot2 labels

12 Answered Questions

[SOLVED] Side-by-side plots with ggplot2

  • 2009-08-08 18:16:43
  • Christopher DuBois
  • 259379 View
  • 266 Score
  • 12 Answer
  • Tags:   r visualization ggplot2

2 Answered Questions

2 Answered Questions

[SOLVED] How to set limits for axes in ggplot2 R plots?

  • 2010-08-31 07:03:24
  • David B
  • 490330 View
  • 306 Score
  • 2 Answer
  • Tags:   r plot ggplot2

11 Answered Questions

[SOLVED] How to save a plot as image on the disk?

2 Answered Questions

[SOLVED] geom_point() and geom_line() for multiple datasets on same graph in ggplot2

  • 2011-09-19 19:08:26
  • MZT
  • 68592 View
  • 32 Score
  • 2 Answer
  • Tags:   r ggplot2

Sponsored Content