Tambahkan legenda ke plot garis ggplot2

143

Saya punya pertanyaan tentang legenda di ggplot2. Saya berhasil menggambar tiga garis dalam grafik yang sama dan ingin menambahkan legenda dengan tiga warna yang digunakan. Ini adalah kode yang digunakan

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

dan hasilnya

ggplot tiga baris

Saya ingin menambahkan legenda dengan tiga warna yang digunakan dan nama variabel (TempMax, TempMedia, dan TempMin). saya telah mencoba

scale_colour_manual

tetapi tidak dapat menemukan cara yang tepat.

Sayangnya data asli dihapus dari situs tertaut dan tidak dapat dipulihkan. Tetapi mereka datang dari file data cuaca dengan format ini

"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
sumber
Saya masih penasaran apakah legenda dapat diikat ke elemen plot yang terpisah (seperti geom_line yang berbeda).
Etienne Low-Décarie
Jika Anda hanya memiliki 3 baris saya sarankan melihat paket dirrectlabels. (LINK)
Tyler Rinker
@ TylerRinker Saya telah menggunakannya sebelumnya untuk tujuan lain, tetapi sekarang jawaban dari csgillespie lebih baik bagi saya
pacomet
@ EtienneLow-Décarie Anda bisa, tetapi secara umum hanya jika mereka menggunakan estetika yang berbeda. mis. memetakan satu set garis untuk diwarnai dan lainnya untuk linetype. Biasanya Anda akan meneruskan data terpisah untuk setiap geom juga dalam kasus itu.
joran

Jawaban:

82

Saya cenderung menemukan bahwa jika saya menentukan warna individu dalam beberapa geom, saya salah melakukannya. Begini cara saya memplot data Anda:

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

Yang tersisa hanyalah perintah ggplot sederhana:

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

Contoh plot

masukkan deskripsi gambar di sini

csgillespie
sumber
87
Saya masih ingin tahu tentang cara menambahkan legenda yang terkait dengan penambahan elemen yang terpisah seperti geom_line, yang menurut saya merupakan tujuan awal dari pertanyaan tersebut.
Etienne Low-Décarie
201

Karena @Etienne bertanya bagaimana melakukan ini tanpa melelehkan data (yang secara umum adalah metode yang disukai, tapi saya tahu mungkin ada beberapa kasus di mana itu tidak mungkin), saya menyajikan alternatif berikut.

Mulai dengan subset dari data asli:

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

Anda bisa mendapatkan efek yang diinginkan dengan (dan ini juga membersihkan kode plot asli):

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

Idenya adalah bahwa setiap baris diberi warna dengan memetakan colourestetika ke string konstan. Memilih string yang ingin Anda tampilkan dalam legenda adalah yang termudah. Fakta bahwa dalam kasus ini sama dengan nama yvariabel yang diplot tidak signifikan; itu bisa berupa serangkaian string. Sangat penting bahwa ini ada di dalam aespanggilan; Anda membuat pemetaan untuk "variabel" ini.

scale_colour_manualsekarang dapat memetakan string ini ke warna yang sesuai. Hasilnya adalah masukkan deskripsi gambar di sini

Dalam beberapa kasus, pemetaan antara level dan warna perlu dibuat eksplisit dengan menyebutkan nilai dalam skala manual (terima kasih kepada @DaveRGP untuk menunjukkan ini):

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

(memberi angka yang sama seperti sebelumnya). Dengan nilai yang disebutkan, jeda dapat digunakan untuk mengatur urutan dalam legenda dan urutan apa pun dapat digunakan dalam nilai.

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
sumber
2
Saya suka solusi ini, tetapi saya pikir mungkin ada batasan. Apakah ada masalah pengurutan alfabetis antara pemetaan variabel 'istirahat' dan 'nilai'? TempM {a] x, TempM {e} dia dan TempM {i} n menyortir dengan rapi, meskipun ketika saya mengadaptasinya dengan nama variabel saya, warna-warnanya tampak serasi dalam urutan abjad dengan 'break', bukan dalam input urutan . Dapatkah hal di atas diklarifikasi / disempurnakan untuk mencerminkan / memperbaikinya?
DaveRGP
3
Saya telah berhasil menemukan perbaikan untuk masalah yang saya beli sebelumnya: pemesanan warna. gunakan formulir di scale_colour_manual("", values = c("TempMax" = "red", "TempMedia" = "green", "TempMin" = "blue"))mana TempMax, TempMedia, dan TempMin ditentukan sebagai argumen warna seperti pada jawaban di atas.
DaveRGP
@DaveRGP Mungkinkah itu dianggap sebagai bug ggplot?
Alessandro Jacopson
1
@StellaBiderman Terima kasih. Sangat menyenangkan mengetahui bahwa jawaban ini masih berguna (hampir) 5 tahun (!) Kemudian.
Brian Diggs
1
@BrianDiggs Anda tidak akan pernah tahu cara membuat acara ini menjadi titik dalam skala sebagai lawan dari garis kan?
Stella Biderman
2

Saya sangat menyukai solusi yang diusulkan oleh @Brian Diggs. Namun, dalam kasus saya, saya membuat plot garis dalam satu lingkaran daripada memberikannya secara eksplisit karena saya tidak tahu apriori berapa banyak plot yang akan saya miliki. Ketika saya mencoba untuk mengadaptasi kode @ Brian saya menghadapi beberapa masalah dengan penanganan warna dengan benar. Ternyata saya perlu memodifikasi fungsi estetika. Jika seseorang memiliki masalah yang sama, berikut adalah kode yang berfungsi untuk saya.

Saya menggunakan bingkai data yang sama dengan @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")  

Dalam kasus saya, saya menghasilkan my.colsdan my.namessecara dinamis, tetapi saya tidak ingin membuat hal-hal yang tidak perlu jadi saya berikan secara eksplisit di sini. Tiga garis ini membuat pemesanan legenda dan menetapkan warna lebih mudah.

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

Dan inilah plotnya:

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

masukkan deskripsi gambar di sini

Justyna
sumber
2
Pada kompleksitas ini, akan sangat mudah untuk hanya membentuk kembali data Anda ke dalam bentuk panjang yang ggplotdiharapkan.
Axeman
1
Saya tidak berpikir itu benar-benar menambah kompleksitas dibandingkan dengan jawaban asli yang diposting oleh @Brian. Selain itu, beberapa orang mungkin ingin melakukannya tanpa membentuk kembali data.
Justyna
... dan pendekatan ini memungkinkan geom yang berbeda (tipe plot) dengan variabel
mac