J'aimerais superposer deux diagrammes de dispersion dans R de sorte que chaque ensemble de points ait son propre axe y (différent) (c'est-à-dire aux positions 2 et 4 sur la figure) mais les points apparaissent superposés sur la même figure.
Est-il possible de faire cela avec plot
?
Edit Exemple de code montrant le problème
# 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: éléments copiés qui se trouvaient sur le wiki R à l'adresse { http://rwiki.sciviews.org/doku.php?id=tips:graphics-base:2yaxes }, lien maintenant rompu: également disponible à partir de la machine à retourner
(du matériel à l’origine par Daniel Rajdl le 2006/03/31 15:26)
Veuillez noter qu'il existe très peu de situations dans lesquelles il est approprié d'utiliser deux échelles différentes sur la même parcelle. Il est très facile d'induire le spectateur en erreur. Consultez les deux exemples et commentaires suivants sur ce problème ( exemple1 , exemple2 de Graphiques indésirables ), ainsi que cet article de Stephen Few (qui conclut: «Je ne peux certainement pas en conclure, une fois pour toutes, que les graphes avec des axes à deux échelles ne sont jamais utiles; seulement je ne peux pas penser à une situation qui les justifie à la lumière d'autres solutions meilleures».) Voir aussi le point # 4 dans cette caricature ...
Si vous êtes déterminé, la recette de base consiste à créer votre premier tracé, définissez par(new=TRUE)
pour éviter que R n'efface le périphérique graphique, créez le deuxième tracé avec axes=FALSE
(et définissez xlab
et ylab
sur blanc - ann=FALSE
devrait également fonctionner), puis utilisez axis(side=4)
pour ajouter un nouvel axe à droite et mtext(...,side=4)
pour ajouter une étiquette d’axe à droite. Voici un exemple utilisant un peu de données inventées:
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()
dans le package plotrix
automatise ce processus, tout comme doubleYScale()
dans le package latticeExtra
.
Un autre exemple (adapté d'un courrier de la liste de diffusion R 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"))
Des recettes similaires peuvent être utilisées pour superposer des tracés de différents types - tracés à barres, histogrammes, etc.
Comme son nom l’indique, twoord.plot()
dans les tracés plotrix package avec deux axes en ordonnée.
library(plotrix)
example(twoord.plot)
Une option consiste à créer deux parcelles côte à côte. ggplot2
fournit une option intéressante pour cela avec 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")
Si vous pouvez abandonner les étiquettes d'échelles/d'axes, vous pouvez redimensionner les données à un intervalle (0, 1). Cela fonctionne par exemple pour différentes trajectoires de 'wiggle' sur les chromosomes, lorsque vous vous intéressez généralement aux corrélations locales entre les pistes et qu'elles ont des échelles différentes (couverture en milliers, 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
}
Ensuite, en ayant un cadre de données avec des colonnes chrom
, position
, coverage
et fst
, vous pouvez effectuer les opérations suivantes:
ggplot(d, aes(position)) +
geom_line(aes(y = rescale(fst))) +
geom_line(aes(y = rescale(coverage))) +
facet_wrap(~chrom)
L'avantage de ceci est que vous n'êtes pas limité à deux trakcs.
Moi aussi, je suggère twoord.stackplot()
dans les tracés de package plotrix
avec plus de deux axes ordinaux.
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) )
Une autre alternative, similaire à la réponse acceptée par @BenBolker, consiste à redéfinir les coordonnées du tracé existant lors de l'ajout d'un deuxième ensemble de points.
Voici un exemple minimal.
Les données:
x <- 1:10
y1 <- rnorm(10, 100, 20)
y2 <- rnorm(10, 1, 1)
Terrain:
par(mar=c(5,5,5,5)+0.1, las=1)
plot.new()
plot.window(xlim=range(x), ylim=range(y1))
points(x, y1, col="red", pch=19)
axis(1)
axis(2, col.axis="red")
box()
plot.window(xlim=range(x), ylim=range(y2))
points(x, y2, col="limegreen", pch=19)
axis(4, col.axis="limegreen")