Disegna più grafici su un grafico in R?


13

Usando il seguente codice, ho provato a disegnare quattro grafici su un grafico R. Non sono contento della figura perché c'è molto spazio tra i grafici, quindi la larghezza dei grafici non è sufficiente per analizzare i grafici.

  1. Qualcuno potrebbe aiutarmi a produrre un bel grafico con quattro grafici?

  2. Come posso mantenere le etichette dell'asse x da 1 a 10 anziché le 5 etichette predefinite?

Dati:

a1: 11.013 13.814 13.831 13.714 13.787 13.734 13.778 13.771 13.823 13.659

a2: 5.181 7.747 8.314 8.061 7.920 8.153 8.540 8.845 7.881 8.301

Ho usato i dati a1 per b1, c1 e d1; dati a2 per b2, c2 e d2 solo per qui.

Figura:

inserisci qui la descrizione dell'immagine

Codice:

        op=par(mfrow=c(4,1), mar=c(5.5,5.1,4.1,2.1))
        plot(a1, type="b", ylim=c(0,14.5), xlab="Time (secs)", ylab="", cex.axis=1.4, cex.lab=1.3,cex=1.2,lwd=2.5,col="red1",lty=2,pch=1, main="A")
        lines(a2,type="b",pch=3,lty=3,col="darkblue",lwd=2.5,cex=1.2)
        par(xpd=T)
        legend(1,26.5,c("X","Y"),bty="n",horiz=T,cex=1.5,col=c("red1","darkblue"),text.col=c("red1","darkblue"),pch=c(1,3),lty=c(2,3),x.intersp=0.4,adj=0.2)
        plot(b1, type="b", ylim=c(0,14.5), xlab="Time (secs)", ylab="", cex.axis=1.4, cex.lab=1.3,cex=1.2,lwd=2.5,col="red1",lty=2,pch=1, main="B")
        lines(b2,type="b",pch=3,lty=3,col="darkblue",lwd=2.5,cex=1.2)
        plot(c1, type="b", ylim=c(0,14.5), xlab="Time (secs)", ylab="", cex.axis=1.4, cex.lab=1.3,cex=1.2,lwd=2.5,col="red1",lty=2,pch=1, main="C")
        lines(c2,type="b",pch=3,lty=3,col="darkblue",lwd=2.5,cex=1.2)
        plot(d1/1000, type="b", ylim=c(0,14.5), xlab="Time (secs)", ylab="", cex.axis=1.4, cex.lab=1.3,cex=1.2,lwd=2.5,col="red1",lty=2,pch=1, main="D")
        lines(d2,type="b",pch=3,lty=3,col="darkblue",lwd=2.5,cex=1.2)
   > mtext("Price", side=2, at=100,line=3,cex=1.1)

1
potresti fornire i dettagli dei tuoi dati? possibilmente, dput (data_from_r)
suncoolsu

@suncoolsu, ho aggiornato la domanda con un campione di dati. Grazie.
samarasa,

E se avessi 2 colori e 4 tipi di linea sugli stessi assi con una legenda? Mi piacerebbe vedere il codice e i risultati per questo.
Paul,

@ user87: poiché 4 grafici provengono da 4 esperimenti diversi. Pertanto, penso che sia meglio tracciare 4 grafici per analizzare i risultati degli esperimenti.
samarasa,

@ user87, non sono sicuro di cosa intendi. Forse se avessi iniziato una nuova domanda qualcuno avrebbe risposto (lo farei :))
Brandon Bertelsen

Risposte:


16

Se vuoi attenersi a qualcosa di simile al metodo che hai usato, potresti voler imparare il comando layout (). Alcune altre modifiche ai dettagli e puoi avvicinare molto i grafici. Potresti anche mettere le cose uniche che cambiano tra i grafici in un elenco (come i dati e i margini) e poi passare attraverso un ciclo. Inoltre, noterai che ho creato l'asse inferiore con il comando asse diretto () in modo da poter controllare dove vanno gli oggetti.

layout(matrix(1:5, ncol = 1), widths = 1,
        heights = c(1,5,5,5,7), respect = FALSE)
par(mar=c(0, 4, 0, 0))
plot(1, type = 'n', axes = FALSE, bty = 'n', ylab = '')
legend('left', , c("X","Y"), bty="n", horiz=T, cex=1.5, col=c("red1","darkblue"), text.col=c("red1","darkblue"), pch=c(1,3), lty=c(2,3), x.intersp=0.4,adj=0.2)
par(mar=c(0, 4, 2, 1), bty = 'o')
plot(a1, type="b", ylim=c(0,14.5), xlab="Time (secs)", ylab="", xaxt = 'n', cex.axis=1.4, cex.lab=1.3,cex=1.2, lwd=2.5, col="red1", lty=2, pch=1, main="A")
lines(a2,type="b",pch=3,lty=3,col="darkblue",lwd=2.5,cex=1.2)
par(xpd=T)
plot(b1, type="b", ylim=c(0,14.5), xlab="Time (secs)", ylab="", xaxt = 'n', cex.axis=1.4, cex.lab=1.3,cex=1.2,lwd=2.5,col="red1",lty=2,pch=1, main="B")
lines(b2,type="b",pch=3,lty=3,col="darkblue",lwd=2.5,cex=1.2)
plot(c1, type="b", ylim=c(0,14.5), xlab="Time (secs)", ylab="", xaxt = 'n', cex.axis=1.4, cex.lab=1.3,cex=1.2,lwd=2.5,col="red1",lty=2,pch=1, main="C")
lines(c2,type="b",pch=3,lty=3,col="darkblue",lwd=2.5,cex=1.2)
par(mar=c(4, 4, 2, 1))
plot(d1/1000, type="b", ylim=c(0,14.5), xlab="Time (secs)", ylab="", xaxt = 'n', cex.axis=1.4, cex.lab=1.3,cex=1.2,lwd=2.5,col="red1",lty=2,pch=1, main="D")
lines(d2,type="b",pch=3,lty=3,col="darkblue",lwd=2.5,cex=1.2)
mtext("Price", side=2, at=40,line=2.5,cex=1.1)
axis(1, 1:10, cex.axis = 1.4)

la trama

Dovrei notare che non ho davvero fatto uno sforzo per renderlo il più bello possibile e invece di creare quel primo grafico fittizio avrei potuto solo impostare abbastanza spazio nel primo fotogramma. Sfortunatamente l'impostazione mar () tenta di riempire il riquadro e il margine superiore influenza la distanza in cui l'etichetta sopra il grafico è assente, quindi dovrei andare a creare tutte le mie etichette con mtext () o text () invece di usare semplicemente l'impostazione principale all'interno della trama e non mi andava di farlo


secondo il +1 per la grafica di base tosta. Ho provato invano a scrivere qualcosa di carino con il comando layout (). Tornerò qui la prossima volta che dovrò usarlo.
Chris Beeley,

13

Consiglierei di imparare il pacchetto grafico reticolare. Posso avvicinarmi a quello che vuoi con poche righe. Innanzitutto, impacchetta i tuoi dati in un frame di dati, in questo modo:

dat <- data.frame (x=rep (1:10, 8), y=c(a1, a2, b1, b2, c1, c2, d1, d2),
        var=factor (rep (c("X", "Y"), each=10)),
        graph=factor (rep (c("A", "B", "C", "D"), each=20)))

che produce:

    x           y var graph
1   1 0.556372979   X     A
2   2 0.754257646   X     A
3   3 0.815432905   X     A
4   4 0.559513013   X     A
5   5 0.763368168   X     A
6   6 0.426415259   X     A
7   7 0.597962532   X     A
8   8 0.723780143   X     A
9   9 0.228920116   X     A
10 10 0.607378894   X     A
11  1 0.865114425   Y     A
12  2 0.919804947   Y     A
13  3 0.437003794   Y     A
14  4 0.203349303   Y     A
15  5 0.620425977   Y     A
16  6 0.703170299   Y     A
17  7 0.174297656   Y     A
18  8 0.698144659   Y     A
19  9 0.732527016   Y     A
20 10 0.778057398   Y     A
21  1 0.355583032   X     B
22  2 0.015765144   X     B
23  3 0.315004753   X     B
24  4 0.257723585   X     B
25  5 0.506324279   X     B
26  6 0.028634427   X     B
27  7 0.475360443   X     B
28  8 0.577119754   X     B
29  9 0.709063777   X     B
30 10 0.308695235   X     B
31  1 0.852567748   Y     B
32  2 0.938889121   Y     B
33  3 0.080869739   Y     B
34  4 0.732318482   Y     B
35  5 0.325673156   Y     B
36  6 0.378161864   Y     B
37  7 0.830962248   Y     B
38  8 0.990504039   Y     B
39  9 0.331377188   Y     B
40 10 0.448251682   Y     B
41  1 0.967255983   X     C
42  2 0.722894624   X     C
43  3 0.039523960   X     C
44  4 0.003774719   X     C
45  5 0.218605160   X     C
46  6 0.722304874   X     C
47  7 0.576140686   X     C
48  8 0.108219812   X     C
49  9 0.258440127   X     C
50 10 0.739656846   X     C
51  1 0.528278201   Y     C
52  2 0.104415716   Y     C
53  3 0.966076056   Y     C
54  4 0.504415150   Y     C
55  5 0.655384900   Y     C
56  6 0.247340395   Y     C
57  7 0.193857228   Y     C
58  8 0.019133583   Y     C
59  9 0.799404908   Y     C
60 10 0.159209090   Y     C
61  1 0.422574508   X     D
62  2 0.823192614   X     D
63  3 0.808715876   X     D
64  4 0.770499188   X     D
65  5 0.049138399   X     D
66  6 0.747017767   X     D
67  7 0.239916970   X     D
68  8 0.152777362   X     D
69  9 0.052862276   X     D
70 10 0.937605577   X     D
71  1 0.850112019   Y     D
72  2 0.675407232   Y     D
73  3 0.273276166   Y     D
74  4 0.455995477   Y     D
75  5 0.695497498   Y     D
76  6 0.688414035   Y     D
77  7 0.454013633   Y     D
78  8 0.874853452   Y     D
79  9 0.568746031   Y     D

Quindi, usa il reticolo xyplot :

library (lattice)
xyplot (y ~ x | graph, groups=var, data=dat, type="o",
        layout=c(1, 4), as.table=T, xlab="Time (secs)", ylab="Price")

che produce un bel grafico come:

inserisci qui la descrizione dell'immagine

MODIFICARE:

Se vuoi avere simboli e linee diversi e mostrarli nella tua legenda, diventa complicato, perché letteralmente costruisci tu stesso la legenda e devi sapere come ottenere i colori reticolari predefiniti se non li hai ignorati da soli :

my.text <- levels (dat$var)
my.lty <- c(2, 3)
my.pch <- c(1, 2)
my.col <- trellis.par.get ("superpose.symbol")$col[1:2]
xyplot (y ~ x | graph, groups=var, data=dat, type="o", pch=my.pch, lty=my.lty,
        main="Main Title", layout=c(1, 4), as.table=T, xlab="Time (secs)", ylab="Price",
        key=list (columns=2, text=list (my.text), points=list (pch=my.pch, col=my.col)))

inserisci qui la descrizione dell'immagine

MODIFICA 2:

Puoi semplificare il codice e il grafico, se le due categorie sono davvero semplici come "X" e "Y":

xyplot (y ~ x | graph, groups=var, data=dat, type="o", pch=c("X", "Y"), cex=1.25, lty=c(2, 3),
        layout=c(1, 4), as.table=T, xlab="Time (secs)", ylab="Price")

che utilizzerà "X" e "Y" come simboli punto. Non hai bisogno di una legenda e puoi quindi dedicare ancora più spazio ai grafici stessi. (D'altra parte, potrebbe non piacerti l'aspetto o potresti trovare più difficile determinare il centro esatto del punto, anche se non è un problema tanto quanto potrebbe essere poiché la linea passa attraverso ogni punto.)

MODIFICA 3:

In realtà, dovresti aggiungere strip=F, strip.left=T,alla trama, per mettere le etichette A, B, C, D a sinistra dei grafici, che ti danno più spazio su un grafico lungo come questo:

xyplot (y ~ x | graph, groups=var, data=dat, type="o", pch=my.pch, lty=my.lty,
        main="Main Title", layout=c(1, 4), as.table=T, xlab="Time (secs)", ylab="Price",
        strip.left=T, strip=F,
        key=list (columns=2, text=list (my.text), points=list (pch=my.pch, col=my.col),
        lines=list (lty=my.lty, col=my.col)))

inserisci qui la descrizione dell'immagine


@Wayne: sto cercando di mantenere una legenda in cima al grafico usando auto.key con argomenti space = "top", pch = c (1,2), lty = c (2,4), ma i valori pch e lty valori non funzionano. Inoltre, vorrei mantenere X e Y orizzontali nella legenda. Potresti per favore aiutarmi per questo.
samarasa,

Sì. Devo usare valori di pch diversi per distinguere X e Y su un foglio. Sono in grado di utilizzare diversi valori pch nella trama aggiungendo l'argomento pch (1,4) a xyplot, ma non si sta riflettendo sulla legenda. Per favore fatemi sapere come posso usare diversi valori pch per X e Y nella legenda.
samarasa,

OK, l'ho capito una volta tornato a casa e ho consultato il libro. Dai un'occhiata alla versione modificata.
Wayne,

Nessun problema. Penso che il mio EDIT 3 ti offra il miglior grafico simile (ma più bello e con più spazio grafico rispetto) al tuo originale. Non ho spostato la leggenda, che penso sia abbastanza semplice. Se vuoi che la linea passi attraverso il punto della legenda, penso che dovresti portarla al livello di complessità successivo e fare cose di draw.key che creino grobs personalizzati (una gridcosa: reticolo e ggplot2 si basano sulla griglia) .
Wayne,

Sì, ora il grafico è migliore. Tuttavia, sarebbe davvero bello se ottenessimo il punto oltre la linea nella legenda come se ottenessimo con la normale funzione di trama.
samarasa,

9

Ecco una versione della ggplot2soluzione di @ Brandon che incorpora il comportamento legenda desiderato:

dat <- data.frame (x=rep (1:10, 8), y=runif(80),
        var=factor (rep (c("X", "Y"), each=10)),
        graph=factor (rep (c("A", "B", "C", "D"), each=20)))

ggplot(data = dat,aes(x = x, y = y)) + 
    facet_wrap(~graph,nrow = 4) + 
    geom_point(aes(shape = var)) + 
    geom_line(aes(colour = var, group = var)) + 
    labs(x = NULL, y = NULL, shape = "", colour = "") + 
    theme_bw() + 
    opts(legend.position = "top", legend.direction = "horizontal")

inserisci qui la descrizione dell'immagine

Trovo che le leggende siano molto più semplici ggplot2, ma YMMV.

MODIFICARE

Rispondere ad alcune domande nei commenti. Per specificare particolari tipi di punti o di linea, si potrebbe utilizzare scale_aesthetic_manualdove aestheticè o shape, linetypeecc Per esempio:

ggplot(data = dat,aes(x = x, y = y)) + 
    facet_wrap(~graph,nrow = 4) + 
    geom_point(aes(shape = var)) + 
    geom_line(aes(colour = var, linetype = var, group = var)) + 
    labs(x = NULL, y = NULL, shape = "", colour = "", linetype = "") + 
    scale_shape_manual(values = 4:5) +
    theme_bw() + 
    opts(legend.position = "top", legend.direction = "horizontal")

La modifica delle dimensioni delle varie etichette degli assi viene effettuata modificando le impostazioni nel tema, in genere utilizzando opts(). Per esempio:

ggplot(data = dat,aes(x = x, y = y)) + 
    facet_wrap(~graph,nrow = 4) + 
    geom_point(aes(shape = var)) + 
    geom_line(aes(colour = var, linetype = var, group = var)) + 
    labs(x = "X Label", y = "Y Label", shape = "", colour = "", linetype = "") + 
    theme_bw() + 
    opts(legend.position = "top", legend.direction = "horizontal",
         axis.text.x = theme_text(size = 15),axis.title.y = theme_text(size = 25, angle = 90))

Dovresti davvero immergerti nel sito Web e nel suo libro per ulteriori informazioni.


2
Preferisco spesso ggplot2. In effetti ho fatto un rapido tentativo con ggplot2 quando il reticolo stava diventando troppo complesso e ho scoperto che non avrei potuto far sì che la legenda riflettesse correttamente gli stili punto / linea se volevo scegliere esplicitamente forme e stili di linea. Probabilmente l'ho fatto nel modo sbagliato, ed è riuscito a funzionare nel grafico, ma ha ingannato la creazione della leggenda di ggplot. Potresti vedere se funziona per te e pubblicare il codice?
Wayne,

@Joran: ho provato a capire di cambiare i tipi di linea, i tipi di punta e i colori, ma senza successo. Potresti farci sapere come possiamo cambiare i tipi di linea, ecc. E per favore facci sapere come possiamo aumentare le dimensioni dei laboratori xey.
samarasa,

Sono al telefono al momento; se @Brandon non modifica la sua risposta prima di tornare a casa con quello che stai cercando, ci arriverò più tardi stasera.
joran,

8

Simile alla risposta di Wayne, utilizzerei anche un pacchetto diverso, vale a dire ggplot2

library(ggplot2) 

df <- data.frame(
parameter=runif(300),
Time=1:300,
split=sample(c(1:4),300,replace=T),
split2=sample(c(1:2),300,replace=T)
)

ggplot(df, aes(Time, parameter, colour=as.factor(split2))) + 
geom_line() + 
facet_wrap(~split,nrow=4)

Il che ci dà un grafico come:

inserisci qui la descrizione dell'immagine


1
Mi piacciono le griglie in ggplot, ma c'è un modo per disattivare lo sfondo grigio chiaro?
bluepole,

1
+ opts(panel.background=theme_blank())
Brandon Bertelsen,

1
Se si desidera apportare altre modifiche, è possibile digitare theme_get()per vedere cosa è possibile modificare. Quindi segui lo stesso schema del mio ultimo commento, impostandoli=theme_blank()
Brandon Bertelsen il

2
Stavo per fare ggplot2 da solo, ma pensavo che forse il reticolo sarebbe stato un passo più facile. Uno dei due fornisce un modo strutturato per impilare grafici come questo. Modificare molti dettagli potrebbe diventare difficile, ma ottenere rapidamente qualcosa di attraente e leggibile è facile. (Anche se devi avvolgere la testa creando il giusto frame di dati da cui rappresentare graficamente i dati, invece di buttare cose nel grafico.
Wayne,

Ho scoperto che Hadley ha fornito strumenti di manipolazione dei dati nei suoi altri pacchetti per massaggiare i dati nella giusta forma. In caso di dubbio la risposta è di solito,melt()
Brandon Bertelsen il
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.