Frage

Ich möchte von Seite zwei Plots Seite platzieren mit der ggplot2 Paket , also tun das Äquivalent von par(mfrow=c(1,2)).

Zum Beispiel würde Ich mag die beiden folgenden Diagramme zeigen Seite an Seite haben, mit dem gleichen Maßstab.

x <- rnorm(100)
eps <- rnorm(100,0,.2)
qplot(x,3*x+eps)
qplot(x,2*x+eps)

Habe ich sie in der gleichen data.frame setzen müssen?

qplot(displ, hwy, data=mpg, facets = . ~ year) + geom_smooth()
War es hilfreich?

Lösung

Jeder ggplots Seite-an-Seite (oder n Plots auf einem Gitter)

Die Funktion grid.arrange() im gridExtra Paket kombiniert mehrere Grundstücke; Dies ist, wie Sie zwei nebeneinander setzen.

require(gridExtra)
plot1 <- qplot(1)
plot2 <- qplot(1)
grid.arrange(plot1, plot2, ncol=2)

Dies ist nützlich, wenn die beiden Parzellen nicht auf den gleichen Daten basieren, zum Beispiel, wenn Sie verschiedene Variablen darstellen mögen, ohne neu zu gestalten () zu verwenden.

Das wird die Ausgabe als Nebeneffekt zeichnen. Um die Nebenwirkung in eine Datei zu drucken, geben Sie einen Gerätetreiber (wie pdf, png, usw.), z.

pdf("foo.pdf")
grid.arrange(plot1, plot2)
dev.off()

oder Verwendung arrangeGrob() in Kombination mit ggsave(),

ggsave("foo.pdf", arrangeGrob(plot1, plot2))

Dies ist das Äquivalent zur Herstellung von zwei verschiedenen Parzellen mit par(mfrow = c(1,2)). Das spart nicht nur Zeit, Datenanordnungs, es ist notwendig, wenn Sie zwei unterschiedlichen Grund wollen.


Anhang: Mit Facets

facettiert sind nützlich für die Herstellung von ähnlichen Plots für verschiedene Gruppen. Dies wird im Folgenden unten in vielen Antworten darauf hingewiesen, aber ich mag mit Beispielen äquivalent zu den oben genannten Grundstücken, diesen Ansatz markieren.

mydata <- data.frame(myGroup = c('a', 'b'), myX = c(1,1))

qplot(data = mydata, 
    x = myX, 
    facets = ~myGroup)

ggplot(data = mydata) + 
    geom_bar(aes(myX)) + 
    facet_wrap(~myGroup)

Update

die plot_grid Funktion im cowplot ist ein Besuch wert als eine alternative zu grid.arrange. Siehe beantworten von @ claus-Wilke unten und diese Vignette für einen gleichwertigen Ansatz; aber die Funktion erlaubt eine feinere Steuerung auf einem Grundstück Lage und Größe, basierend auf diese Vignette .

Andere Tipps

Ein Nachteil der auf grid.arrange basierten Lösungen ist, dass sie es schwierig machen, die Plots mit Buchstaben (A, B, etc.) zu beschriften, da die meisten Zeitschriften benötigen.

Ich schrieb die cowplot Paket zur Lösung dieses ( und ein paar andere) Fragen, insbesondere die Funktion plot_grid():

library(cowplot)

iris1 <- ggplot(iris, aes(x = Species, y = Sepal.Length)) +
  geom_boxplot() + theme_bw()

iris2 <- ggplot(iris, aes(x = Sepal.Length, fill = Species)) +
  geom_density(alpha = 0.7) + theme_bw() +
  theme(legend.position = c(0.8, 0.8))

plot_grid(iris1, iris2, labels = "AUTO")

Das Objekt, das zurückkehrt plot_grid() ist ein weiteres ggplot2 Objekt, und Sie können es mit ggsave() wie gewohnt speichern:

p <- plot_grid(iris1, iris2, labels = "AUTO")
ggsave("plot.pdf", p)

Alternativ können Sie die Funktion cowplot save_plot() verwenden, die eine dünne Hülle um ggsave() ist, dass es leicht zu bekommen, die richtigen Maße für den kombinierten Plots macht, z.

p <- plot_grid(iris1, iris2, labels = "AUTO")
save_plot("plot.pdf", p, ncol = 2)

(Das ncol = 2 Argument teilt save_plot(), dass es zwei Grundstücke Seite an Seite, und save_plot() macht das gespeicherte Bild doppelt so breit.)

Für eine tiefer gehende Beschreibung, wie Plots in einem Raster anzuordnen sehen diese Vignette. Es gibt auch eine Vignette zu erklären, wie Plots machen mit einem shared Legende.

Ein häufiger Punkt der Verwirrung ist, dass das Paket cowplot den Standard ggplot2 Thema ändert. Das Paket verhält sich so, weil es ursprünglich für die interne Labor Anwendungen geschrieben wurde, und wir verwenden nie die Standard-Theme. Wenn diese Probleme verursacht, können Sie eine der folgenden drei Ansätze verwenden, um sie zu arbeiten:

1. Stellen Sie das Thema manuell für jede Handlung. Ich denke, es ist eine gute Praxis ist immer auf ein bestimmtes Thema für jede Handlung angeben, so wie ich mit + theme_bw() im Beispiel oben haben. Wenn Sie ein bestimmtes Thema angeben, wird das Standard-Theme keine Rolle.

2. Revert die Standard-Theme zurück zum ggplot2 default Sie können dies tun mit einer Zeile Code.

theme_set(theme_gray())

3. Rufen Sie cowplot Funktionen, ohne das Paket anzubringen. Sie können auch library(cowplot) oder require(cowplot) nicht nennen und stattdessen cowplot Funktionen aufrufen durch cowplot:: vorangestellt. Zum Beispiel das obige Beispiel die ggplot2 Standard-Theme verwendet werden würde:

## Commented out, we don't call this
# library(cowplot)

iris1 <- ggplot(iris, aes(x = Species, y = Sepal.Length)) +
  geom_boxplot()

iris2 <- ggplot(iris, aes(x = Sepal.Length, fill = Species)) +
  geom_density(alpha = 0.7) +
  theme(legend.position = c(0.8, 0.8))

cowplot::plot_grid(iris1, iris2, labels = "AUTO")

Updates:

  • Ab cowplot 1.0 wird das Standard-ggplot2 Thema nicht mehr geändert werden.
  • Ab ggplot2 3.0.0 können Plots direkt markiert werden, siehe z.B. hier.

Sie können die folgende multiplot Funktion von Winston Chang R Kochbuch

multiplot(plot1, plot2, cols=2)

multiplot <- function(..., plotlist=NULL, cols) {
    require(grid)

    # Make a list from the ... arguments and plotlist
    plots <- c(list(...), plotlist)

    numPlots = length(plots)

    # Make the panel
    plotCols = cols                          # Number of columns of plots
    plotRows = ceiling(numPlots/plotCols) # Number of rows needed, calculated from # of cols

    # Set up the page
    grid.newpage()
    pushViewport(viewport(layout = grid.layout(plotRows, plotCols)))
    vplayout <- function(x, y)
        viewport(layout.pos.row = x, layout.pos.col = y)

    # Make each plot, in the correct location
    for (i in 1:numPlots) {
        curRow = ceiling(i/plotCols)
        curCol = (i-1) %% plotCols + 1
        print(plots[[i]], vp = vplayout(curRow, curCol ))
    }

}

Mit dem Patchwork Paket, können Sie einfach + Operator verwenden:

# install.packages("devtools")
devtools::install_github("thomasp85/patchwork")

library(ggplot2)
p1 <- ggplot(mtcars) + geom_point(aes(mpg, disp))
p2 <- ggplot(mtcars) + geom_boxplot(aes(gear, disp, group = gear))

library(patchwork)
p1 + p2

 Patchwork

Ja, methinks Sie benötigen, um Ihre Daten in geeigneter Weise zu arrangieren. Eine Möglichkeit wäre dies:

X <- data.frame(x=rep(x,2),
                y=c(3*x+eps, 2*x+eps),
                case=rep(c("first","second"), each=100))

qplot(x, y, data=X, facets = . ~ case) + geom_smooth()

Ich bin sicher, dass es bessere Tricks in plyr sind oder neu zu gestalten - ich bin noch nicht so richtig auf Touren über all diese leistungsstarken Pakete von Hadley.

das reshape Paket verwenden Sie so etwas wie dies tun können.

library(ggplot2)
wide <- data.frame(x = rnorm(100), eps = rnorm(100, 0, .2))
wide$first <- with(wide, 3 * x + eps)
wide$second <- with(wide, 2 * x + eps)
long <- melt(wide, id.vars = c("x", "eps"))
ggplot(long, aes(x = x, y = value)) + geom_smooth() + geom_point() + facet_grid(.~ variable)

Update: Diese Antwort ist sehr alt. gridExtra::grid.arrange() ist jetzt die empfohlene Vorgehensweise. Ich lasse dies hier im Fall könnte es nützlich sein.


Stephen Turner veröffentlicht die arrange() Funktion auf Erste Genetics Fertig Blog (siehe Beitrag für Montage-Anleitung)

vp.layout <- function(x, y) viewport(layout.pos.row=x, layout.pos.col=y)
arrange <- function(..., nrow=NULL, ncol=NULL, as.table=FALSE) {
 dots <- list(...)
 n <- length(dots)
 if(is.null(nrow) & is.null(ncol)) { nrow = floor(n/2) ; ncol = ceiling(n/nrow)}
 if(is.null(nrow)) { nrow = ceiling(n/ncol)}
 if(is.null(ncol)) { ncol = ceiling(n/nrow)}
        ## NOTE see n2mfrow in grDevices for possible alternative
grid.newpage()
pushViewport(viewport(layout=grid.layout(nrow,ncol) ) )
 ii.p <- 1
 for(ii.row in seq(1, nrow)){
 ii.table.row <- ii.row 
 if(as.table) {ii.table.row <- nrow - ii.table.row + 1}
  for(ii.col in seq(1, ncol)){
   ii.table <- ii.p
   if(ii.p > n) break
   print(dots[[ii.table]], vp=vp.layout(ii.table.row, ii.col))
   ii.p <- ii.p + 1
  }
 }
}

ggplot2 auf Rastergrafik basiert, die für die Vermittlung Plots auf einer Seite ein anderes System zur Verfügung stellen. Der par(mfrow...) Befehl keine direkte Entsprechung hat, als Gitterobjekte (so genannte Grobs ) ist nicht notwendigerweise sofort gezeichnet, kann aber als reguläre R bevor sie zu einer grafischen Ausgabe umgewandelt werden Objekte gespeichert und manipuliert werden. Dies ermöglicht eine größere Flexibilität als die diese ziehen jetzt Modell der Basis Grafiken, aber die Strategie ist notwendigerweise ein wenig anders.

Ich schrieb grid.arrange() eine einfache Schnittstelle so nahe wie möglich zur Verfügung zu stellen par(mfrow). In seiner einfachsten Form aussehen würde der Code wie:

library(ggplot2)
x <- rnorm(100)
eps <- rnorm(100,0,.2)
p1 <- qplot(x,3*x+eps)
p2 <- qplot(x,2*x+eps)

library(gridExtra)
grid.arrange(p1, p2, ncol = 2)

 image description hier

Weitere Optionen sind in diese Vignette .

Eine gemeinsame Beschwerde ist, dass Grundstücke sind nicht notwendigerweise ausgerichtet z.B. wenn sie Achse Etiketten unterschiedlicher Größe haben, aber dies ist durch Design: grid.arrange keinen Versuch, einen speziellen Fall ggplot2 Objekte macht, und behandelt sie gleichermaßen auf andere Grobs (Gitter Plots, zum Beispiel). Er hat lediglich legt Grobs in einem rechteckigen Grundriss.

Für den speziellen Fall von ggplot2 Objekten, habe ich eine andere Funktion, ggarrange, mit einer ähnlichen Oberfläche, die Plot Platten auszurichten versucht (einschließlich facettiert Plots) und versucht, die Seitenverhältnisse zu achten, wenn es durch den Benutzer definiert.

library(egg)
ggarrange(p1, p2, ncol = 2)

Beide Funktionen sind kompatibel mit ggsave(). Für einen allgemeinen Überblick über die verschiedenen Möglichkeiten, und einigen historischen Kontext, dieses Vignette bietet zusätzliche Informationen .

Es gibt auch multipanelfigure Paket dass zu erwähnen ist, lohnt sich. Siehe auch diese beantworten .

library(ggplot2)
theme_set(theme_bw())

q1 <- ggplot(mtcars) + geom_point(aes(mpg, disp))
q2 <- ggplot(mtcars) + geom_boxplot(aes(gear, disp, group = gear))
q3 <- ggplot(mtcars) + geom_smooth(aes(disp, qsec))
q4 <- ggplot(mtcars) + geom_bar(aes(carb))

library(magrittr)
library(multipanelfigure)
figure1 <- multi_panel_figure(columns = 2, rows = 2, panel_label_type = "none")
# show the layout
figure1

figure1 %<>%
  fill_panel(q1, column = 1, row = 1) %<>%
  fill_panel(q2, column = 2, row = 1) %<>%
  fill_panel(q3, column = 1, row = 2) %<>%
  fill_panel(q4, column = 2, row = 2)
figure1

# complex layout
figure2 <- multi_panel_figure(columns = 3, rows = 3, panel_label_type = "upper-roman")
figure2

figure2 %<>%
  fill_panel(q1, column = 1:2, row = 1) %<>%
  fill_panel(q2, column = 3, row = 1) %<>%
  fill_panel(q3, column = 1, row = 2) %<>%
  fill_panel(q4, column = 2:3, row = 2:3)
figure2

Erstellt am 2018.07.06 von dem reprex Paket (v0.2.0.9000).

Mit tidyverse:

x <- rnorm(100)
eps <- rnorm(100,0,.2)
df <- data.frame(x, eps) %>% 
  mutate(p1 = 3*x+eps, p2 = 2*x+eps) %>% 
  tidyr::gather("plot", "value", 3:4) %>% 
  ggplot(aes(x = x , y = value)) + 
    geom_point() + 
    geom_smooth() + 
    facet_wrap(~plot, ncol =2)

df

Die oben genannten Lösungen nicht effizient sein können, wenn Sie mehrere ggplot Plots mit einer Schleife (zB plotten mögen, wie hier gefragt: Erstellen von mehreren Plots in ggplot mit unterschiedlichen Y-Achsen-Werten eine Schleife ) verwendet, die bei der Analyse der unbekannten ein erwünschter Schritt ist, (oder große) Datensatz (zB wenn Sie wollen Counts aller Variablen in einem Datensatz zeichnen).

Der folgende Code zeigt, wie zu tun, dass die oben genannten ‚Multiplot ()‘ verwendet wird, die Quelle, von denen hier: http://www.cookbook-r.com/Graphs/Multiple_graphs_on_one_page_ (ggplot2) :

plotAllCounts <- function (dt){   
  plots <- list();
  for(i in 1:ncol(dt)) {
    strX = names(dt)[i]
    print(sprintf("%i: strX = %s", i, strX))
    plots[[i]] <- ggplot(dt) + xlab(strX) +
      geom_point(aes_string(strX),stat="count")
  }

  columnsToPlot <- floor(sqrt(ncol(dt)))
  multiplot(plotlist = plots, cols = columnsToPlot)
}

Sie nun die Funktion laufen - bekommen Zählungen für alle gedruckten Variablen auf einer Seite mit ggplot

dt = ggplot2::diamonds
plotAllCounts(dt)

Ein Ding zu beachten ist, dass:
 mit aes(get(strX)), die Sie normalerweise in Schleifen verwenden würden, wenn sie mit ggplot, in dem obigen Code statt aes_string(strX) arbeiten, werden nicht die gewünschten Diagramme zeichnen. Stattdessen wird es die letzte Handlung oft plotten. Ich habe nicht herausgefunden, warum -. Es zu tun hat, kann die aes und aes_string werden in ggplot genannt

Ansonsten hoffen, dass Sie die Funktion nützlich sein.

Das cowplot Paket gibt Ihnen eine schöne Art und Weise, dies zu tun, in einer Weise, die Veröffentlichung entspricht.

x <- rnorm(100)
eps <- rnorm(100,0,.2)
A = qplot(x,3*x+eps, geom = c("point", "smooth"))+theme_gray()
B = qplot(x,2*x+eps, geom = c("point", "smooth"))+theme_gray()
cowplot::plot_grid(A, B, labels = c("A", "B"), align = "v")

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top