Trace dos gráficos en el mismo diagrama en R

572

Me gustaría trazar y1 e y2 en la misma trama.

x  <- seq(-2, 2, 0.05)
y1 <- pnorm(x)
y2 <- pnorm(x, 1, 1)
plot(x, y1, type = "l", col = "red")
plot(x, y2, type = "l", col = "green")

Pero cuando lo hago así, no se trazan en la misma trama juntos.

En Matlab se puede hacer hold on, pero ¿alguien sabe cómo hacer esto en R?

Sandra Schlichting
fuente
3
Echa un vistazo ?curve. Uso add=TRUE.
isomorphismes
Consulte esta pregunta para obtener respuestas más específicas de ggplot2.
Axeman

Respuestas:

618

lines()o points()se agregará al gráfico existente, pero no creará una nueva ventana. Entonces deberías hacer

plot(x,y1,type="l",col="red")
lines(x,y2,col="green")
bnaul
fuente
10
¿Por qué no funciona en el siguiente ejemplo simple? > plot (sin)> lines (cos) Error en as.double (y): no se puede forzar el tipo 'builtin' al vector del tipo 'double'
Frank
23
Esto es fácil de ver. Con plot (sin), está pasando una función en lugar de datos reales. plot () detectará esto y, a su vez, usar plot.function () para trazar su función (lea sobre el envío múltiple para obtener más información sobre esto). Sin embargo, lines.function () no está definido, por lo que lines () no sabe qué hacer con un parámetro de la función de clase. las líneas solo pueden tratar con sus datos y objetos de series temporales de la clase ts.
Soumendra
27
@Frank hacerlo de esta manera: plot(sin); curve(cos, add=TRUE).
isomorphismes
2
¿Cómo usar lo mismo si x es diferente? Digamos, tengo x1 e y1 para un gráfico y agrego otro gráfico de x2 e y2 en el mismo gráfico. Tanto x1 como x2 tienen el mismo rango pero valores diferentes.
Kavipriya
1
Es exactamente lo mismo: en lines(x2,y2,...)lugar delines(x,y2,...)
bnaul
220

También puede usar pary trazar en el mismo gráfico pero en diferentes ejes. Algo como sigue:

plot( x, y1, type="l", col="red" )
par(new=TRUE)
plot( x, y2, type="l", col="green" )

Si lees en detalle sobre parin R, podrás generar gráficos realmente interesantes. Otro libro para mirar es R Graphics de Paul Murrel.

Sam
fuente
3
Mi R me da un error: Error en el par (fig (new = TRUE)): no se pudo encontrar la función "fig"
Alessandro Jacopson
55
¿Su método preserva la escala correcta (eje y) para las dos parcelas?
Alessandro Jacopson
1
@uvts_cvs Sí, conserva el gráfico original en toto.
Sam
10
El problema con esto es que reescribirá varios elementos de la trama. Incluiría xlab="", ylab="", ...y algunos otros en el segundo plot.
isomorfismos
118

Al construir parcelas multicapa, uno debe considerar el ggplotpaquete. La idea es crear un objeto gráfico con una estética básica y mejorarlo gradualmente.

ggplotel estilo requiere que se empaqueten los datos data.frame.

# Data generation
x  <- seq(-2, 2, 0.05)
y1 <- pnorm(x)
y2 <- pnorm(x,1,1)
df <- data.frame(x,y1,y2)

Solución básica:

require(ggplot2)

ggplot(df, aes(x)) +                    # basic graphical object
  geom_line(aes(y=y1), colour="red") +  # first layer
  geom_line(aes(y=y2), colour="green")  # second layer

Aquí + operatorse usa para agregar capas adicionales al objeto básico.

Con ggplotusted tiene acceso a objetos gráficos en cada etapa del trazado. Digamos, la configuración habitual paso a paso puede verse así:

g <- ggplot(df, aes(x))
g <- g + geom_line(aes(y=y1), colour="red")
g <- g + geom_line(aes(y=y2), colour="green")
g

gproduce la trama, y ​​puede verla en cada etapa (bueno, después de crear al menos una capa). Otros encantamientos de la trama también se realizan con el objeto creado. Por ejemplo, podemos agregar etiquetas para ejes:

g <- g + ylab("Y") + xlab("X")
g

El final se gve así:

ingrese la descripción de la imagen aquí

ACTUALIZACIÓN (2013-11-08):

Como se señaló en los comentarios, ggplotla filosofía sugiere utilizar datos en formato largo. Puede consultar esta respuesta para ver el código correspondiente.

Redmode
fuente
55
Como sugiere Henrik , los datos realmente deberían estar en formato "largo", ggplotmaneja esto de forma más natural que el formato "ancho" que utiliza.
krlmlr
1
@Henrik: No, gracias por tu respuesta en primer lugar. Tal vez el autor de esta respuesta puede modificarlo para que se ajuste bien con ggplotla filosofía 's ...
krlmlr
1
@krlmlr, intenté editar mi respuesta para que aborde más explícitamente la pregunta. Por favor, siéntase libre de sugerir nuevas actualizaciones. Salud.
Henrik
3
me enseñó a definir x en ggplot (aes ()) y luego y por sí mismo en geom _ * (). ¡Agradable!
Dan
41

Creo que la respuesta que estás buscando es:

plot(first thing to plot)
plot(second thing to plot,add=TRUE)
usuario3749764
fuente
25
Esto no parece funcionar, da una "add" is not a graphical parameteradvertencia y luego imprime el segundo diagrama sobre el primero.
Waldir Leoncio
8
@WaldirLeoncio ver stackoverflow.com/questions/6789055/…
Alessandro Jacopson
Un buen beneficio de esto es que parece mantener consistentes los límites de los ejes y los títulos. Algunos de los métodos anteriores hacen que R dibuje dos conjuntos de marcas en el eje y, a menos que tenga problemas para especificar más opciones. No hace falta decir que tener dos conjuntos de marcas en los ejes podría ser muy engañoso.
RMurphy
1
el parámetro add funciona para algunos métodos de trazado, pero no el base / predeterminado en R
cloudscomputes
2
Tengo el mismo error "add" is not a graphical parameter. Mi R es R version 3.2.3 (2015-12-10). Puede usar el par(new=TRUE)comando entre estas parcelas.
quepas
29

Usa la matplotfunción:

matplot(x, cbind(y1,y2),type="l",col=c("red","green"),lty=c(1,1))

use esto si y1y y2se evalúan en los mismos xpuntos. Escala el eje Y para que se ajuste al que sea más grande ( y1o y2), a diferencia de algunas de las otras respuestas aquí que se recortarán y2si se hace más grande que y1(las soluciones de ggplot en su mayoría están bien con esto).

Alternativamente, y si las dos líneas no tienen las mismas coordenadas x, establezca los límites del eje en el primer diagrama y agregue:

x1  <- seq(-2, 2, 0.05)
x2  <- seq(-3, 3, 0.05)
y1 <- pnorm(x1)
y2 <- pnorm(x2,1,1)

plot(x1,y1,ylim=range(c(y1,y2)),xlim=range(c(x1,x2)), type="l",col="red")
lines(x2,y2,col="green")

Me sorprende que este Q tenga 4 años y nadie lo haya mencionado matploto x/ylim...

Hombre espacial
fuente
25

tl; dr: desea usar curve(con add=TRUE) o lines.


No estoy de acuerdo con par(new=TRUE)porque eso imprimirá dos marcas de graduación y etiquetas de eje. P.ej

seno y parábola

La salida de plot(sin); par(new=T); plot( function(x) x**2 ).

¡Mira lo desordenadas que están las etiquetas del eje vertical! Dado que los rangos son diferentes, necesitaría establecerlos ylim=c(lowest point between the two functions, highest point between the two functions), lo cual es menos fácil de lo que estoy a punto de mostrarle, y mucho menos fácil si desea agregar no solo dos curvas, sino muchas.


Lo que siempre me confundió acerca de trazar es la diferencia entre curvey lines. (Si no puede recordar que estos son los nombres de los dos comandos de trazado importantes, simplemente cántelo ).

Aquí está la gran diferencia entre curvey lines.

curvetrazará una función, como curve(sin). linesparcelas puntos con valores x e y, como: lines( x=0:10, y=sin(0:10) ).

Y aquí hay una pequeña diferencia: curvedebe llamarse con add=TRUElo que está tratando de hacer, mientras que linesya asume que está agregando a una trama existente.

id y seno

Aquí está el resultado de llamar plot(0:2); curve(sin).


Detrás de escena, echa un vistazo methods(plot). Y verifica body( plot.function )[[5]]. Cuando llamas a plot(sin)R, descubres que sines una función (no valores de y) y usa el plot.functionmétodo, que termina llamando curve. Así curvees la herramienta destinada a manejar funciones.

isomorfismos
fuente
17

Si desea dividir la trama en dos columnas (2 parcelas una al lado de la otra), puede hacerlo así:

par(mfrow=c(1,2))

plot(x)

plot(y) 

Link de referencia

Hamed2005
fuente
16

Según lo descrito por @redmode, puede trazar las dos líneas en el mismo dispositivo gráfico usando ggplot. En esa respuesta, los datos estaban en un formato 'ancho'. Sin embargo, cuando se usa ggplotgeneralmente es más conveniente mantener los datos en un marco de datos en un formato 'largo'. Luego, mediante el uso de diferentes 'variables de agrupación' en los aesargumentos de temas, las propiedades de la línea, como el tipo de línea o el color, variarán de acuerdo con la variable de agrupación, y aparecerán las leyendas correspondientes.

En este caso, podemos usar la colourestética, que hace coincidir el color de las líneas con diferentes niveles de una variable en el conjunto de datos (aquí: y1 vs y2). Pero primero necesitamos derretir los datos de formato ancho a largo, usando, por ejemplo, la función 'derretir' del reshape2paquete. Aquí se describen otros métodos para remodelar los datos: Reformar data.frame de formato ancho a largo .

library(ggplot2)
library(reshape2)

# original data in a 'wide' format
x  <- seq(-2, 2, 0.05)
y1 <- pnorm(x)
y2 <- pnorm(x, 1, 1)
df <- data.frame(x, y1, y2)

# melt the data to a long format
df2 <- melt(data = df, id.vars = "x")

# plot, using the aesthetics argument 'colour'
ggplot(data = df2, aes(x = x, y = value, colour = variable)) + geom_line()

ingrese la descripción de la imagen aquí

Henrik
fuente
15

Si está utilizando gráficos base (es decir, no gráficos de cuadrícula / cuadrícula), puede imitar la función de retención de MATLAB utilizando las funciones de puntos / líneas / polígonos para agregar detalles adicionales a sus gráficos sin comenzar un nuevo gráfico. En el caso de un diseño multiplot, puede usar par(mfg=...)para elegir a qué gráfico agregar cosas.

mcabral
fuente
14

Puede usar puntos para la sobreparcela, es decir.

plot(x1, y1,col='red')

points(x2,y2,col='blue')
idea genial
fuente
7

En lugar de mantener los valores que se trazarán en una matriz, almacénelos en una matriz. Por defecto, toda la matriz se tratará como un conjunto de datos. Sin embargo, si agrega la misma cantidad de modificadores al gráfico, por ejemplo, col (), ya que tiene filas en la matriz, R descubrirá que cada fila debe tratarse de forma independiente. Por ejemplo:

x = matrix( c(21,50,80,41), nrow=2 )
y = matrix( c(1,2,1,2), nrow=2 )
plot(x, y, col("red","blue")

Esto debería funcionar a menos que sus conjuntos de datos sean de diferentes tamaños.

arándano
fuente
Esto da: Error en if (as.factor) {: argumento no es interpretable como lógico
baouss
5

Idiomatic Matlab plot(x1,y1,x2,y2)se puede traducir en R con, ggplot2por ejemplo, de esta manera:

x1 <- seq(1,10,.2)
df1 <- data.frame(x=x1,y=log(x1),type="Log")
x2 <- seq(1,10)
df2 <- data.frame(x=x2,y=cumsum(1/x2),type="Harmonic")

df <- rbind(df1,df2)

library(ggplot2)
ggplot(df)+geom_line(aes(x,y,colour=type))

ingrese la descripción de la imagen aquí

Inspirado en los trazados de doble línea de Tingting Zhao con diferentes rangos de eje x con ggplot2 .

Alessandro Jacopson
fuente
5

Podría usar la ggplotly()función del paquete plotly para convertir cualquiera de los ejemplos de gggplot2 aquí en un diagrama interactivo, pero creo que este tipo de diagrama es mejor sin ggplot2 :

# call Plotly and enter username and key
library(plotly)
x  <- seq(-2, 2, 0.05)
y1 <- pnorm(x)
y2 <- pnorm(x, 1, 1)

plot_ly(x = x) %>%
  add_lines(y = y1, color = I("red"), name = "Red") %>%
  add_lines(y = y2, color = I("green"), name = "Green")

ingrese la descripción de la imagen aquí

Mateo Sanchez
fuente
tramadamente se ve brillante; es gratis ?
denis
@denis, hay una trama pública gratuita ilimitada y una trama privada pagada u opciones locales. Ver la página de planes .
Mateo Sánchez
44
El paquete plotly R ahora es 100% gratuito y de código abierto (licencia MIT). Puede usarlo con o sin una cuenta gráfica.
Carson el
4

También puede crear su trama usando ggvis :

library(ggvis)

x  <- seq(-2, 2, 0.05)
y1 <- pnorm(x)
y2 <- pnorm(x,1,1)
df <- data.frame(x, y1, y2)

df %>%
  ggvis(~x, ~y1, stroke := 'red') %>%
  layer_paths() %>%
  layer_paths(data = df, x = ~x, y = ~y2, stroke := 'blue')

Esto creará la siguiente trama:

ingrese la descripción de la imagen aquí

epo3
fuente
2

Usando plotly(agregando solución desde el plotlyeje y primario y secundario- Parece que falta):

library(plotly)     
x  <- seq(-2, 2, 0.05)
y1 <- pnorm(x)
y2 <- pnorm(x, 1, 1)

df=cbind.data.frame(x,y1,y2)

  plot_ly(df) %>%
    add_trace(x=~x,y=~y1,name = 'Line 1',type = 'scatter',mode = 'lines+markers',connectgaps = TRUE) %>%
    add_trace(x=~x,y=~y2,name = 'Line 2',type = 'scatter',mode = 'lines+markers',connectgaps = TRUE,yaxis = "y2") %>%
    layout(title = 'Title',
       xaxis = list(title = "X-axis title"),
       yaxis2 = list(side = 'right', overlaying = "y", title = 'secondary y axis', showgrid = FALSE, zeroline = FALSE))

Captura de pantalla de la demostración de trabajo:

ingrese la descripción de la imagen aquí

Saurabh Chauhan
fuente
Compilé el código y no funciona, primero marqué un error en%>% y lo eliminé, luego marqué un error Error in library(plotly) : there is no package called ‘plotly’¿por qué?
Bellatrix
¿Has instalado el paquete plotly? Necesita instalar el paquete usando el install.packages("plotly")comando.
Saurabh Chauhan
1

también podemos usar la biblioteca de celosía

library(lattice)
x <- seq(-2,2,0.05)
y1 <- pnorm(x)
y2 <- pnorm(x,1,1)
xyplot(y1 + y2 ~ x, ylab = "y1 and y2", type = "l", auto.key = list(points = FALSE,lines = TRUE))

Para colores específicos

xyplot(y1 + y2 ~ x,ylab = "y1 and y2", type = "l", auto.key = list(points = F,lines = T), par.settings = list(superpose.line = list(col = c("red","green"))))

ingrese la descripción de la imagen aquí

Varn K
fuente