¿Dibujar varias parcelas en una gráfica en R?

13

Usando el siguiente código, intenté dibujar cuatro parcelas en un gráfico R. No estoy contento con la figura porque hay mucho espacio entre las parcelas, por lo tanto, el ancho de las parcelas no es suficiente para analizarlas.

  1. ¿Podría alguien ayudarme a producir un buen gráfico que tenga cuatro parcelas?

  2. ¿Cómo puedo mantener las etiquetas del eje x del 1 al 10 en lugar de las 5 etiquetas predeterminadas?

Datos:

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

He usado datos de a1 para b1, c1 y d1; datos de a2 para b2, c2 y d2 solo por aquí.

Figura:

ingrese la descripción de la imagen aquí

Código:

        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)
samarasa
fuente
1
¿podría dar los detalles de sus datos? posiblemente, dput (data_from_r)
suncoolsu
@suncoolsu, he actualizado la pregunta con una muestra de datos. Gracias.
samarasa
¿Qué pasaría si tuviera 2 colores y 4 tipos de línea en los mismos ejes con una leyenda? Me gustaría ver el código y los resultados para eso.
Paul
@ user87: Dado que 4 parcelas son de 4 experimentos diferentes. Por lo tanto, creo que es mejor dibujar 4 parcelas para analizar los resultados de los experimentos.
samarasa
@ user87, no estoy seguro de lo que quieres decir. Quizás si comenzaras una nueva pregunta, alguien la respondería (yo lo haría :))
Brandon Bertelsen

Respuestas:

16

Si desea seguir con algo como el método que ha estado utilizando, puede aprender el comando layout (). Algunos otros cambios detallados y puede obtener los gráficos mucho más juntos. También podría poner las cosas únicas que cambian entre los gráficos en una lista (como los datos y los márgenes) y luego pasar por un bucle. Además, notará que hice el eje inferior con el comando axis () directo para que pueda controlar dónde van los elementos.

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

Debo señalar que realmente no me esforcé por hacer esto lo más agradable posible y en lugar de hacer ese primer gráfico ficticio, podría haber establecido suficiente espacio en el primer fotograma. Desafortunadamente, la configuración mar () intenta llenar el marco y el margen superior influye en la distancia a la que está lejos la etiqueta sobre el gráfico, por lo que tendría que ir y hacer todas mis etiquetas con mtext () o text () en lugar de simplemente usar la configuración principal dentro de la trama y no tenía ganas de hacerlo

John
fuente
segundo el +1 para gráficos base rudos. Intenté en vano escribir algo bueno con el comando layout (). Volveré aquí la próxima vez que necesite usarlo.
Chris Beeley
13

Recomendaría aprender el paquete de gráficos de celosía. Puedo acercarme a lo que quieres con unas pocas líneas. Primero, empaquete sus datos en un marco de datos, algo como esto:

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

cuyos rendimientos:

    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

Luego, usa la red 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")

que produce un buen gráfico como:

ingrese la descripción de la imagen aquí

EDITAR:

Si desea tener diferentes símbolos y líneas y que aparezcan en su leyenda, se complica, porque literalmente construye la leyenda usted mismo y tiene que saber cómo obtener los colores de red predeterminados si no los anuló usted mismo :

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

ingrese la descripción de la imagen aquí

EDITAR 2:

Puede simplificar el código y el gráfico, si las dos categorías realmente son tan simples como "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")

que usará "X" e "Y" como símbolos de puntos. No necesita una leyenda en absoluto, y luego puede dedicar aún más espacio a los gráficos en sí. (Por otro lado, es posible que no le guste el aspecto, o que le resulte más difícil determinar el centro exacto del punto, aunque eso no es un problema tan importante como podría ser, ya que la línea pasa por cada punto).

EDITAR 3:

En realidad, debe agregar strip=F, strip.left=T,al gráfico, para colocar las etiquetas A, B, C, D, a la izquierda de los gráficos, lo que le da más espacio en un gráfico largo como este:

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

ingrese la descripción de la imagen aquí

Wayne
fuente
@Wayne: Estoy tratando de mantener una leyenda en la parte superior del gráfico usando auto.key con space = "top", pch = c (1,2), lty = c (2,4) argumentos, pero los valores de pch y Los valores de lty no funcionan. Además, me gustaría mantener las X e Y como horizontales en la leyenda. ¿Podrías ayudarme por favor?
samarasa
Si. Necesito usar diferentes valores de pch para distinguir X e Y en un papel. Puedo usar diferentes valores de pch en la gráfica agregando el argumento pch (1,4) a xyplot, pero no se refleja en la leyenda. Avíseme cómo puedo usar diferentes valores de pch para X e Y en la leyenda.
samarasa
Bien, lo descubrí una vez que llegué a casa y consulté el libro. Mira la versión editada.
Wayne
No hay problema. Creo que mi EDIT 3 le ofrece el mejor gráfico que es similar (pero más atractivo y con más espacio gráfico) que su original. No moví la leyenda, lo que creo que es bastante sencillo. Si desea que la línea pase por el punto de la leyenda, creo que debería llevarla al siguiente nivel de complejidad y hacer cosas de draw.key que crean grobs personalizados ( gridalgo: celosía y ggplot2 construidos en la cuadrícula) .
Wayne
Sí, ahora el gráfico es mejor. Sin embargo, sería realmente bueno si obtenemos el punto sobre la línea en la leyenda como lo hacemos con la función de trazado normal.
samarasa
9

Aquí hay una versión de la ggplot2solución de @ Brandon que incorpora el comportamiento de leyenda deseado:

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

ingrese la descripción de la imagen aquí

Encuentro que las leyendas son mucho más fáciles ggplot2, pero YMMV.

EDITAR

Abordando algunas preguntas en los comentarios. Para especificar determinados tipos de puntos o de líneas, utilizaría scale_aesthetic_manualdonde aesthetices o bien shape, linetype, etc. Por ejemplo:

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

El cambio del tamaño de varias etiquetas de eje se realiza cambiando la configuración en el tema, generalmente usando opts(). Por ejemplo:

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

Realmente deberías sumergirte en el sitio web y su libro para obtener más información.

joran
fuente
2
A menudo prefiero ggplot2. De hecho, intenté rápidamente con ggplot2 cuando la red se estaba volviendo demasiado compleja, y descubrí que no podía lograr que la leyenda reflejara correctamente los estilos de punto / línea si quisiera elegir formas y estilos de línea explícitamente. Probablemente lo hice de la manera incorrecta y logré trabajar en el gráfico, pero engañé la creación de la leyenda de ggplot. ¿Podría ver si funciona para usted y publicar el código?
Wayne
@Joran: Traté de descifrar para cambiar los tipos de línea y de punto, y los colores, pero no tuve éxito. ¿Podría decirnos cómo podemos cambiar los tipos de línea, etc.? Y también, ¿cómo podemos aumentar el tamaño de los laboratorios x e y?
samarasa
Estoy en mi teléfono en este momento; Si @Brandon no edita su respuesta antes de que llegue a casa con lo que estás buscando, lo haré más tarde esta noche.
joran
8

Similar a la respuesta de Wayne, también usaría un paquete diferente, a saber 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)

Lo que nos da un cuadro como:

ingrese la descripción de la imagen aquí

Brandon Bertelsen
fuente
1
Me gustan las cuadrículas en ggplot, pero ¿hay alguna manera de desactivar el fondo gris claro?
bluepole
1
+ opts(panel.background=theme_blank())
Brandon Bertelsen
1
Si desea realizar otros cambios, puede escribir theme_get()para ver qué puede cambiar. Luego siga el mismo patrón que mi último comentario, configurándolos=theme_blank()
Brandon Bertelsen
2
Iba a hacer ggplot2 yo mismo, pero pensé que tal vez el enrejado sería un paso más fácil. Cualquiera de los dos proporciona una forma estructurada para apilar gráficos como este. Ajustar muchos detalles puede ser difícil, pero obtener algo atractivo y legible rápidamente es fácil. (Aunque tiene que pensar en crear el marco de datos correcto desde el cual graficar los datos, en lugar de simplemente arrojar cosas al gráfico.
Wayne
Descubrí que Hadley ha proporcionado herramientas de manipulación de datos en sus otros paquetes para masajear los datos en la forma correcta. En caso de duda, la respuesta suele sermelt()
Brandon Bertelsen