Plotando duas variáveis ​​como linhas usando ggplot2 no mesmo gráfico

305

Uma pergunta muito recente, mas digamos que eu tenha dados 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)
  )

Como plotar ambas as séries temporais var0e var1no mesmo gráfico, com dateo eixo x, usando ggplot2? Os pontos de bónus se você fizer var0e var1cores diferentes, e pode incluir uma lenda!

Tenho certeza de que isso é muito simples, mas não consigo encontrar exemplos por aí.

fmark
fonte

Respostas:

373

Para um pequeno número de variáveis, você pode criar o gráfico manualmente:

ggplot(test_data, aes(date)) + 
  geom_line(aes(y = var0, colour = "var0")) + 
  geom_line(aes(y = var1, colour = "var1"))
Hadley
fonte
3
bom exemplo, mas como personalizar minhas próprias cores (por exemplo, preto e laranja) ?, porque parece que você está usando colour=como o nome da variável.
Darwin PC
1
mesmo colour='var_names'conforme especificado por hadley funciona bem. mas @DaveX - seria mais específico se você quiser escolher cores específicas em vez de cores selecionadas automaticamente pela função.
I_m_LeMarque 5/04
Como posso adicionar uma legenda?
user1700890 23/03
361

A abordagem geral é converter os dados em formato longo (usando melt()do pacote reshapeou reshape2) ou gather()/ pivot_longer()do tidyrpacote:

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

saída ggplot2

Veja também esta pergunta sobre como remodelar dados de amplos para longos.

rcs
fonte
8
Você também pode usar a gather()função de tidyrpacote para derreter os dados:gather(test_data, variable, value, -date)
janosdivenyi
33

Você precisa que os dados estejam no formato "alto" em vez de "amplo" para o ggplot2. "wide" significa ter uma observação por linha com cada variável como uma coluna diferente (como você tem agora). Você precisa convertê-lo para um formato "alto", onde você tem uma coluna que informa o nome da variável e outra coluna que informa o valor da variável. O processo de passagem da largura para a altura é geralmente chamado de "fusão". Você pode usar tidyr::gatherpara derreter seu quadro de dados:

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

várias séries ggplot2

Só para esclarecer o dataque ggplotestá consumindo após a tubulação, gatherfica assim:

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
fonte
13

Usando seus dados:

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

Eu crio uma versão empilhada com a qual ggplot()gostaria de trabalhar:

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

Neste caso, a produção stackedera muito fácil, já que só tinha que fazer um par de manipulações, mas reshape()ea reshapee reshape2pode ser útil se você tiver um conjunto de dados reais mais complexo para manipular.

Uma vez que os dados estão neste formulário empilhado, é necessária apenas uma ggplot()chamada simples para produzir o gráfico desejado com todos os extras (uma razão pela qual os pacotes de plotagem de nível superior gostam latticee ggplot2são tão úteis):

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

Vou deixar você arrumar os rótulos dos eixos, o título da legenda etc.

HTH

Gavin Simpson
fonte
1
Eu acho que você tem um parênteses fora de lugar no seu código lá em cima. Eu acho que é isso que você está depois: empilhado <- com (test_data, data.frame (valor = c (var0, var1), variável = fator (rep (c ("Var0", "Var1")))), cada um = NROW (test_data), Datas = representante (data, 2))). Além disso, qual é o objetivo da coluna "each"? E essa não é apenas uma maneira mais complicada e menos eficiente de derreter os dados, conforme mostrado pelos rcs? Eu acho que eu poderia imaginar um caso em que o derretimento não faria o trabalho, mas é quase certamente a ferramenta certa para esse trabalho, a menos que eu esteja perdendo alguma coisa?
Chase
1
@ compra, desculpe, isso é o Emacs ESS que está entendendo errado. cada um é um argumento para rep(), então realmente estamos apenas recebendo 3 cols stacked. Vou editar o código para tornar o recuo mais claro.
Gavin Simpson
1
@correr atrás; seu comentário melt()é bem aceito e observo que o pacote remodelar [2] seria útil aqui. Eu não estou tão familiarizado com o remodelar2 e, para uma manipulação tão simples fazê-lo manualmente, é mais complexo do que uma ligação melt(), foi menos esforço, pois eu não precisava ler como usar melt(). E rcs esgueirou-se com sua resposta enquanto eu produzia a minha; quando iniciei a resposta, não havia respostas. mais de uma maneira de esfolar um gato - como eles dizem! ;-)
Gavin Simpson
7

Também sou novo no R, mas, tentando entender como o ggplot funciona, acho que tenho outra maneira de fazê-lo. Apenas compartilho provavelmente não como uma solução perfeita e completa, mas para adicionar alguns pontos de vista diferentes.

Eu sei que o ggplot foi criado para funcionar melhor com quadros de dados, mas talvez às vezes também seja útil saber que você pode plotar diretamente dois vetores sem usar um quadro de dados.

Carregando dados. O comprimento do vetor de data original é 100, enquanto var0 e var1 têm comprimento 50, portanto, planto apenas os dados disponíveis (primeiras 50 datas).

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)    

Plotagem

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

insira a descrição da imagem aqui

No entanto, não consegui adicionar uma legenda correta usando este formato. Alguém sabe como?

Papalagui
fonte
1
Isso adiciona uma lenda 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