Trazar dos variables como líneas usando ggplot2 en el mismo gráfico

305

Una pregunta muy nueva, pero digamos que tengo datos como este:

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

¿Cómo puedo trazar tanto series de tiempo var0como var1en el mismo gráfico, con dateel eje x, usando ggplot2? Los puntos de bonificación si se hacen var0y var1diferentes colores y puede incluir una leyenda!

Estoy seguro de que esto es muy simple, pero no puedo encontrar ningún ejemplo por ahí.

fmark
fuente

Respuestas:

373

Para una pequeña cantidad de variables, puede construir el gráfico manualmente usted mismo:

ggplot(test_data, aes(date)) + 
  geom_line(aes(y = var0, colour = "var0")) + 
  geom_line(aes(y = var1, colour = "var1"))
Hadley
fuente
3
buen ejemplo, pero ¿cómo personalizar mis propios colores (por ejemplo, negro y naranja) ?, porque parece que lo estás usando colour=como el nombre de la variable.
Darwin PC
1
incluso colour='var_names'según lo especificado por hadley funciona bien. pero @DaveX: sería más específico si se desea elegir colores específicos en lugar de colores seleccionados automáticamente por la función.
I_m_LeMarque
¿Cómo puedo agregarle una leyenda?
user1700890
361

El enfoque general es convertir los datos a formato largo (usando melt()desde el paquete reshapeo reshape2) o gather()/ pivot_longer()desde el tidyrpaquete:

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

salida ggplot2

También vea esta pregunta sobre la remodelación de datos de ancho a largo.

rcs
fuente
8
También puede usar la gather()función de tidyrpaquete para derretir los datos:gather(test_data, variable, value, -date)
janosdivenyi
33

Necesita que los datos estén en formato "alto" en lugar de "ancho" para ggplot2. "ancho" significa tener una observación por fila con cada variable como una columna diferente (como lo tiene ahora). Debe convertirlo a un formato "alto" donde tenga una columna que le indique el nombre de la variable y otra columna que le indique el valor de la variable. El proceso de pasar de ancho a alto generalmente se llama "derretimiento". Puede usar tidyr::gatherpara derretir su marco de datos:

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 múltiple ggplot2

Para que quede claro, lo dataque ggplotestá consumiendo después de conectarlo se gatherve así:

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
RubenLaguna
fuente
13

Usando sus datos:

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 versión apilada con la que me ggplot()gustaría trabajar:

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

En este caso, la producción stackedfue muy fácil ya que sólo tuvimos que hacer un par de manipulaciones, pero reshape()y el reshapey reshape2podría ser útil si usted tiene un conjunto de datos reales más compleja de manipular.

Una vez que los datos están en esta forma apilada, solo se requiere una simple ggplot()llamada para producir la trama que desea con todos los extras (una razón por la cual los paquetes de trama de alto nivel les gustan latticey ggplot2son tan útiles):

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

Te dejaré que arregles las etiquetas de los ejes, el título de la leyenda, etc.

HTH

Gavin Simpson
fuente
1
Creo que tienes un parens fuera de lugar en tu código allí arriba. Creo que esto es lo que busca: apilado <- con (test_data, data.frame (value = c (var0, var1), variable = factor (rep (c ("Var0", "Var1"))), each = NROW (test_data), Fechas = rep (fecha, 2))). Además, ¿cuál es el propósito de la columna "cada"? ¿Y no es esta una forma más enrevesada y menos eficiente de fundir los datos como se muestra por rcs? Supongo que podría imaginar una instancia en la que derretir no hiciera el trabajo, pero es casi seguro que sea la herramienta adecuada para este trabajo a menos que me falte algo.
Chase
1
@chase, lo siento, ese es Emacs ESS que está haciendo una sangría incorrecta. cada uno es un argumento rep(), por lo que realmente solo estamos obteniendo 3 cols stacked. Editaré el código para aclarar la sangría.
Gavin Simpson el
1
@persecución; su comentario sobre melt()está bien tomado, y noto que el paquete reshape [2] sería útil aquí. No estoy tan familiarizado con reshape2 y para una manipulación tan simple hacerlo a mano es más complejo que una llamada melt(), fue menos esfuerzo ya que no necesitaba leer cómo usarlo melt(). Y RCS se coló con su respuesta mientras yo producía la mía; cuando comencé la respuesta no había habido respuestas. más de una forma de pelar un gato, como dicen. ;-)
Gavin Simpson
7

También soy nuevo en R, pero al tratar de entender cómo funciona ggplot, creo que tengo otra forma de hacerlo. Probablemente comparto probablemente no como una solución perfecta completa sino para agregar algunos puntos de vista diferentes.

Sé que ggplot está diseñado para funcionar mejor con los marcos de datos, pero tal vez a veces también sea útil saber que puedes trazar directamente dos vectores sin usar un marco de datos.

Cargando datos. La longitud del vector de fecha original es 100, mientras que var0 y var1 tienen una longitud de 50, por lo que solo trazo los datos disponibles (primeras 50 fechas).

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)    

Graficado

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

ingrese la descripción de la imagen aquí

Sin embargo, no pude agregar una leyenda correcta usando este formato. ¿Alguien sabe cómo?

Papalagui
fuente
1
Esto agrega una leyenda 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 el