Como posso traçar com 2 eixos y diferentes?

Eu gostaria de sobrepor dois charts de dispersão em R de modo que cada conjunto de pontos tenha seu próprio eixo y (diferente) (ou seja, nas posições 2 e 4 na figura), mas os pontos aparecem sobrepostos na mesma figura.

É possível fazer isso com o plot ?

Editar código de exemplo mostrando o problema

 # example code for SO question y1 <- rnorm(10, 100, 20) y2 <- rnorm(10, 1, 1) x <- 1:10 # in this plot y2 is plotted on what is clearly an inappropriate scale plot(y1 ~ x, ylim = c(-1, 150)) points(y2 ~ x, pch = 2) 

update : Material copiado que estava no wiki R em http://rwiki.sciviews.org/doku.php?id=tips:graphics-base:2yaxes , link agora quebrado: também disponível na máquina do wayback

Dois eixos y diferentes no mesmo enredo

(algum material originalmente de Daniel Rajdl 2006/03/31 15:26)

Por favor, note que existem muito poucas situações em que é apropriado usar duas escalas diferentes no mesmo enredo. É muito fácil enganar o visualizador do gráfico. Verifique os dois exemplos e comentários a seguir sobre este assunto ( exemplo1 , exemplo2 de Gráficos Lixo ), bem como este artigo de Stephen Few (que conclui: “Eu certamente não posso concluir, de uma vez por todas, que os charts com eixos de escala dupla nunca são útil, só que eu não consigo pensar em uma situação que os justifique à luz de outras soluções melhores. ”) Veja também o ponto # 4 deste desenho animado …

Se você está determinado, a receita básica é criar sua primeira plotagem, set par(new=TRUE) para evitar que R limpe o dispositivo gráfico, criando a segunda plotagem com axes=FALSE (e definindo xlab e xlab como em branco – ann=FALSE também deve funcionar) e, em seguida, usando o axis(side=4) para adicionar um novo eixo no lado direito e mtext(...,side=4) para adicionar um label de eixo no lado direito. Aqui está um exemplo usando um pouco de dados inventados:

 set.seed(101) x < - 1:10 y <- rnorm(10) ## second data set on a very different scale z <- runif(10, min=1000, max=10000) par(mar = c(5, 4, 4, 4) + 0.3) # Leave space for z axis plot(x, y) # first plot par(new = TRUE) plot(x, z, type = "l", axes = FALSE, bty = "n", xlab = "", ylab = "") axis(side=4, at = pretty(range(z))) mtext("z", side=4, line=3) 

twoord.plot() no pacote plotrix automatiza esse processo, assim como doubleYScale() no pacote latticeExtra .

Outro exemplo (adaptado de um post da lista de discussão de Robert W. Baer):

 ## set up some fake test data time < - seq(0,72,12) betagal.abs <- c(0.05,0.18,0.25,0.31,0.32,0.34,0.35) cell.density <- c(0,1000,2000,3000,4000,5000,6000) ## add extra space to right margin of plot within frame par(mar=c(5, 4, 4, 6) + 0.1) ## Plot first set of data and draw its axis plot(time, betagal.abs, pch=16, axes=FALSE, ylim=c(0,1), xlab="", ylab="", type="b",col="black", main="Mike's test data") axis(2, ylim=c(0,1),col="black",las=1) ## las=1 makes horizontal labels mtext("Beta Gal Absorbance",side=2,line=2.5) box() ## Allow a second plot on the same graph par(new=TRUE) ## Plot the second plot and put axis scale on right plot(time, cell.density, pch=15, xlab="", ylab="", ylim=c(0,7000), axes=FALSE, type="b", col="red") ## a little farther out (line=4) to make room for labels mtext("Cell Density",side=4,col="red",line=4) axis(4, ylim=c(0,7000), col="red",col.axis="red",las=1) ## Draw the time axis axis(1,pretty(range(time),10)) mtext("Time (Hours)",side=1,col="black",line=2.5) ## Add Legend legend("topleft",legend=c("Beta Gal","Cell Density"), text.col=c("black","red"),pch=c(16,15),col=c("black","red")) 

insira a descrição da imagem aqui

Receitas similares podem ser usadas para sobrepor charts de diferentes tipos - charts de barras, histogramas, etc.

Como o próprio nome sugere, twoord.plot() no pacote plotrix plota com dois eixos ordenados.

 library(plotrix) example(twoord.plot) 

insira a descrição da imagem aqui

insira a descrição da imagem aqui

insira a descrição da imagem aqui

insira a descrição da imagem aqui

insira a descrição da imagem aqui

Uma opção é fazer duas plots lado a lado. ggplot2 fornece uma boa opção para isso com o facet_wrap() :

 dat < - data.frame(x = c(rnorm(100), rnorm(100, 10, 2)) , y = c(rnorm(100), rlnorm(100, 9, 2)) , index = rep(1:2, each = 100) ) require(ggplot2) ggplot(dat, aes(x,y)) + geom_point() + facet_wrap(~ index, scales = "free_y") 

É um FAQ. Aqui está uma solução mais antiga que eu forneci há quase seis anos para a Galeria de Gráficos R

Você pode ver, por exemplo, a function plotVolumeBars() que combina uma escala absoluta e uma relativa em um gráfico.

Se você pode desistir dos labels de balança / eixo, você pode resize os dados para o intervalo (0, 1). Isso funciona, por exemplo, para diferentes tramas de “wiggle” nos cromossomos, quando você está geralmente interessado em correlações locais entre as trilhas e elas têm diferentes escalas (cobertura em milhares, Fst 0-1).

 # rescale numeric vector into (0, 1) interval # clip everything outside the range rescale < - function(vec, lims=range(vec), clip=c(0, 1)) { # find the coeficients of transforming linear equation # that maps the lims range to (0, 1) slope <- (1 - 0) / (lims[2] - lims[1]) intercept <- - slope * lims[1] xformed <- slope * vec + intercept # do the clipping xformed[xformed < 0] <- clip[1] xformed[xformed > 1] < - clip[2] xformed } 

Em seguida, com um quadro de dados com as colunas chrom , position , coverage e fst , você pode fazer algo como:

 ggplot(d, aes(position)) + geom_line(aes(y = rescale(fst))) + geom_line(aes(y = rescale(coverage))) + facet_wrap(~chrom) 

A vantagem disso é que você não está limitado a dois trakcs.

Eu também twoord.stackplot() , twoord.stackplot() no pacote plotrix plots com mais de dois eixos ordenados.

 data< -read.table(text= "e0AL fxAL e0CO fxCO e0BR fxBR anos 51.8 5.9 50.6 6.8 51.0 6.2 1955 54.7 5.9 55.2 6.8 53.5 6.2 1960 57.1 6.0 57.9 6.8 55.9 6.2 1965 59.1 5.6 60.1 6.2 57.9 5.4 1970 61.2 5.1 61.8 5.0 59.8 4.7 1975 63.4 4.5 64.0 4.3 61.8 4.3 1980 65.4 3.9 66.9 3.7 63.5 3.8 1985 67.3 3.4 68.0 3.2 65.5 3.1 1990 69.1 3.0 68.7 3.0 67.5 2.6 1995 70.9 2.8 70.3 2.8 69.5 2.5 2000 72.4 2.5 71.7 2.6 71.1 2.3 2005 73.3 2.3 72.9 2.5 72.1 1.9 2010 74.3 2.2 73.8 2.4 73.2 1.8 2015 75.2 2.0 74.6 2.3 74.2 1.7 2020 76.0 2.0 75.4 2.2 75.2 1.6 2025 76.8 1.9 76.2 2.1 76.1 1.6 2030 77.6 1.9 76.9 2.1 77.1 1.6 2035 78.4 1.9 77.6 2.0 77.9 1.7 2040 79.1 1.8 78.3 1.9 78.7 1.7 2045 79.8 1.8 79.0 1.9 79.5 1.7 2050 80.5 1.8 79.7 1.9 80.3 1.7 2055 81.1 1.8 80.3 1.8 80.9 1.8 2060 81.7 1.8 80.9 1.8 81.6 1.8 2065 82.3 1.8 81.4 1.8 82.2 1.8 2070 82.8 1.8 82.0 1.7 82.8 1.8 2075 83.3 1.8 82.5 1.7 83.4 1.9 2080 83.8 1.8 83.0 1.7 83.9 1.9 2085 84.3 1.9 83.5 1.8 84.4 1.9 2090 84.7 1.9 83.9 1.8 84.9 1.9 2095 85.1 1.9 84.3 1.8 85.4 1.9 2100", header=T) require(plotrix) twoord.stackplot(lx=data$anos, rx=data$anos, ldata=cbind(data$e0AL, data$e0BR, data$e0CO), rdata=cbind(data$fxAL, data$fxBR, data$fxCO), lcol=c("black","red", "blue"), rcol=c("black","red", "blue"), ltype=c("l","o","b"), rtype=c("l","o","b"), lylab="Años de Vida", rylab="Hijos x Mujer", xlab="Tiempo", main="Mortalidad/Fecundidad:1950–2100", border="grey80") legend("bottomright", c(paste("Proy:", c("A. Latina", "Brasil", "Colombia"))), cex=1, col=c("black","red", "blue"), lwd=2, bty="n", lty=c(1,1,2), pch=c(NA,1,1) )