Tracer deux variables sous forme de lignes à l'aide de ggplot2 sur le même graphique

305

Une question très nouvelle, mais disons que j'ai des données comme celle-ci:

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

Comment puis-je tracer les deux séries chronologiques var0et var1sur le même graphique, avec datesur l'axe des x, en utilisant ggplot2? Des points bonus si vous faites var0et var1des couleurs différentes, et peuvent inclure une légende!

Je suis sûr que c'est très simple, mais je ne trouve aucun exemple là-bas.

fmark
la source

Réponses:

373

Pour un petit nombre de variables, vous pouvez construire le tracé manuellement vous-même:

ggplot(test_data, aes(date)) + 
  geom_line(aes(y = var0, colour = "var0")) + 
  geom_line(aes(y = var1, colour = "var1"))
hadley
la source
3
bel exemple, mais comment personnaliser mes propres couleurs (par exemple noir et orange)?, car il semble que vous l'utilisiez colour=comme nom de variable.
Darwin PC
1
même colour='var_names'comme spécifié par hadley fonctionne très bien. mais @DaveX - serait plus spécifique si l'on veut choisir des couleurs spécifiques plutôt que des couleurs sélectionnées automatiquement par la fonction.
I_m_LeMarque
Comment puis-je y ajouter une légende?
user1700890
361

L'approche générale consiste à convertir les données au format long (à l'aide melt()du package reshapeou reshape2) ou gather()/ pivot_longer()du tidyrpackage:

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

sortie ggplot2

Voir également cette question sur le remodelage des données de large à long.

rcs
la source
8
Vous pouvez également utiliser la gather()fonction de tidyrpackage pour faire fondre les données:gather(test_data, variable, value, -date)
janosdivenyi
33

Vous avez besoin que les données soient au format "grand" au lieu de "large" pour ggplot2. "large" signifie avoir une observation par ligne avec chaque variable comme une colonne différente (comme vous l'avez maintenant). Vous devez le convertir dans un format "grand" où vous avez une colonne qui vous indique le nom de la variable et une autre colonne qui vous indique la valeur de la variable. Le processus de passage du large au grand est généralement appelé «fusion». Vous pouvez utiliser tidyr::gatherpour faire fondre votre bloc de données:

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

plusieurs séries ggplot2

Juste pour être clair, ce dataqui ggplotest consommé après l'avoir canalisé via gatherressemble à ceci:

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
la source
13

Utilisation de vos données:

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

Je crée une version empilée avec laquelle ggplot()j'aimerais travailler:

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

Dans ce cas, la production a stackedété assez facile car nous n'avons eu à effectuer que quelques manipulations, mais reshape()le reshapeet reshape2pourrait être utile si vous avez un ensemble de données réelles plus complexe à manipuler.

Une fois que les données sont sous cette forme empilée, il suffit d'un simple ggplot()appel pour produire le tracé que vous vouliez avec tous les extras (une des raisons pour lesquelles les packages de traçage de niveau supérieur aiment latticeet ggplot2sont si utiles):

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

Je vous laisse le soin de ranger les étiquettes des axes, le titre de la légende, etc.

HTH

Gavin Simpson
la source
1
Je pense que vous avez un parens mal placé dans votre code là-haut. Je pense que c'est ce que vous recherchez: stacked <- with (test_data, data.frame (value = c (var0, var1), variable = factor (rep (c ("Var0", "Var1")))), each = NROW (test_data), Dates = rep (date, 2))). Quel est également le but de la colonne "chacun"? Et n'est-ce pas simplement un moyen plus compliqué et moins efficace de faire fondre les données comme le montre rcs? Je suppose que je pourrais imaginer un cas où la fusion ne ferait pas le travail, mais c'est presque certainement le bon outil pour ce travail à moins que je manque quelque chose?
Chase
1
@chase, désolé, c'est Emacs ESS qui se trompe. chacun est un argument rep(), donc nous ne recevons vraiment que 3 colonnes stacked. Je vais modifier le code pour rendre le retrait plus clair.
Gavin Simpson
1
@chasse; votre commentaire melt()est bien pris et je note que le package de remodelage [2] serait utile ici. Je ne suis pas très familier avec reshape2 et pour une manipulation aussi simple, le faire à la main est plus complexe qu'un appel à melt(), c'était moins d'effort car je n'avais pas besoin de lire comment l'utiliser melt(). Et rcs s'est faufilé avec sa réponse pendant que je produisais la mienne; lorsque j'ai commencé la réponse, il n'y avait eu aucune réponse. plus d'une façon d'écorcher un chat - comme on dit! ;-)
Gavin Simpson
7

Je suis également nouveau sur R, mais en essayant de comprendre comment fonctionne ggplot, je pense que je peux faire autrement. Je partage juste probablement pas comme une solution parfaite complète mais pour ajouter des points de vue différents.

Je sais que ggplot est conçu pour mieux fonctionner avec les trames de données, mais il peut également être parfois utile de savoir que vous pouvez tracer directement deux vecteurs sans utiliser de trame de données.

Chargement des données. La longueur du vecteur de date d'origine est de 100 tandis que var0 et var1 ont une longueur de 50, donc je ne trace que les données disponibles (les 50 premières dates).

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)    

Traçage

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

entrez la description de l'image ici

Cependant, je n'ai pas pu ajouter une légende correcte en utilisant ce format. Est-ce que quelqu'un sait comment?

Papalagui
la source
1
Cela ajoute une légende 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