Aggiungi legenda al grafico a linee ggplot2


143

Ho una domanda sulle leggende in ggplot2. Sono riuscito a tracciare tre linee nello stesso grafico e voglio aggiungere una legenda con i tre colori utilizzati. Questo è il codice utilizzato

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

e l'uscita

ggplot tre righe

Vorrei aggiungere una legenda con i tre colori utilizzati e il nome della variabile (TempMax, TempMedia e TempMin). Ho provato

scale_colour_manual

ma non riesco a trovare il modo esatto.

Purtroppo i dati originali sono stati eliminati dal sito collegato e non è stato possibile recuperarli. Ma provenivano da file di dati meteo con questo 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

Sono ancora curioso di sapere se le leggende possono essere legate a elementi separati della trama (come diverse geom_line).
Etienne Low-Décarie,

Se hai solo 3 righe ti suggerirei di guardare il pacchetto dirrectlabels. (LINK)
Tyler Rinker,

@TylerRinker L'avevo usato prima per altri scopi, ma ora la risposta di csgillespie funziona meglio per me
pacomet

@ EtienneLow-Décarie Puoi, ma in generale solo se usano un'estetica diversa. ad es. mappatura di una serie di linee per colorare e un'altra per il tipo di linea. In genere, in quel caso passeresti dati separati a ciascun geom.
joran,

Risposte:


82

Tendo a scoprire che se sto specificando i singoli colori in più geom, sto sbagliando. Ecco come vorrei tracciare i tuoi dati:

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

Tutto ciò che rimane è un semplice comando ggplot:

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

Esempio di trama

inserisci qui la descrizione dell'immagine


87
Sono ancora curioso di sapere come aggiungere le leggende associate all'aggiunta separata di elementi come geom_line, che pensavo fosse lo scopo originale della domanda.
Etienne Low-Décarie,

202

Dato che @Etienne ha chiesto come farlo senza fondere i dati (che in generale è il metodo preferito, ma riconosco che potrebbero esserci alcuni casi in cui ciò non è possibile), presento la seguente alternativa.

Inizia con un sottoinsieme dei dati originali:

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

Puoi ottenere l'effetto desiderato (e questo pulisce anche il codice di stampa originale):

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'idea è che ad ogni linea sia dato un colore mappando l' colourestetica a una stringa costante. La scelta della stringa che è ciò che si desidera visualizzare nella legenda è la più semplice. Il fatto che in questo caso sia lo stesso del nome della yvariabile da tracciare non è significativo; potrebbe essere qualsiasi set di stringhe. È molto importante che questo sia all'interno della aeschiamata; stai creando una mappatura su questa "variabile".

scale_colour_manualora può mappare queste stringhe con i colori appropriati. Il risultato è inserisci qui la descrizione dell'immagine

In alcuni casi, la mappatura tra livelli e colori deve essere resa esplicita nominando i valori nella scala manuale (grazie a @DaveRGP per averlo sottolineato):

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 stessa cifra di prima). Con i valori nominati, le interruzioni possono essere utilizzate per impostare l'ordine nella legenda e qualsiasi valore può essere utilizzato nei valori.

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
Adoro questa soluzione, ma penso che ci possa essere un limite. Esiste un problema di ordinamento alfabetico tra la mappatura delle variabili "pause" e "valori"? TempM {a] x, TempM {e} dia e TempM {i} n ordinano ordinatamente, anche se quando lo adatta ai miei nomi variabili, i colori sembrano essere abbinati in ordine alfabetico alle "interruzioni", non nell'input dell'ordine . Quanto sopra può essere chiarito / perfezionato per riflettere / risolvere questo problema?
DaveRGP,

3
Sono riuscito a trovare una soluzione al problema che avevo acquistato in precedenza in merito all'ordinamento dei colori. utilizzare il modulo in scale_colour_manual("", values = c("TempMax" = "red", "TempMedia" = "green", "TempMin" = "blue"))cui TempMax, TempMedia e TempMin sono specificati come argomento color come nella risposta sopra.
DaveRGP,

@DaveRGP Potrebbe essere considerato un bug di ggplot?
Alessandro Jacopson,

1
@StellaBiderman Grazie. È bello sapere che questa risposta è ancora utile (quasi) 5 anni (!) Più tardi.
Brian Diggs,

1
@BrianDiggs Non capiresti come rendere questo show un punto nella scala invece di una linea, vero?
Stella Biderman,

2

Mi piace molto la soluzione proposta da @Brian Diggs. Tuttavia, nel mio caso, creo le trame di linea in un ciclo piuttosto che fornirle esplicitamente perché non conosco apriori quante trame avrò. Quando ho provato ad adattare il codice di @ Brian ho riscontrato alcuni problemi con la gestione corretta dei colori. Ho scoperto che dovevo modificare le funzioni estetiche. Nel caso in cui qualcuno abbia lo stesso problema, ecco il codice che ha funzionato per me.

Ho usato lo stesso frame di dati di @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")  

Nel mio caso, genero my.colse in my.namesmodo dinamico, ma non voglio rendere le cose inutilmente complicate, quindi le do esplicitamente qui. Queste tre righe semplificano l'ordinamento della legenda e l'assegnazione dei colori.

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

Ed ecco 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

inserisci qui la descrizione dell'immagine


2
Con questa complessità, diventa davvero molto più semplice rimodellare i tuoi dati nella forma lunga che ti ggplotaspetti.
Axeman

1
Non penso che aggiunga davvero complessità rispetto alla risposta originale pubblicata da @Brian. Inoltre, alcune persone potrebbero voler farlo senza rimodellare i dati.
Justyna,

... e questo approccio consente diversi geomi (tipi di trama) per variabile
mac
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.