Agregar leyenda al diagrama de líneas de ggplot2
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)
## edit from original post - removed lines that downloaded data from broken link. Data snippet now below.
## Here a subset as used by [Brian Diggs in their answer](https://stackoverflow.com/a/10355844/7941188)
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")
ggplot(data = datos, aes(x = fecha, y = TempMax, colour = "1")) +
geom_line(colour = "red") +
geom_line(aes(x = fecha, y = TempMedia, colour = "2"), colour = "green") +
geom_line(aes(x = fecha, y = TempMin, colour = "2"), colour = "blue") +
scale_y_continuous(limits = c(-10, 40)) +
scale_colour_manual(values = c("red", "green", "blue")) +
labs(title = "TITULO", x = NULL, y = "Temperatura (C)")
Me gustaría agregar una leyenda con los tres colores utilizados y el nombre de la variable (TempMax,TempMedia y TempMin). Lo he intentado
scale_colour_manual
, pero no encuentro la forma exacta.
Dado que @Etienne preguntó cómo hacer esto sin fundir los datos (que en general es el método preferido, pero reconozco que puede haber algunos casos en los 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 dé un color asignando la colour
estética a una cadena constante. Elegir la cadena que quieres 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 y
variable que se está representando no es significativo; podría ser cualquier conjunto de cadenas. Es muy importante que esto esté dentro de la aes
convocatoria; está creando una asignación para esta "variable".
scale_colour_manual
Ahora puede asignar estas cadenas a los colores apropiados. El resultado es
En algunos casos, la asignación entre los niveles y los colores debe hacerse explícita nombrando 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, las rupturas se pueden usar para establecer el orden en la leyenda y se puede usar cualquier orden 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")
Tiendo a descubrir que si especifico colores individuales en varias geom, lo estoy haciendo mal. Así es como trazaría sus datos:
library(ggplot2)
library(tidyr)
dd_tidyr <- pivot_longer(datos, cols = -fecha, names_to = "Temperature")
Todo lo que queda es un simple comando ggplot:
ggplot(dd_tidyr) +
geom_line(aes(x = fecha, y = value, colour = Temperature)) +
scale_colour_manual(values = c("red", "green", "blue"))
Hay otras formas de remodelar los datos. Una forma reemplazada es utilizar el paquete {reshape2} ahora retirado.
library(reshape2)
dd = melt(datos, id=c("fecha"))
Realmente me gusta la solución propuesta por @Brian Diggs. Sin embargo, en mi caso, creo los diagramas de líneas en un bucle en lugar de darlos explícitamente porque no sé a priori cuántos diagramas tendré. Cuando intenté adaptar el código de @Brian me encontré con 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.cols
y my.names
dinámicamente, pero no quiero complicar innecesariamente las cosas, así que las doy explícitamente aquí. Estas tres líneas facilitan el ordenamiento 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
Otra opción usando scale_color_identity
. La clave es especificar el nombre del color en cada uno aes
de cada uno geom_line
. En el scale_color_identity
puedes mencionar cada color como breaks
y agregar el labels
que quieras. Aquí hay un ejemplo reproducible:
library(ggplot2)
temp = ggplot(data = datos, aes(x = fecha)) +
geom_line(aes(y = TempMax, colour = "red")) +
geom_line(aes(y = TempMedia, colour = "green")) +
geom_line(aes(y = TempMin, colour = "blue")) +
labs(title="TITULO") +
ylab("Temperatura (C)") +
xlab(" ") +
scale_y_continuous(limits = c(-10,40)) +
scale_color_identity(name = '',
breaks = c('red', 'green', 'blue'),
labels = c("TempMax", "TempMedia", "TempMin"),
guide = 'legend')
temp
Creado el 19/11/2022 con reprex v2.0.2