Come impilare verticalmente due grafici con la stessa scala x, ma una scala y diversa in R?


9

Saluti,

Attualmente sto facendo quanto segue in R:

require(zoo)
data <- read.csv(file="summary.csv",sep=",",head=TRUE)
cum  = zoo(data$dcomp, as.Date(data$date))
data = zoo(data$compressed, as.Date(data$date))
data <- aggregate(data, identity, tail, 1)
cum  <- aggregate(cum, identity, sum, 1)
days = seq(start(data), end(data), "day")
data2 = na.locf(merge(data, zoo(,days)))

plot(data2,xlab='',ylab='compressed bytes',col=rgb(0.18,0.34,0.55))
lines(cum,type="h",col=rgb(0,0.5,0))

Snip di summary.csv:

date,revision,file,lines,nclass,nattr,nrel,bytes,compressed,diff,dcomp
2007-07-25,16,model.xml,96,11,22,5,4035,991,0,0
2007-07-27,17,model.xml,115,16,26,6,4740,1056,53,777
2007-08-09,18,model.xml,106,16,26,7,4966,1136,47,761
2007-08-10,19,model.xml,106,16,26,7,4968,1150,4,202
2007-09-06,81,model.xml,111,16,26,7,5110,1167,13,258
...

Le ultime due righe tracciano le informazioni di cui ho bisogno e il risultato è simile al seguente: testo alternativo La linea blu è l'entropia in byte del manufatto che mi interessa. Le linee verdi rappresentano l'entropia dei cambiamenti.

Ora, in questo grafico, funziona bene perché non c'è un'enorme differenza nelle scale. Ma ho altri grafici in cui le linee verdi diventano così piccole che non si possono vedere.

La soluzione che cercavo riguardava due cose:

  1. Per spostare le linee verticali verdi su un secondo grafico, appena sotto il primo, con il proprio asse y, ma con l'asse x condiviso.
  2. Per fornirgli una scala logaritmica, poiché sono più interessato alla "grandezza", che ai valori specifici.

Grazie in anticipo!

PS Se qualcuno può anche dirmi come posso inserire "tick minori" nella scala x riferita ai mesi, apprezzo :-) Se queste sono troppe domande per un singolo post, posso dividerle ulteriormente.

Risposte:


15

Puoi usare par(new=TRUE)per tracciare nello stesso grafico usando due diversi assi y! Questo dovrebbe anche risolvere il tuo problema.

Successivamente troverai un semplice esempio che traccia due variabili normali casuali, una sulla media 0 e l'altra sulla media 100 (entrambe sd s = 1) nella stessa trama. Il primo in rosso sull'asse y sinistro, il secondo in blu sull'asse y destro. Quindi, vengono aggiunte le etichette degli assi.

Ecco qui:

x <- 1:10
y1 <- rnorm(10)
y2 <- rnorm(10)+100

plot(x,y1,pch=0,type="b",col="red",yaxt="n",ylim=c(-8,2))
par(new=TRUE)
plot(x,y2,pch=1,type="b",col="blue",yaxt="n",ylim=c(98,105))

axis(side=2)
axis(side=4)

assomiglia quindi a questo (ricorda il rosso sull'asse sinistro, il blu sull'asse destro): testo alternativo

AGGIORNAMENTO:
Sulla base dei commenti ho prodotto una versione aggiornata del mio grafico. Ora scavo un po 'più a fondo nella funzionalità del grafico di base usando par(mar=c(a,b,c,d))per creare un margine più grande attorno al grafico (necessario per l'etichetta dell'asse destro), mtextper mostrare le etichette degli assi e e l'uso avanzato della axisfunzione:

x <- 1:100
y1 <- rnorm(100)
y2 <- rnorm(100)+100

par(mar=c(5,5,5,5))

plot(x,y1,pch=0,type="b",col="red",yaxt="n",ylim=c(-8,2),ylab="")
axis(side=2, at=c(-2,0,2))
mtext("red line", side = 2, line=2.5, at=0)

par(new=TRUE)
plot(x,y2,pch=1,type="b",col="blue",yaxt="n",ylim=c(98,108), ylab="")
axis(side=4, at=c(98,100,102), labels=c("98%","100%","102%"))
mtext("blue line", side=4, line=2.5, at=100)

testo alternativo

Come vedi è abbastanza semplice. È possibile definire la posizione dei dati con ylimnella plotfunzione, quindi utilizzare atnella axisfunzione per selezionare gli assi che si desidera visualizzare. Inoltre, puoi anche fornire le etichette per i tick dell'asse (abbastanza utile per l'asse x nominale) tramite labelsla axisfunzione (fatta qui sull'asse destro). Per aggiungere etichette degli assi, utilizzare mtextcon atper il posizionamento verticale ( lineper il posizionamento orizzontale).

Assicurati di controllare ?plot, ?par, ?axis, e ?mtextper ulteriori informazioni.
Grandi risorse Web sono: Quick-R per grafici: 1 , 2 e 3 .


È interessante, ma come possiamo dire al lettore quale scala corrisponde a quale linea?
Hugo Sereno Ferreira,

Dai un'occhiata a questo grafico: imgur.com/K8BCr.png Qui presentiamo etichette e segni di spunta sull'asse y solo dove si applicano ai dati (ovvero, per l'asse sinistro nella parte superiore del grafico, come dati corrispondenti, e per l'asse destro nella parte inferiore del grafico, come i dati di ricodifica). Inoltre abbiamo usato diversi colori (come nell'esempio sopra) e tipi di linea e l'abbiamo spiegato nella didascalia. È inoltre possibile utilizzare un grafico a linee a sinistra e un grafico a barre sull'asse destro per rendere più chiara la distinzione.
Henrik,

L'esempio che hai dato è molto buono ... Come sei riuscito a scostare verticalmente ogni asse?
Hugo Sereno Ferreira,

2
Davvero un buon esempio. L'unico problema con il tuo grafico è che entrambi i nomi delle variabili Y si sovrappongono. In questo caso ne vorresti uno a sinistra e l'altro a destra (possibilmente anche in posizione verticale). Per aggiornare il tuo esempio da "davvero buono" a "perfetto", potresti voler usare la funzione mtext da R per fare i nomi delle variabili
Dave Kellen,

@Hugo @Dave: vedi il mio aggiornamento per l'incorporazione di entrambi i commenti.
Henrik,

12

Penso che tu possa ottenere quello che vuoi usando ggplot2. Utilizzando il codice qui sotto, posso produrre:

testo alternativo

Ovviamente cose come i colori delle linee possono essere cambiate in qualsiasi cosa tu voglia. Sull'asse x ho specificato le linee principali su anni e le linee minori su mesi.

require(ggplot2)
t = as.Date(0:1000, origin="2008-01-01")  
y1 = rexp(1001)
y2 = cumsum(y1)
df = data.frame(t=t, values=c(y2,y1), type=rep(c("Bytes", "Changes"), each=1001))

g = ggplot(data=df, aes(x=t, y=values)) +
  geom_line() +
  facet_grid(type ~ ., scales="free") +
  scale_y_continuous(trans="log10") +
  scale_x_date(major="years", minor="months") +
  ylab("Log values")
g

Ho provato a configurare df = data.frame (t = giorni, valori = c (data2, cum), tipo = rep (c ("Byte", "Modifiche"), ciascuno = 1001)), ma dà un Errore in rbind.zoo (...): gli indici si sovrappongono
Hugo Sereno Ferreira,

Questo perché data2 e cum sono oggetti zoo. Utilizzare as.vector (data2) per ottenere i valori non elaborati. Inoltre, ho usato 1001 perché avevo 1001 osservazioni. Avrai bisogno di qualcosa di diverso.
csgillespie,

Utente Noob R qui: errore in data.frame (t = giorni, valori = c (as.vector (data2), as.vector (cum)),: gli argomenti implicano un numero diverso di righe: 1063, 1300, 2
Hugo Sereno Ferreira,

Digita "giorni", "data2" e "cum" per esaminare i tuoi dati. Quindi guarda "lunghezza (giorni)", ecc. Devi abbinare i punti temporali con i valori.
csgillespie,
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.