it-swarm.com.de

Wie kann ich mit 2 verschiedenen Y-Achsen plotten?

Ich möchte zwei Streudiagramme in R überlagern, so dass jeder Punktsatz seine eigene (unterschiedliche) y-Achse hat (d. H. In Position 2 und 4 der Figur), die Punkte jedoch der gleichen Figur überlagert erscheinen.

Kann man das mit plot machen?

Edit Beispielcode, der das Problem zeigt

# 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)
105
KennyPeanuts

update: Material kopiert, das sich im R-Wiki unter http://rwiki.sciviews.org/doku.php?id=tips:graphics-base:2yaxes befand, Link jetzt defekt: auch verfügbar bei die Rückwegmaschine

Zwei verschiedene y-Achsen in derselben Grafik

(Material ursprünglich von Daniel Rajdl 2006/03/31 15:26)

Bitte beachten Sie, dass es sehr wenige Situationen gibt, in denen es sinnvoll ist, zwei verschiedene Skalen in derselben Grafik zu verwenden. Es ist sehr leicht, den Betrachter der Grafik in die Irre zu führen. Überprüfen Sie die folgenden zwei Beispiele und Kommentare zu diesem Problem ( example1 , example2 aus Junk Charts ) sowie diesen Artikel von Stephen Few (was zu dem Schluss kommt: "Ich kann es nicht schlussfolgern ein für alle Mal, dass Diagramme mit zwei Skalenachsen niemals nützlich sind, nur dass mir keine Situation einfällt, die sie angesichts anderer, besserer Lösungen rechtfertigt. “) Siehe auch Punkt 4 in dieser Zeichentrickfilm ...

Wenn Sie bestimmt sind, besteht das Grundrezept darin, Ihren ersten Plot zu erstellen. Setzen Sie par(new=TRUE), um zu verhindern, dass R das Grafikgerät löscht. Erstellen Sie den zweiten Plot mit axes=FALSE (und setzen Sie xlab und ylab auf leer - ann=FALSE sollte ebenfalls funktionieren) axis(side=4), um eine neue Achse auf der rechten Seite hinzuzufügen, und mtext(...,side=4), um eine Achsenbeschriftung auf der rechten Seite hinzuzufügen. Hier ist ein Beispiel mit ein wenig erfundenen Daten:

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() im Paket plotrix automatisiert diesen Vorgang ebenso wie doubleYScale() im Paket latticeExtra.

Ein anderes Beispiel (angepasst an einen Posting-Listen-Post von 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"))

enter image description here

Ähnliche Rezepte können verwendet werden, um Diagramme verschiedener Typen zu überlagern - Balkendiagramme, Histogramme usw.

101
Ben Bolker

Wie der Name schon sagt, ist twoord.plot() in den Paketplots plotrix mit zwei Ordinatenachsen.

library(plotrix)
example(twoord.plot)

enter image description here

enter image description here

enter image description here

enter image description here

enter image description here

33
kmm

Eine Möglichkeit besteht darin, zwei Parzellen nebeneinander zu erstellen. ggplot2 bietet hierfür eine nette Option mit 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")
5
Chase

Wenn Sie die Skalen/Achsenbeschriftungen aufgeben können, können Sie die Daten in Intervallen von (0, 1) neu skalieren. Dies funktioniert zum Beispiel für verschiedene "wackelnde" Trakcs auf Chromosomen, wenn Sie generell an lokalen Korrelationen zwischen den Spuren interessiert sind und unterschiedliche Skalen aufweisen (Reichweite in Tausend, 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
}

Wenn Sie dann einen Datenrahmen mit den Spalten chrom, position, coverage und fst haben, können Sie Folgendes tun:

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

Dies hat den Vorteil, dass Sie nicht auf zwei Trakcs beschränkt sind.

3
liborm

Ich schlage auch vor, twoord.stackplot() in den plotrix Paketplots mit mehr von zwei Ordinatenachsen.

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

Eine andere Alternative, die der akzeptierten Antwort von @BenBolker ähnelt, besteht darin, die Koordinaten der vorhandenen Zeichnung neu zu definieren, wenn Sie einen zweiten Satz von Punkten hinzufügen.

Hier ist ein minimales Beispiel.

Daten:

x  <- 1:10
y1 <- rnorm(10, 100, 20)
y2 <- rnorm(10, 1, 1)

Handlung:

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

 example