Agregar leyenda al diagrama de línea ggplot2

143

Tengo una pregunta sobre leyendas en ggplot2. Logré trazar tres líneas en el mismo gráfico y quiero agregar una leyenda con los tres colores utilizados. Este es el código usado

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

y la salida

ggplot tres líneas

Me gustaría agregar una leyenda con los tres colores utilizados y el nombre de la variable (TempMax, TempMedia y TempMin). Yo he tratado

scale_colour_manual

pero no puedo encontrar la manera exacta.

Lamentablemente, los datos originales se eliminaron del sitio vinculado y no se pudieron recuperar. Pero vinieron de archivos de datos meteo con este formato

"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
pacomet
fuente
Todavía tengo curiosidad de saber si las leyendas pueden vincularse con elementos separados de la trama (como diferentes geom_line).
Etienne Low-Décarie
Si solo tiene 3 líneas, le sugiero que consulte el paquete dirrectlabels. (ENLACE)
Tyler Rinker
@TylerRinker Lo había usado antes para otros fines, pero ahora la respuesta de csgillespie me funciona mejor
pacomet
@ EtienneLow-Décarie Puedes, pero en general solo si usan una estética diferente. por ejemplo, mapear un conjunto de líneas a color y otro a tipo de línea. Por lo general, también pasaría datos separados a cada geom en ese caso.
joran

Respuestas:

82

Tiendo a encontrar que si estoy especificando colores individuales en múltiples geom, lo estoy haciendo mal. Así es como trazaría sus datos:

##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"))

Todo lo que queda es un simple comando ggplot:

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

Parcela de ejemplo

ingrese la descripción de la imagen aquí

csgillespie
fuente
87
Todavía tengo curiosidad acerca de cómo agregar leyendas asociadas con la adición por separado de elementos como geom_line, que, sin embargo, era el propósito original de la pregunta.
Etienne Low-Décarie
201

Como @Etienne preguntó cómo hacer esto sin fusionar los datos (que en general es el método preferido, pero reconozco que puede haber algunos casos en que eso no sea posible), presento la siguiente alternativa.

Comience con un subconjunto de los datos originales:

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")

Puede obtener el efecto deseado (y esto también limpia el código de trazado original):

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")

La idea es que a cada línea se le asigne un color asignando la colourestética a una cadena constante. Elegir la cadena que es lo que desea que aparezca en la leyenda es lo más fácil. El hecho de que en este caso sea el mismo que el nombre de la yvariable que se está trazando no es significativo; podría ser cualquier conjunto de cuerdas. Es muy importante que esto esté dentro de la aesllamada; está creando una asignación a esta "variable".

scale_colour_manualAhora puede asignar estas cadenas a los colores apropiados. El resultado es ingrese la descripción de la imagen aquí

En algunos casos, la asignación entre los niveles y los colores debe hacerse explícita al nombrar los valores en la escala manual (gracias a @DaveRGP por señalar esto):

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")

(dando la misma cifra que antes). Con valores con nombre, los saltos se pueden usar para establecer el orden en la leyenda y cualquier orden se puede usar en los valores.

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")

Brian Diggs
fuente
2
Me encanta esta solución, pero creo que puede haber una limitación. ¿Existe un problema de clasificación alfabética entre la asignación de las variables 'interrupciones' y 'valores'? TempM {a] x, TempM {e} dia y TempM {i} n se ordenan ordenadamente, aunque cuando adapto esto a mis nombres de variables, los colores parecen coincidir en orden alfabético con los 'saltos', no en la entrada de orden . ¿Se puede aclarar / refinar lo anterior para reflejar / arreglar esto?
DaveRGP
3
Me las arreglé para encontrar una solución al problema que compré anteriormente con respecto a los pedidos de color. use el formulario scale_colour_manual("", values = c("TempMax" = "red", "TempMedia" = "green", "TempMin" = "blue"))donde TempMax, TempMedia y TempMin se especifican como el argumento de color como en la respuesta anterior.
DaveRGP
@DaveRGP ¿Podría considerarse un error de ggplot?
Alessandro Jacopson
1
@StellaBiderman Gracias. Es bueno saber que esta respuesta sigue siendo útil (casi) 5 años (!) Más tarde.
Brian Diggs el
1
@BrianDiggs No sabrías cómo hacer que esto muestre un punto en la escala en lugar de una línea, ¿verdad?
Stella Biderman
2

Realmente me gusta la solución propuesta por @Brian Diggs. Sin embargo, en mi caso, creo los gráficos de líneas en un bucle en lugar de darlos explícitamente porque no sé a priori cuántos gráficos tendré. Cuando traté de adaptar el código de @ Brian, tuve algunos problemas para manejar los colores correctamente. Resultó que necesitaba modificar las funciones estéticas. En caso de que alguien tenga el mismo problema, aquí está el código que funcionó para mí.

Usé el mismo marco de datos que @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")  

En mi caso, genero my.colsy my.namesdinámicamente, pero no quiero complicar las cosas innecesariamente, así que las doy explícitamente aquí. Estas tres líneas facilitan el orden de la leyenda y la asignación de colores.

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

Y aquí está la trama:

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

ingrese la descripción de la imagen aquí

Justyna
fuente
2
A esta complejidad, realmente se vuelve mucho más fácil simplemente remodelar sus datos en la forma larga que ggplotespera.
Axeman
1
No creo que realmente agregue complejidad en comparación con la respuesta original publicada por @Brian. Además, algunas personas pueden querer hacerlo sin cambiar la forma de los datos.
Justyna
... y este enfoque permite diferentes geoms (tipos de parcelas) por variable
mac