Domanda

Vorrei affiancare due lotti a fianco utilizzando il ggplot2 pacchetto , vale a dire fare l'equivalente di par(mfrow=c(1,2)).

Per esempio, mi piacerebbe avere le seguenti due grafici mostrano fianco a fianco con la stessa scala.

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

Devo metterli nella stessa data.frame?

qplot(displ, hwy, data=mpg, facets = . ~ year) + geom_smooth()
È stato utile?

Soluzione

Eventuali ggplots side-by-side (o n trame su una griglia)

La grid.arrange() funzione nel pacchetto gridExtra combinerà multipla trame; questo è il modo di mettere due fianco a fianco.

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

Questo è utile quando le due trame non si basano sugli stessi dati, per esempio, se si desidera tracciare diverse variabili senza l'utilizzo di rimodellare ().

In questo modo tracciare l'uscita come un effetto collaterale. Per stampare l'effetto collaterale di un file, specificare un driver di periferica (come pdf, png, ecc), per es.

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

In alternativa, utilizzare arrangeGrob() in combinazione con ggsave(),

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

Questa è l'equivalente di fare due lotti distinti utilizzando par(mfrow = c(1,2)). Questa volta non solo consente di risparmiare l'organizzazione dei dati, è necessario quando si vuole due lotti differenti.


Appendice: Utilizzo Sfaccettature

sfaccettature sono utili per realizzare grafici simili per i diversi gruppi. Questo si evidenzia di seguito in molte risposte qui sotto, ma voglio sottolineare questo approccio con esempi equivalenti alle trame di cui sopra.

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)

Aggiornamento

la funzione plot_grid nel cowplot è la pena di verificare come alternativa alla grid.arrange. Vedere le rispondere da @ Claus-wilke qui sotto e questo vignetta per un approccio equivalente; ma la funzione consente controlli più sottili sul posto trama e dimensioni, in base a questa vignetta .

Altri suggerimenti

Un difetto delle soluzioni basate su grid.arrange è che essi rendono difficile etichettare le trame con le lettere (A, B, ecc), come la maggior parte delle riviste richiedono.

ho scritto il cowplot pacchetto per risolvere questo ( e poche altre) questioni, in particolare la funzione di 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")

entrare descrizione dell'immagine qui

L'oggetto che plot_grid() rendimenti è un altro oggetto ggplot2, ed è possibile salvarlo con ggsave() come al solito:

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

In alternativa, è possibile utilizzare la funzione di cowplot save_plot(), che è un sottile wrapper ggsave() che rende facile per ottenere le dimensioni corrette per trame combinate, per esempio:.

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

(L'argomento ncol = 2 racconta save_plot() che ci sono due terreni side-by-side, e save_plot() rende l'immagine salvata due volte più largo.)

Per una descrizione più approfondita di come organizzare trame in una griglia vedi questa vignetta. C'è anche una vignetta che spiega come fare trame con un leggenda condivisa.

Un punto di confusione frequente è che il pacchetto cowplot cambia il tema di default ggplot2. Il pacchetto si comporta in quel modo perché è stato scritto originariamente per usi di laboratorio interni, e non abbiamo mai utilizzare il tema di default. Se questo causa problemi, è possibile utilizzare uno dei seguenti tre metodi per lavorare intorno a loro:

1. Impostare il tema manualmente per ogni trama. Penso che sia buona norma indicare sempre un tema particolare per ogni trama, proprio come ho fatto con + theme_bw() nell'esempio di cui sopra. Se si specifica un particolare tema, il tema di default non ha importanza.

2. Ripristinare il tema predefinito al valore predefinito ggplot2 Si può fare questo con una sola riga di codice:.

theme_set(theme_gray())

3. Chiamare funzioni cowplot senza associare il pacchetto. Puoi anche non chiamare library(cowplot) o require(cowplot) invece chiamare le funzioni cowplot anteponendo cowplot::. Per esempio, l'esempio precedente utilizzando il tema di default ggplot2 sarebbe diventato:

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

entrare descrizione dell'immagine qui

Aggiornamenti:

  • A partire dal cowplot 1.0, il tema di default ggplot2 non viene modificato più.
  • A partire dal ggplot2 3.0.0, trame possono essere etichettati direttamente, vedi per esempio qui.

È possibile utilizzare la seguente funzione multiplot da R libro di ricette di Winston Chang

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

}

Sì, mi pare è necessario organizzare i dati in modo appropriato. Un modo potrebbe essere questo:

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

Sono sicuro che ci sono trucchi migliori in plyr o rimodellare - io non sono ancora molto fino a velocità su tutti questi potenti pacchetti di Hadley.

Usando il pacchetto Reshape si può fare qualcosa di simile.

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)

Aggiornamento: Questa risposta è molto vecchio. gridExtra::grid.arrange() è ora l'approccio consigliato. Lascio questo qui nel caso che potrebbe essere utile.


postato la funzione arrange() su Come Genetica Fatto blog (vedi post per le istruzioni di applicazione)

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 si basa sulla grafica della griglia, che forniscono un sistema diverso per l'organizzazione di trame in una pagina. Il comando par(mfrow...) non ha un equivalente diretto, come oggetti griglia (chiamato grobs ) non sono necessariamente disegnati immediatamente, ma possono essere memorizzati e manipolati come oggetti regolare R prima di essere convertito in un output grafico. Questo consente una maggiore flessibilità rispetto al disegnare questo ora il modello di grafica di base, ma la strategia è necessariamente un po 'diverso.

ho scritto grid.arrange() per fornire una semplice interfaccia il più vicino possibile ai par(mfrow). Nella sua forma più semplice, il codice sarà simile:

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)

 entrare descrizione dell'immagine qui

Altre opzioni sono dettagliate nel questa vignetta .

Una lamentela comune è che trame non sono necessariamente allineati per esempio quando hanno etichette dell'asse di dimensioni diverse, ma questo è di progettazione: grid.arrange non cerca di oggetti ggplot2 casi speciali, e li tratta anche per altri grobs (trame reticolari, per esempio). Viene semplicemente grobs in pianta rettangolare.

Per il caso speciale di oggetti ggplot2, ho scritto un'altra funzione, ggarrange, con un'interfaccia simile, che tenta di allineare pannelli terreno (compresa piazzole sfaccettati) e cerca di rispettare le proporzioni quando definito dall'utente.

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

Entrambe le funzioni sono compatibili con ggsave(). Per una panoramica generale delle diverse opzioni, e alcuni contesto storico, questo vignetta offre informazioni aggiuntive .

C'è anche multipanelfigure pacchetto che vale la pena di menzionare. Vedi anche rispondere .

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

Creato il 2018/07/06 dal reprex pacchetto (v0.2.0.9000).

Utilizzando 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

entrare descrizione dell'immagine qui

Le soluzioni di cui sopra potrebbero non essere efficiente se si desidera tracciare molteplici trame ggplot utilizzando un ciclo (ad esempio, come chiesto qui: Creazione di più trame in ggplot con differenti valori dell'asse Y utilizzando un loop), che è un passo desiderato nell'analisi sconosciuto (o grandi) insiemi di dati (ad esempio, quando si vuole tracciare conti di tutte le variabili in un data-set).

Il codice seguente mostra come farlo utilizzando il sopra menzionato 'multiplo ()', la cui sorgente è qui: 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)
}

Ora eseguire la funzione - per ottenere conteggi per tutte le variabili stampati utilizzando ggplot in un'unica pagina

dt = ggplot2::diamonds
plotAllCounts(dt)

Una cosa da notare è che:
 utilizzando aes(get(strX)), che si usa normalmente in loop quando si lavora con ggplot, nel codice qui sopra, invece di aes_string(strX) NON trarrà le trame desiderati. Sarà invece tracciare la trama ultima molte volte. Non ho capito perché -. Si può avere a che fare il aes e aes_string vengono chiamati in ggplot

In caso contrario, spero troverete la funzione utile.

Il pacchetto cowplot ti dà un bel modo per fare questo, in modo che si adatta pubblicazione.

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

entrare descrizione dell'immagine qui

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top