Merencanakan dua variabel sebagai garis menggunakan ggplot2 pada grafik yang sama

305

Pertanyaan yang sangat baru, tetapi katakan saya memiliki data seperti ini:

test_data <-
  data.frame(
    var0 = 100 + c(0, cumsum(runif(49, -20, 20))),
    var1 = 150 + c(0, cumsum(runif(49, -10, 10))),
    date = seq(as.Date("2002-01-01"), by="1 month", length.out=100)
  )

Bagaimana saya bisa memplot deret waktu var0dan var1grafik yang sama, dengan datesumbu x, gunakan ggplot2? Poin bonus jika Anda membuat var0dan var1warna yang berbeda, dan dapat menyertakan legenda!

Saya yakin ini sangat sederhana, tetapi saya tidak dapat menemukan contoh di luar sana.

fmark
sumber

Jawaban:

373

Untuk sejumlah kecil variabel, Anda dapat membuat plot sendiri secara manual:

ggplot(test_data, aes(date)) + 
  geom_line(aes(y = var0, colour = "var0")) + 
  geom_line(aes(y = var1, colour = "var1"))
Hadley
sumber
3
contoh yang bagus, tetapi bagaimana cara menyesuaikan warna saya sendiri (Misalnya hitam dan oranye) ?, karena sepertinya Anda menggunakan colour=sebagai nama variabel.
Darwin PC
1
bahkan colour='var_names'seperti yang ditentukan oleh hadley berfungsi dengan baik. tetapi @DaveX - akan lebih spesifik jika seseorang ingin memilih warna tertentu daripada warna yang dipilih secara otomatis oleh fungsi.
I_m_LeMarque
Bagaimana saya bisa menambahkan legenda ke dalamnya?
user1700890
361

Pendekatan umum adalah untuk mengkonversi data ke format panjang (menggunakan melt()dari paket reshapeatau reshape2) atau gather()/ pivot_longer()dari tidyrpaket:

library("reshape2")
library("ggplot2")

test_data_long <- melt(test_data, id="date")  # convert to long format

ggplot(data=test_data_long,
       aes(x=date, y=value, colour=variable)) +
       geom_line()

keluaran ggplot2

Lihat juga pertanyaan ini tentang membentuk kembali data dari lebar ke panjang.

rcs
sumber
8
Anda juga dapat menggunakan gather()fungsi tidyrpaket untuk melelehkan data:gather(test_data, variable, value, -date)
janosdivenyi
33

Anda membutuhkan data dalam format "tinggi" alih-alih "lebar" untuk ggplot2. "lebar" berarti memiliki pengamatan per baris dengan setiap variabel sebagai kolom yang berbeda (seperti yang Anda miliki sekarang). Anda perlu mengonversinya menjadi format "tinggi" di mana Anda memiliki kolom yang memberi tahu Anda nama variabel dan kolom lain yang memberi tahu Anda nilai variabel. Proses perpindahan dari lebar ke tinggi biasanya disebut "melting". Anda dapat menggunakan tidyr::gatheruntuk melelehkan frame data Anda:

library(ggplot2)
library(tidyr)

test_data <-
  data.frame(
    var0 = 100 + c(0, cumsum(runif(49, -20, 20))),
    var1 = 150 + c(0, cumsum(runif(49, -10, 10))),
    date = seq(as.Date("2002-01-01"), by="1 month", length.out=100)
  )
test_data %>%
    gather(key,value, var0, var1) %>%
    ggplot(aes(x=date, y=value, colour=key)) +
    geom_line()

beberapa seri ggplot2

Hanya untuk memperjelas databahwa ggplotyang dikonsumsi setelah memipisnya melalui gathertampak seperti ini:

date        key     value
2002-01-01  var0    100.00000
2002-02-01  var0    115.16388 
...
2007-11-01  var1    114.86302
2007-12-01  var1    119.30996
RubenLaguna
sumber
13

Menggunakan data Anda:

test_data <- data.frame(
var0 = 100 + c(0, cumsum(runif(49, -20, 20))),
var1 = 150 + c(0, cumsum(runif(49, -10, 10))),
Dates = seq.Date(as.Date("2002-01-01"), by="1 month", length.out=100))

Saya membuat versi bertumpuk yang ggplot()ingin saya gunakan:

stacked <- with(test_data,
                data.frame(value = c(var0, var1),
                           variable = factor(rep(c("Var0","Var1"),
                                                 each = NROW(test_data))),
                           Dates = rep(Dates, 2)))

Dalam hal ini memproduksi stackedcukup mudah karena kami hanya perlu melakukan beberapa manipulasi, tetapi reshape()dan reshapedan reshape2mungkin berguna jika Anda memiliki set data nyata yang lebih kompleks untuk dimanipulasi.

Setelah data berada dalam formulir yang ditumpuk ini, itu hanya membutuhkan ggplot()panggilan sederhana untuk menghasilkan plot yang Anda inginkan dengan semua tambahan (satu alasan mengapa paket merencanakan tingkat yang lebih tinggi suka latticedan ggplot2sangat berguna):

require(ggplot2)
p <- ggplot(stacked, aes(Dates, value, colour = variable))
p + geom_line()

Saya akan menyerahkan kepada Anda untuk merapikan label sumbu, judul legenda dll.

HTH

Gavin Simpson
sumber
1
Saya pikir Anda memiliki parens yang salah tempat dalam kode Anda di sana. Saya pikir ini adalah apa yang Anda cari: ditumpuk <- dengan (test_data, data.frame (nilai = c (var0, var1), variabel = faktor (rep (c ("Var0", "Var1"))), masing-masing = NROW (test_data), Tanggal = rep (tanggal, 2))). Juga, apa tujuan kolom "masing-masing"? Dan bukankah ini hanya cara yang lebih berbelit-belit dan kurang efisien untuk mencairkan data seperti yang ditunjukkan oleh rcs? Saya kira saya bisa membayangkan sebuah contoh di mana lelehan tidak akan menyelesaikan pekerjaan, tetapi hampir pasti alat yang tepat untuk pekerjaan ini kecuali saya kehilangan sesuatu?
Mengejar
1
@ chase, maaf, itu salah Emacs ESS membuat indentasi salah. masing-masing adalah argumen untuk rep(), jadi kami benar-benar hanya mendapatkan 3 cols stacked. Saya akan mengedit kode untuk membuat indentasi lebih jelas.
Gavin Simpson
1
@mengejar; komentar Anda tentang melt()diambil dengan baik, dan saya perhatikan bahwa paket membentuk kembali [2] akan berguna di sini. Saya tidak begitu terbiasa dengan membentuk kembali dan untuk manipulasi sederhana melakukannya dengan tangan lebih kompleks daripada panggilan melt(), itu kurang usaha karena saya tidak perlu membaca cara menggunakan melt(). Dan rcs menyelinap masuk dengan jawabannya sementara saya menghasilkan milik saya; ketika saya memulai balasan, tidak ada jawaban. lebih dari satu cara menguliti kucing - seperti yang mereka katakan! ;-)
Gavin Simpson
7

Saya juga baru mengenal R tetapi mencoba memahami cara kerja ggplot, saya pikir saya punya cara lain untuk melakukannya. Saya hanya berbagi mungkin bukan sebagai solusi sempurna yang lengkap tetapi untuk menambahkan beberapa sudut pandang yang berbeda.

Saya tahu ggplot dibuat untuk bekerja dengan kerangka data yang lebih baik, tetapi mungkin juga bermanfaat untuk mengetahui bahwa Anda dapat langsung memplot dua vektor tanpa menggunakan kerangka data.

Memuat data. Panjang vektor tanggal asli adalah 100 sedangkan var0 dan var1 memiliki panjang 50 jadi saya hanya memplot data yang tersedia (50 tanggal pertama).

var0 <- 100 + c(0, cumsum(runif(49, -20, 20)))
var1 <- 150 + c(0, cumsum(runif(49, -10, 10)))
date <- seq(as.Date("2002-01-01"), by="1 month", length.out=50)    

Merencanakan

ggplot() + geom_line(aes(x=date,y=var0),color='red') + 
           geom_line(aes(x=date,y=var1),color='blue') + 
           ylab('Values')+xlab('date')

masukkan deskripsi gambar di sini

Namun saya tidak dapat menambahkan legenda yang benar menggunakan format ini. Adakah yang tahu bagaimana caranya?

Papalagui
sumber
1
Ini menambah legenda ggplot() + geom_line(aes(x=date,y=var0, group=1, colour = 'red')) + geom_line(aes(x=date,y=var1, group = 2, colour = 'blue')) + ylab('Values')+xlab('date')
flurbius