180 votes

Ajout d'une légende au graphique linéaire ggplot2

J'ai une question sur les légendes dans ggplot2. J'ai réussi à tracer trois lignes dans le même graphique et je veux ajouter une légende avec les trois couleurs utilisées. Voici le code utilisé

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

et la sortie

ggplot three lines

J'aimerais ajouter une légende avec les trois couleurs utilisées et le nom de la variable (TempMax, TempMedia et TempMin). J'ai essayé

scale_colour_manual

mais je n'arrive pas à trouver le moyen exact.

Malheureusement, les données originales ont été supprimées du site lié et n'ont pas pu être récupérées. Mais elles provenaient de fichiers de données météo ayant ce 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

1 votes

Je suis toujours curieux de savoir si les légendes peuvent être liées à des éléments distincts du tracé (comme des lignes géométriques différentes).

0 votes

Si vous n'avez que 3 lignes, je vous suggère de regarder le paquet dirrectlabels. (LIEN)

0 votes

@TylerRinker Je l'avais déjà utilisé à d'autres fins, mais la réponse de csgillespie me convient mieux maintenant.

248voto

Brian Diggs Points 22433

Desde @Etienne a demandé comment faire cela sans faire fondre les données (ce qui est en général la méthode préférée, mais je reconnais qu'il peut y avoir des cas où cela n'est pas possible), je présente l'alternative suivante.

Commencez par un sous-ensemble des données d'origine :

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

Vous pouvez obtenir l'effet désiré en (et cela nettoie également le code de traçage 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")

L'idée est d'attribuer une couleur à chaque ligne en mettant en correspondance les éléments suivants colour esthétique à une chaîne constante. Le choix de la chaîne qui correspond à ce que vous voulez voir apparaître dans la légende est le plus simple. Le fait que dans ce cas, il s'agisse du même nom que celui de la balise y La variable tracée n'est pas significative ; il peut s'agir de n'importe quel ensemble de chaînes de caractères. Il est très important que ce soit à l'intérieur de l'élément aes vous créez une correspondance avec cette "variable".

scale_colour_manual peut maintenant faire correspondre ces chaînes de caractères aux couleurs appropriées. Le résultat est enter image description here

Dans certains cas, le mappage entre les niveaux et les couleurs doit être rendu explicite en nommant les valeurs dans l'échelle manuelle (merci à @DaveRGP pour l'avoir signalé) :

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

(ce qui donne le même chiffre que précédemment). Avec les valeurs nommées, les ruptures peuvent être utilisées pour définir l'ordre dans la légende et n'importe quel ordre peut être utilisé dans les valeurs.

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

2 votes

J'adore cette solution, mais je pense qu'il y a peut-être une limite. Y a-t-il un problème de tri alphabétique entre le mappage des variables "breaks" et "values" ? TempM{a]x, TempM{e}dia et TempM{i}n sont bien triés, mais lorsque je l'adapte à mes noms de variables, les couleurs semblent correspondre par ordre alphabétique aux "ruptures", et non dans l'ordre de saisie. Peut-on clarifier/affiner ce qui précède pour refléter/corriger ce problème ?

4 votes

J'ai réussi à trouver une solution au problème que j'ai soulevé plus tôt concernant la commande de couleurs. Utilisez le formulaire. scale_colour_manual("", values = c("TempMax" = "red", "TempMedia" = "green", "TempMin" = "blue")) où TempMax, TempMedia et TempMin sont spécifiés comme argument de couleur comme dans la réponse ci-dessus.

0 votes

@DaveRGP Peut-on considérer que c'est un bug de ggplot ?

93voto

csgillespie Points 20349

J'ai tendance à penser que si je spécifie des couleurs individuelles dans plusieurs géomètres, je m'y prends mal. Voici comment je représenterais vos données :

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

Il ne reste plus qu'une simple commande ggplot :

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

Exemple d'intrigue

enter image description here

106 votes

Je suis toujours curieux de savoir comment ajouter des légendes associées à l'ajout séparé d'éléments tels que geom_line, ce qui, je pensais, était le but initial de la question.

4 votes

Parce que cette réponse est souvent citée, et parce que reshape2 a été retiré du marché, il serait bon de montrer une page d'accueil. tidyr::pivot_longer() pour remodeler les données également.

2voto

Justyna Points 397

J'aime beaucoup la solution proposée par @Brian Diggs. Cependant, dans mon cas, je crée les graphiques linéaires dans une boucle plutôt que de les donner explicitement parce que je ne sais pas apriori combien de graphiques j'aurai. Lorsque j'ai essayé d'adapter le code de @Brian, j'ai rencontré quelques problèmes pour gérer correctement les couleurs. Il s'est avéré que j'ai dû modifier les fonctions esthétiques. Au cas où quelqu'un aurait le même problème, voici le code qui a fonctionné pour moi.

J'ai utilisé le même cadre de données 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")  

Dans mon cas, je génère my.cols y my.names dynamiquement, mais je ne veux pas rendre les choses inutilement compliquées, donc je les donne explicitement ici. Ces trois lignes facilitent l'ordonnancement de la légende et l'attribution des couleurs.

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

Et voici l'intrigue :

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

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X