Plote dois gráficos no mesmo gráfico em R

571

Eu gostaria de plotar y1 e y2 na mesma plotagem.

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

Mas quando faço assim, eles não são plotados no mesmo enredo juntos.

No Matlab, é possível fazer hold on, mas alguém sabe como fazer isso no R?

Sandra Schlichting
fonte
3
Confira ?curve. Use add=TRUE.
Isomorphismes
Veja esta pergunta para obter respostas mais específicas do ggplot2.
Axeman

Respostas:

617

lines()ou points()será adicionado ao gráfico existente, mas não criará uma nova janela. Então você precisaria fazer

plot(x,y1,type="l",col="red")
lines(x,y2,col="green")
bnaul
fonte
10
Por que não funciona no seguinte exemplo simples? > Plot (SIN)> linhas (cos) Erro no as.double (y): não pode tipo coerce 'embutido' para vector do tipo 'double'
Frank
23
Isso é fácil de ver. Com plot (sin), você está passando uma função em vez de dados reais. plot () detectará isso e, por sua vez, use plot.function () para plotar sua função (leia em despacho múltiplo para saber mais sobre isso). No entanto, lines.function () não está definido, portanto, lines () não sabe o que fazer com um parâmetro da função de classe. As linhas só podem lidar com seus dados e objetos de séries temporais da classe ts.
Soumendra 9/07/2013
27
@Frank fazê-lo como este: plot(sin); curve(cos, add=TRUE).
Isomorphismes
2
Como usar o mesmo se x é diferente? Digamos, eu tenho x1 e y1 para um gráfico e adicione outro gráfico de x2 e y2 no mesmo gráfico. X1 e x2 têm o mesmo intervalo, mas valores diferentes.
Kavipriya
1
É exatamente o mesmo: em lines(x2,y2,...)vez delines(x,y2,...)
bnaul
220

Você também pode usar pare plotar no mesmo gráfico, mas em eixos diferentes. Algo da seguinte forma:

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

Se você ler detalhadamente sobre parin R, poderá gerar gráficos realmente interessantes. Outro livro é o R Graphics, de Paul Murrel.

Sam
fonte
3
Meu R me dá um erro: Erro no par (fig (novos = TRUE)): não foi possível encontrar a função "fig"
Alessandro Jacopson
5
Seu método preserva a escala correta (eixo y) para as duas parcelas?
Alessandro Jacopson
1
@uvts_cvs Sim, ele preserva o gráfico original no total.
Sam
10
O problema é que ele reescreve vários elementos da plotagem. Eu incluiria xlab="", ylab="", ...e alguns outros no segundo plot.
Isomorphismes
118

Ao construir plotagens multicamadas, deve-se considerar o ggplotpacote. A idéia é criar um objeto gráfico com estética básica e aprimorá-lo gradualmente.

ggplotestilo requer que os dados sejam compactados data.frame.

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

Solução 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

Aqui + operatoré usado para adicionar camadas extras ao objeto básico.

Com ggplotvocê tem acesso ao objeto gráfico em todas as etapas da plotagem. Digamos, a configuração passo a passo usual pode ser assim:

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

gproduz o gráfico e você pode vê-lo em todas as etapas (bem, após a criação de pelo menos uma camada). Encantamentos adicionais da trama também são feitos com o objeto criado. Por exemplo, podemos adicionar rótulos para eixos:

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

Final se gparece com:

insira a descrição da imagem aqui

ATUALIZAÇÃO (08-11-2013):

Como apontado nos comentários, ggplota filosofia de sugerir o uso de dados em formato longo. Você pode consultar esta resposta para ver o código correspondente.

redmode
fonte
5
Conforme sugerido por Henrik , os dados realmente devem estar no formato "longo", ggplotlida com isso mais naturalmente do que o formato "amplo" usado.
krlmlr
1
@ Henrik: Não, obrigado pela resposta em primeiro lugar. Talvez o autor desta resposta pode editá-lo para que ele se encaixa bem com ggplota filosofia de ...
krlmlr
1
@krlmlr, tentei editar minha resposta para que ela abordasse mais explicitamente a questão. Por favor, sinta-se livre para sugerir mais atualizações. Felicidades.
Henrik
3
me ensinou a definir x no ggplot (aes ()) e depois y por si só no geom _ * (). Agradável!
Dan
41

Eu acho que a resposta que você está procurando é:

plot(first thing to plot)
plot(second thing to plot,add=TRUE)
user3749764
fonte
25
Isso não parece funcionar, emite um "add" is not a graphical parameteraviso e depois imprime o segundo gráfico sobre o primeiro.
Waldir Leoncio 26/08
8
@WaldirLeoncio veja stackoverflow.com/questions/6789055/…
Alessandro Jacopson
Um bom benefício disso é que parece manter os limites e os títulos dos eixos consistentes. Alguns dos métodos anteriores fazem com que R desenhe dois conjuntos de marcas de seleção no eixo y, a menos que você tenha o problema de especificar mais opções. Escusado será dizer que ter dois conjuntos de marcas nos eixos pode ser muito enganador.
RMurphy
1
o parâmetro add funciona para alguns métodos de enredo, mas não a base / default em R
cloudscomputes
2
Eu recebi o mesmo erro "add" is not a graphical parameter. Meu R é R version 3.2.3 (2015-12-10). Você pode usar o par(new=TRUE)comando entre esses gráficos.
quepas
29

Use a matplotfunção:

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

use isso se y1e y2for avaliado nos mesmos xpontos. Ele escala o eixo Y para se ajustar ao que for maior ( y1ou y2), ao contrário de outras respostas aqui que serão cortadas se ficarem y2maiores que y1(as soluções ggplot geralmente estão de acordo com isso).

Como alternativa, e se as duas linhas não tiverem as mesmas coordenadas x, defina os limites do eixo no primeiro gráfico e adicione:

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

Estou surpreso que este Q tenha 4 anos e ninguém tenha mencionado matplotou x/ylim...

Spacedman
fonte
25

tl; dr: você deseja usar curve(com add=TRUE) ou lines.


Não concordo par(new=TRUE)porque isso imprimirá duas marcas de escala e rótulos de eixo. Por exemplo

seno e parábola

A saída de plot(sin); par(new=T); plot( function(x) x**2 ).

Veja como estão confusos os rótulos dos eixos verticais! Como os intervalos são diferentes, você precisaria definir ylim=c(lowest point between the two functions, highest point between the two functions), o que é menos fácil do que o que vou mostrar --- e muito menos fácil se você quiser adicionar não apenas duas curvas, mas muitas.


O que sempre me confundiu sobre plotagem é a diferença entre curvee lines. (Se você não se lembra de que esses são os nomes dos dois importantes comandos de plotagem, basta cantá- lo.)

Aqui está a grande diferença entre curvee lines.

curveirá traçar uma função, como curve(sin). lineslotes de pontos com valores xey, como: lines( x=0:10, y=sin(0:10) ).

E aqui está uma pequena diferença: curveprecisa ser chamado add=TRUEpara o que você está tentando fazer, enquanto linesjá assume que você está adicionando a um gráfico existente.

id & sine

Aqui está o resultado da chamada plot(0:2); curve(sin).


Nos bastidores, confira methods(plot). E confira body( plot.function )[[5]]. Quando você chama plot(sin)R, descobre que siné uma função (e não valores y) e usa o plot.functionmétodo, que acaba chamando curve. Assim curveé a ferramenta destinada a lidar com funções.

isomorfismos
fonte
17

se você quiser dividir o gráfico em duas colunas (2 gráficos um ao lado do outro), faça o seguinte:

par(mfrow=c(1,2))

plot(x)

plot(y) 

Link de referência

Hamed2005
fonte
16

Conforme descrito por @redmode, você pode plotar as duas linhas no mesmo dispositivo gráfico usando ggplot. Nessa resposta, os dados estavam em um formato "amplo". No entanto, ao usá- ggplotlo, geralmente é mais conveniente manter os dados em um quadro de dados em um formato 'longo'. Então, usando diferentes 'variáveis ​​de agrupamento' nos aesargumentos téticos, as propriedades da linha, como tipo de linha ou cor, variarão de acordo com a variável de agrupamento e as legendas correspondentes aparecerão.

Nesse caso, podemos usar a colourestética, que corresponde à cor das linhas em diferentes níveis de uma variável no conjunto de dados (aqui: y1 vs y2). Mas primeiro precisamos derreter os dados do formato amplo para o longo, usando, por exemplo, a função 'derreter' do reshape2pacote. Outros métodos para remodelar os dados são descritos aqui: Remodelando data.frame do formato amplo para o longo .

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

insira a descrição da imagem aqui

Henrik
fonte
15

Se você estiver usando gráficos de base (ou seja, não gráficos de malha / grade), poderá imitar o recurso de espera do MATLAB usando as funções de pontos / linhas / polígonos para adicionar detalhes adicionais aos seus gráficos sem iniciar um novo gráfico. No caso de um layout de plotagem múltipla, você pode usar par(mfg=...)para escolher em qual plotagem você adiciona itens.

mcabral
fonte
14

Você pode usar pontos para a plotagem, isto é.

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

points(x2,y2,col='blue')
chuva de ideias
fonte
7

Em vez de manter os valores a serem plotados em uma matriz, armazene-os em uma matriz. Por padrão, a matriz inteira será tratada como um conjunto de dados. No entanto, se você adicionar o mesmo número de modificadores ao gráfico, por exemplo, col (), como você possui linhas na matriz, R descobrirá que cada linha deve ser tratada independentemente. Por exemplo:

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

Isso deve funcionar, a menos que seus conjuntos de dados tenham tamanhos diferentes.

oxicoco
fonte
Isto dá: Erro no if (as.factor) {: argumento não é interpretável como lógica
baouss
5

Idiomatic Matlab plot(x1,y1,x2,y2)pode ser traduzido em R com, ggplot2por exemplo, desta maneira:

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

insira a descrição da imagem aqui

Inspirado nos gráficos de linha dupla de Tingting Zhao com diferentes faixas de eixo x usando ggplot2 .

Alessandro Jacopson
fonte
5

Você pode usar a ggplotly()função do pacote plotly para transformar qualquer um dos exemplos do gggplot2 aqui em um gráfico interativo, mas acho que esse tipo de gráfico é melhor sem o 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")

insira a descrição da imagem aqui

Mateo Sanchez
fonte
o enredo parece brilhante; é de graça ?
denis
@denis, há plotagem pública gratuita e ilimitada e plotagem privada paga ou opções no local. Veja a página de planos .
Mateo Sanchez
4
O pacote plotly R agora é 100% gratuito e de código aberto (licenciado pelo MIT). Você pode usá-lo com ou sem uma conta gráfica.
Carson
4

Você também pode criar seu gráfico 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')

Isso criará o seguinte gráfico:

insira a descrição da imagem aqui

epo3
fonte
2

Usando plotly(adicionando solução do plotlyeixo y primário e secundário - parece estar faltando):

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 tela da demonstração de trabalho:

insira a descrição da imagem aqui

Saurabh Chauhan
fonte
Compilei o código e não funciona, primeiro marquei um erro em%>% e o apaguei, depois marquei um erro, Error in library(plotly) : there is no package called ‘plotly’por quê?
Bellatrix
Você instalou o pacote plotly? Você precisa instalar o pacote usando o install.packages("plotly")comando
Saurabh Chauhan
1

também podemos usar a biblioteca de treliç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 cores específicas

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

insira a descrição da imagem aqui

Varn K
fonte