Tracciare due variabili come linee usando ggplot2 sullo stesso grafico


305

Una domanda molto nuova, ma dire che ho dati come questo:

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

Come posso tracciare entrambe le serie temporali var0e var1sullo stesso grafico, con datesull'asse x, usando ggplot2? Punti bonus se crei var0e var1colori diversi e puoi includere una legenda!

Sono sicuro che questo è molto semplice, ma non riesco a trovare alcun esempio là fuori.

Risposte:


373

Per un numero limitato di variabili, puoi creare manualmente il grafico:

ggplot(test_data, aes(date)) + 
  geom_line(aes(y = var0, colour = "var0")) + 
  geom_line(aes(y = var1, colour = "var1"))

3
bell'esempio, ma come personalizzare i miei colori (es. nero e arancione)? perché sembra che tu stia usando colour=come nome della variabile.
Darwin PC

1
anche colour='var_names'come specificato da Hadley funziona benissimo. ma @DaveX - sarebbe più specifico se si desidera scegliere colori specifici anziché i colori selezionati automaticamente dalla funzione.
I_m_LeMarque il

Come posso aggiungere una legenda ad esso?
user1700890

361

L'approccio generale è di convertire i dati in formato lungo (usando melt()dal pacchetto reshapeo reshape2) o gather()/ pivot_longer()dal tidyrpacchetto:

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

uscita ggplot2

Vedi anche questa domanda sulla rimodulazione dei dati da ampia a lunga.


8
È inoltre possibile utilizzare la gather()funzione di tidyrpacchetto per fondere i dati:gather(test_data, variable, value, -date)
janosdivenyi

33

È necessario che i dati siano in formato "alto" anziché "largo" per ggplot2. "largo" significa avere un'osservazione per riga con ogni variabile come una colonna diversa (come hai fatto ora). Devi convertirlo in un formato "alto" in cui hai una colonna che ti dice il nome della variabile e un'altra colonna che ti dice il valore della variabile. Il processo di passaggio da largo ad alto è generalmente chiamato "fusione". È possibile utilizzare tidyr::gatherper sciogliere il frame di dati:

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

serie multiple ggplot2

Giusto per essere chiari dataciò che ggplotsta consumando dopo averlo convogliato via gatherè simile al seguente:

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

13

Utilizzando i tuoi dati:

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

Creo una versione in pila che è ciò con cui mi ggplot()piacerebbe lavorare:

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

In questo caso la produzione stackedera abbastanza facile come abbiamo solo dovuto fare un paio di manipolazioni, ma reshape()e l' reshapee reshape2potrebbe essere utile se si dispone di un vero e proprio set di dati più complessi da manipolare.

Una volta che i dati sono in questo modulo sovrapposto, è sufficiente una semplice ggplot()chiamata per produrre la trama desiderata con tutti gli extra (un motivo per cui pacchetti di livello superiore che piacciono latticee ggplot2sono così utili):

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

Lascerò a te per riordinare le etichette degli assi, il titolo della legenda ecc.

HTH


1
Penso che tu abbia dei genitori fuori posto nel tuo codice lassù. Penso che questo sia ciò che stai cercando: stacked <- con (test_data, data.frame (value = c (var0, var1), variabile = factor (rep (c ("Var0", "Var1"))), each = NROW (test_data), Dates = rep (date, 2))). Inoltre, qual è lo scopo della colonna "ciascuno"? E questo non è solo un modo più contorto e meno efficiente per fondere i dati come mostrato da rcs? Immagino di poter immaginare un'istanza in cui Melt non riuscirebbe a fare il lavoro, ma è quasi sicuramente lo strumento giusto per questo lavoro a meno che non mi manchi qualcosa?
Insegui il

1
@chase, scusa, è Emacs ESS che sbaglia il rientro. ognuno è un argomento rep(), quindi stiamo davvero ottenendo solo 3 punti stacked. Modificherò il codice per rendere più chiaro il rientro.
Gavin Simpson,

1
@inseguire; il tuo commento su melt()è ben ripreso e noto che il pacchetto reshape [2] sarebbe utile qui. Non ho molta familiarità con reshape2 e per una manipolazione così semplice farlo a mano è più complesso di una chiamata melt(), è stato meno sforzo in quanto non avevo bisogno di leggere come usare melt(). E rcs si intrufolò con la sua risposta mentre stavo producendo la mia; quando ho iniziato la risposta non c'erano state risposte. più di un modo per scuoiare un gatto - come si suol dire! ;-)
Gavin Simpson,

7

Sono anche nuovo di R ma sto cercando di capire come funziona ggplot, penso di avere un altro modo per farlo. Condivido probabilmente non come una soluzione perfetta completa, ma per aggiungere diversi punti di vista.

So che ggplot è progettato per funzionare meglio con i frame di dati, ma forse a volte può anche essere utile sapere che è possibile tracciare direttamente due vettori senza utilizzare un frame di dati.

Caricamento dati. La lunghezza del vettore della data originale è 100 mentre var0 e var1 hanno una lunghezza di 50, quindi tracciamo solo i dati disponibili (prime 50 date).

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)    

plotting

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

inserisci qui la descrizione dell'immagine

Tuttavia non sono stato in grado di aggiungere una legenda corretta utilizzando questo formato. Qualcuno sa come?


1
Questo aggiunge una leggenda 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,
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.