Wie staple ich zwei Graphen vertikal mit derselben x-Skala, aber einer anderen y-Skala in R?

9

Schöne Grüße,

Derzeit mache ich folgendes in R:

require(zoo)
data <- read.csv(file="summary.csv",sep=",",head=TRUE)
cum  = zoo(data$dcomp, as.Date(data$date))
data = zoo(data$compressed, as.Date(data$date))
data <- aggregate(data, identity, tail, 1)
cum  <- aggregate(cum, identity, sum, 1)
days = seq(start(data), end(data), "day")
data2 = na.locf(merge(data, zoo(,days)))

plot(data2,xlab='',ylab='compressed bytes',col=rgb(0.18,0.34,0.55))
lines(cum,type="h",col=rgb(0,0.5,0))

Ausschnitt aus summary.csv:

date,revision,file,lines,nclass,nattr,nrel,bytes,compressed,diff,dcomp
2007-07-25,16,model.xml,96,11,22,5,4035,991,0,0
2007-07-27,17,model.xml,115,16,26,6,4740,1056,53,777
2007-08-09,18,model.xml,106,16,26,7,4966,1136,47,761
2007-08-10,19,model.xml,106,16,26,7,4968,1150,4,202
2007-09-06,81,model.xml,111,16,26,7,5110,1167,13,258
...

Die letzten beiden Zeilen zeichnen die Informationen auf, die ich benötige, und das Ergebnis ähnelt dem Folgenden: Die Alt-Text blaue Linie ist die Entropie des Artefakts in Byte, an dem ich interessiert bin. Grüne Linien repräsentieren die Entropie der Änderungen.

In diesem Diagramm funktioniert es nun gut, da es keinen großen Unterschied in der Skalierung gibt. Aber ich habe andere Grafiken, in denen die grünen Linien so klein werden, dass man sie nicht sehen kann.

Die Lösung, nach der ich suchte, beinhaltete zwei Dinge:

  1. Verschieben der grünen vertikalen Linien in ein zweites Diagramm direkt unter dem ersten mit eigener y-Achse, aber gemeinsamer x-Achse.
  2. Um es als logarithmische Skala bereitzustellen, da mich die "Größe" mehr interessiert als die spezifischen Werte.

Danke im Voraus!

PS Wenn mir jemand auch sagen kann, wie ich "kleine Häkchen" in die x-Skala einfügen kann, die sich auf die Monate bezieht, schätze ich :-) Wenn dies zu viele Fragen für einen einzelnen Beitrag sind, kann ich sie weiter unterteilen.

Hugo Sereno Ferreira
quelle

Antworten:

15

Sie können par(new=TRUE)mit zwei verschiedenen y-Achsen in dasselbe Diagramm zeichnen! Dies sollte auch Ihr Problem lösen.

Als nächstes finden Sie ein einfaches Beispiel, das zwei zufällige Normalvariablen darstellt, eine auf Mittelwert 0 und eine auf Mittelwert 100 (beide sd s = 1) in derselben Darstellung. Die erste in rot auf der linken y-Achse, die zweite in blau auf der rechten y-Achse. Anschließend werden Achsenbeschriftungen hinzugefügt.

Bitte schön:

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

plot(x,y1,pch=0,type="b",col="red",yaxt="n",ylim=c(-8,2))
par(new=TRUE)
plot(x,y2,pch=1,type="b",col="blue",yaxt="n",ylim=c(98,105))

axis(side=2)
axis(side=4)

sieht dann so aus (erinnere dich an Rot auf der linken Achse, Blau auf der rechten Achse): Alt-Text

UPDATE:
Basierend auf Kommentaren habe ich eine aktualisierte Version meines Diagramms erstellt. Jetzt gehe ich etwas tiefer in die Funktionalität par(mar=c(a,b,c,d))des Basisdiagramms ein, indem ich einen größeren Rand um das Diagramm erstelle (erforderlich für die Beschriftung der rechten Achse), mtextum die Achsenbeschriftungen und die erweiterte Verwendung der axisFunktion anzuzeigen:

x <- 1:100
y1 <- rnorm(100)
y2 <- rnorm(100)+100

par(mar=c(5,5,5,5))

plot(x,y1,pch=0,type="b",col="red",yaxt="n",ylim=c(-8,2),ylab="")
axis(side=2, at=c(-2,0,2))
mtext("red line", side = 2, line=2.5, at=0)

par(new=TRUE)
plot(x,y2,pch=1,type="b",col="blue",yaxt="n",ylim=c(98,108), ylab="")
axis(side=4, at=c(98,100,102), labels=c("98%","100%","102%"))
mtext("blue line", side=4, line=2.5, at=100)

Alt-Text

Wie Sie sehen, ist es ziemlich einfach. Sie können die Position Ihrer Daten ylimin der plotFunktion definieren und dann atin der axisFunktion auswählen, welche Achsen-Ticks Sie sehen möchten. Darüber hinaus können Sie labelsin der axisFunktion (hier auf der rechten Achse) sogar die Beschriftungen für die Achsen-Ticks (sehr nützlich für die nominale x-Achse) bereitstellen . Verwenden Sie zum Hinzufügen von Achsenbeschriftungen mtextmit atfür die vertikale Positionierung ( linefür die horizontale Positionierung).

Achten Sie darauf , zu prüfen ?plot, ?par, ?axis, und ?mtextfür weitere Informationen.
Hervorragende Webressourcen sind: Quick-R für Grafiken: 1 , 2 und 3 .

Henrik
quelle
Das ist interessant, aber wie können wir dem Leser sagen, welche Skala welcher Zeile entspricht?
Hugo Sereno Ferreira
Schauen Sie sich dieses Diagramm an: imgur.com/K8BCr.png Dort werden Beschriftungen und Häkchen für die y-Achse nur dort angezeigt , wo sie für die Daten gelten (dh für die linke Achse oben im Diagramm als entsprechende Daten). und für die rechte Achse am unteren Rand des Diagramms als entsprechende Daten). Zusätzlich haben wir verschiedene Farben (wie im obigen Beispiel) und Linientypen verwendet und diese in der Beschriftung erläutert. Sie können auch ein Liniendiagramm auf der linken Seite und ein Balkendiagramm auf der rechten Achse verwenden, um die Unterscheidung klarer zu machen.
Henrik
Das Beispiel, das Sie gegeben haben, ist sehr gut ... Wie haben Sie es geschafft, jede Achse vertikal zu versetzen?
Hugo Sereno Ferreira
2
Wirklich gutes Beispiel. Das einzige Problem mit Ihrem Diagramm ist, dass sich beide Y-Variablennamen überlappen. In diesem Fall möchten Sie eine links und die andere rechts (möglicherweise sogar in vertikaler Position). Um Ihr Beispiel von "wirklich gut" auf "perfekt" zu aktualisieren, möchten Sie möglicherweise die mtext-Funktion von R verwenden, um die Variablennamen zu erstellen
Dave Kellen
@Hugo @Dave: In meinem Update finden Sie eine Zusammenfassung beider Kommentare.
Henrik
12

Ich denke, Sie können bekommen, was Sie wollen ggplot2. Mit dem folgenden Code kann ich produzieren:

Alt-Text

Offensichtlich können Dinge wie Linienfarben nach Belieben geändert werden. Auf der x-Achse habe ich Hauptlinien für Jahre und Nebenlinien für Monate angegeben.

require(ggplot2)
t = as.Date(0:1000, origin="2008-01-01")  
y1 = rexp(1001)
y2 = cumsum(y1)
df = data.frame(t=t, values=c(y2,y1), type=rep(c("Bytes", "Changes"), each=1001))

g = ggplot(data=df, aes(x=t, y=values)) +
  geom_line() +
  facet_grid(type ~ ., scales="free") +
  scale_y_continuous(trans="log10") +
  scale_x_date(major="years", minor="months") +
  ylab("Log values")
g
csgillespie
quelle
Äh, ich habe versucht, df = data.frame einzurichten (t = Tage, Werte = c (Daten2, cum), Typ = rep (c ("Bytes", "Änderungen"), jeweils = 1001)), aber es gibt eine Fehler in rbind.zoo (...): Indizes überschneiden sich
Hugo Sereno Ferreira
Das liegt daran, dass data2 und cum Zooobjekte sind. Verwenden Sie as.vector (data2), um die Rohwerte abzurufen. Außerdem habe ich 1001 verwendet, weil ich 1001 Beobachtungen hatte. Du wirst etwas anderes brauchen.
Csgillespie
Noob R-Benutzer hier: Fehler im Datenrahmen (t = Tage, Werte = c (as.vector (data2), as.vector (cum)): Argumente implizieren unterschiedliche Anzahl von Zeilen: 1063, 1300, 2
Hugo Sereno Ferreira
Geben Sie "Tage", "Daten2" und "Sperma" ein, um Ihre Daten anzuzeigen. Schauen Sie sich dann "Länge (Tage)" usw. an. Sie müssen die Zeitpunkte mit den Werten abgleichen.
Csgillespie