Kombinieren Sie Basis- und ggplot-Grafiken im R-Figurenfenster

72

Ich möchte eine Figur generieren, die eine Kombination aus Basis- und ggplot-Grafiken enthält. Der folgende Code zeigt meine Figur unter Verwendung der Basisplotfunktionen von R:

t <- c(1:(24*14)) 
P <- 24 
A <- 10 
y <- A*sin(2*pi*t/P)+20

par(mfrow=c(2,2))
plot(y,type = "l",xlab = "Time (hours)",ylab = "Amplitude",main = "Time series")
acf(y,main = "Autocorrelation",xlab = "Lag (hours)", ylab = "ACF")
spectrum(y,method = "ar",main = "Spectral density function", 
         xlab = "Frequency (cycles per hour)",ylab = "Spectrum")
require(biwavelet)
t1 <- cbind(t, y)
wt.t1=wt(t1)
plot(wt.t1, plot.cb=FALSE, plot.phase=FALSE,main = "Continuous wavelet transform",
     ylab = "Period (hours)",xlab = "Time (hours)")

Welches erzeugt Geben Sie hier die Bildbeschreibung ein

Die meisten dieser Panels scheinen für mich ausreichend zu sein, um sie in meinen Bericht aufzunehmen. Das Diagramm, das die Autokorrelation zeigt, muss jedoch verbessert werden. Mit ggplot sieht das viel besser aus:

require(ggplot2)
acz <- acf(y, plot=F)
acd <- data.frame(lag=acz$lag, acf=acz$acf)
ggplot(acd, aes(lag, acf)) + geom_area(fill="grey") +
  geom_hline(yintercept=c(0.05, -0.05), linetype="dashed") +
  theme_bw()

Geben Sie hier die Bildbeschreibung ein

Da ggplot jedoch keine Basisgrafik ist, können wir ggplot nicht mit layout oder par (mfrow) kombinieren. Wie kann ich das aus den Basisgrafiken generierte Autokorrelationsdiagramm durch das von ggplot generierte ersetzen? Ich weiß, dass ich grid.arrange verwenden kann, wenn alle meine Figuren mit ggplot erstellt wurden. Wie mache ich das, wenn nur eines der Diagramme in ggplot generiert wird?

KatyB
quelle
3
Es könnte fast genauso einfach sein und konsistenter aussehen, polygonmit der Ausgabe von acf()ein Basisgrafikdiagramm zu erstellen, das demjenigen ähnelt ggplot.
Ben Bolker
Vielen Dank für unsere Antwort. Diese Frage zielt wirklich darauf ab zu lernen, wie man ggplot- und Basisgrafiken in einem Figurenfenster kombiniert. Ich erkenne, dass es effizientere Möglichkeiten gibt, die gezeigte Figur zu erzeugen, aber für zukünftige Zwecke möchte ich die angegebene Methode lernen.
KatyB
3
Schauen Sie sich das gridBasePaket an ...
Ben Bolker
Vielleicht gridGraphicsmöchten Sie sich das Paket ansehen , das "Basisgrafiken als Rastergrafiken [neu zeichnet]".
Maj
Obwohl es als dupliziert markiert ist, hat diese Antwort für mich sehr gut funktioniert
Antoni

Antworten:

52

Mit dem gridBase-Paket können Sie dies einfach durch Hinzufügen von 2 Zeilen tun. Ich denke, wenn Sie eine lustige Handlung mit dem Raster machen möchten, müssen Sie nur die Ansichtsfenster verstehen und beherrschen . Es ist wirklich das Grundobjekt des Grid-Pakets.

vps <- baseViewports()
pushViewport(vps$figure) ##   I am in the space of the autocorrelation plot

Die Funktion baseViewports () gibt eine Liste von drei Rasteransichtsfenstern zurück. Ich verwende hier Abbildung Ansichtsfenster Ein Ansichtsfenster, das dem Bildbereich des aktuellen Diagramms entspricht.

So sieht die endgültige Lösung aus:

Geben Sie hier die Bildbeschreibung ein

library(gridBase)
library(grid)

par(mfrow=c(2, 2))
plot(y,type = "l",xlab = "Time (hours)",ylab = "Amplitude",main = "Time series")
plot(wt.t1, plot.cb=FALSE, plot.phase=FALSE,main = "Continuous wavelet transform",
     ylab = "Period (hours)",xlab = "Time (hours)")
spectrum(y,method = "ar",main = "Spectral density function", 
         xlab = "Frequency (cycles per hour)",ylab = "Spectrum")
## the last one is the current plot
plot.new()              ## suggested by @Josh
vps <- baseViewports()
pushViewport(vps$figure) ##   I am in the space of the autocorrelation plot
vp1 <-plotViewport(c(1.8,1,0,1)) ## create new vp with margins, you play with this values 
require(ggplot2)
acz <- acf(y, plot=F)
acd <- data.frame(lag=acz$lag, acf=acz$acf)
p <- ggplot(acd, aes(lag, acf)) + geom_area(fill="grey") +
  geom_hline(yintercept=c(0.05, -0.05), linetype="dashed") +
  theme_bw()+labs(title= "Autocorrelation\n")+
  ## some setting in the title to get something near to the other plots
  theme(plot.title = element_text(size = rel(1.4),face ='bold'))
print(p,vp = vp1)        ## suggested by @bpatiste
Agstudy
quelle
Ja, ich habe dies versucht. Das Problem dabei ist, dass der mit ggplot generierte Plot viel größer ist als die anderen Panels (wie Sie oben sehen können). Gibt es eine Methode, um dies zu ändern?
KatyB
@ Kate Ich habe meine Antwort aktualisiert.
Agstudy
+1 Sehr schön. Wenn Sie den Anruf an acf(...)durch einen Anruf an ersetzen plot.new(), müssen Sie nicht anrufen , um grid.rect()das ACF-Diagramm zu "verdunkeln".
Josh O'Brien
1
Nur b / c kam ich zurück und sah, dass Sie diese viel einfachere und klügere Antwort hinzugefügt hatten.
Josh O'Brien
@ JoshO'Brien Vielen Dank!
Agstudy
15

Sie können den Druckbefehl mit einem Grob und einem Ansichtsfenster verwenden.
Zeichnen Sie zuerst Ihre Basisgrafiken und fügen Sie dann das ggplot hinzu

library(grid)

# Let's say that P is your plot
P <- ggplot(acd, # etc... )

# create an apporpriate viewport.  Modify the dimensions and coordinates as needed
vp.BottomRight <- viewport(height=unit(.5, "npc"), width=unit(0.5, "npc"), 
                           just=c("left","top"), 
                           y=0.5, x=0.5)

# plot your base graphics 
par(mfrow=c(2,2))
plot(y,type #etc .... )

# plot the ggplot using the print command
print(P, vp=vp.BottomRight)
Ricardo Saporta
quelle
Hallo Ricardo. Wissen Sie, wie Sie die Breite der Diagramme mit Ihrer Methode steuern können? Zum Beispiel möchte ich eine Basisgrafik und eine ggplot2-Grafik nebeneinander, aber mit einer größeren Breite für die Basisgrafik.
Stéphane Laurent
Hallo Stéphane, Sie können dies erreichen, indem Sie die Einstellungen in der viewport()Zeile anpassen . Insbesondere möchten Sie widthden yWert anpassen und mit verschiedenen Werten experimentieren, bis Sie die gewünschten Ergebnisse erhalten.
Ricardo Saporta
Vielen Dank, Ricardo. Eigentlich habe ich hier eine Frage gestapelt stackoverflow.com/questions/14358526/…
Stéphane Laurent
7

Ich bin ein Fan des GridGraphics-Pakets. Aus irgendeinem Grund hatte ich Probleme mit gridBase.

library(ggplot2)
library(gridGraphics)
data.frame(x = 2:10, y = 12:20) -> dat
plot(dat$x, dat$y)
grid.echo()
grid.grab() -> mapgrob
ggplot(data = dat) + geom_point(aes(x = x, y = y)) 
pushViewport(viewport(x = .8, y = .4, height = .2, width = .2))    
grid.draw(mapgrob)

Geben Sie hier die Bildbeschreibung ein

Chris
quelle
6

cowplotDas Paket verfügt über eine recordPlot()Funktion zum Erfassen von Basis-R-Plots, damit diese in plot_grid()Funktion zusammengestellt werden können.

library(biwavelet)
library(ggplot2)
library(cowplot)
library(gridGraphics)

t <- c(1:(24*14)) 
P <- 24 
A <- 10 
y <- A*sin(2*pi*t/P)+20

plot(y,type = "l",xlab = "Time (hours)",ylab = "Amplitude",main = "Time series")
### record the previous plot
p1 <- recordPlot()  

spectrum(y,method = "ar",main = "Spectral density function", 
         xlab = "Frequency (cycles per hour)",ylab = "Spectrum")
p2 <- recordPlot()

t1 <- cbind(t, y)
wt.t1=wt(t1)
plot(wt.t1, plot.cb=FALSE, plot.phase=FALSE,main = "Continuous wavelet transform",
     ylab = "Period (hours)",xlab = "Time (hours)")
p3 <- recordPlot()

acz <- acf(y, plot=F)
acd <- data.frame(lag=acz$lag, acf=acz$acf)
p4 <- ggplot(acd, aes(lag, acf)) + geom_area(fill="grey") +
  geom_hline(yintercept=c(0.05, -0.05), linetype="dashed") +
  theme_bw()

### combine all plots together
plot_grid(p1, p4, p2, p3,
          labels = 'AUTO',
          hjust = 0, vjust = 1)

Erstellt am 17.03.2019 durch das reprex-Paket (v0.2.1.9000)

Tung
quelle