Comment puis-je obtenir une grille «déséquilibrée» de ggplots?

94

Avec grid.arrangeje peux organiser plusieurs ggplotfigures dans une grille pour obtenir une figure multi-panneaux en utilisant quelque chose comme:

library(ggplot2)
library(grid)
library(gridExtra)

générer des graphiques ggplot2, puis

plot5 <- grid.arrange(plot4, plot1, heights=c(3/4, 1/4), ncol=1, nrow=2)

Comment puis-je obtenir une disposition à 2 cols «déséquilibrée» avec une parcelle dans tout le premier col et trois parcelles dans le deuxième col? J'ai joué avec une approche `` grille de grilles '' en essayant d'utiliser grid.arrangepour tracer une grille (par exemple plot5, ci-dessus) par rapport à une autre parcelle, mais j'ai obtenu:

Erreur dans arrangeGrob (..., as.table = as.table, clip = clip, main = main,: l'entrée doit être grobs!

Mettre à jour:

Merci pour le conseil. Je vais examiner viewportset grid. En attendant, grâce à @DWin, la layOutfonction du package 'wq' fonctionnait très bien pour la figure de compilation dans mon Sweavedocument: entrez la description de l'image ici

Mise à jour 2:

La arrangeGrobcommande (comme suggéré par @baptiste) fonctionne également bien et semble très intuitive - au moins, il était facile de modifier les largeurs des deux colonnes. Il a également l'avantage de ne pas nécessiter le paquet `wq '.

Par exemple, voici le code de mon fichier Sweave:

<<label=fig5plot, echo=F, results=hide>>=
plot5<-grid.arrange(plot4, arrangeGrob(plot1, plot2, plot3, ncol=1), 
                    ncol=2, widths=c(1,1.2))
@
\begin{figure}[]
    \begin{center}
<<label=fig5,fig=TRUE,echo=T, width=10,height=12>>=
<<fig5plot>>
@
\end{center}
\caption{Combined plots using the `arrangeGrob' command.}
\label{fig:five}
\end{figure}

qui produit la sortie suivante: entrez la description de l'image ici

BTW, quelqu'un me dit pourquoi le «> NA» apparaît?

utilisateur441706
la source
Vous devrez peut-être configurer les fenêtres vous-même - grid.arrangece n'est peut-être pas assez flexible (recherche stackoverflow pour "[r] grid viewport")
Ben Bolker
2
@BenBolker vous a orienté dans une direction fructueuse en utilisant grid. Voir aussi le livre ggplot2 de Hadley, Section 8.4.2.
Ari B.Friedman
1
@BenBolker grid.arrangepeut être utilisé avec des fenêtres imbriquées en utilisant son compagnon arrangeGrob(renvoyant essentiellement a gTree), comme dans l'exemple que j'ai donné ci-dessous.
baptiste
1
votre affectation finale à plot5n'est pas requise car grid.arrangene renvoie rien (NULL). Si vous voulez sauvegarder le grob résultant, utilisez à arrangeGrobnouveau (et grid.drawpour l'afficher).
baptiste

Réponses:

73

grid.arrangedessine directement sur l'appareil; si vous souhaitez le combiner avec d'autres objets de grille dont vous avez besoin arrangeGrob, comme dans

 p = rectGrob()
 grid.arrange(p, arrangeGrob(p,p,p, heights=c(3/4, 1/4, 1/4), ncol=1),
              ncol=2)

Edit (07/2015): avec v> 2.0.0 vous pouvez utiliser l' layout_matrixargument,

 grid.arrange(p,p,p,p, layout_matrix = cbind(c(1,1,1), c(2,3,4)))
baptiste
la source
6
Pouvez-vous expliquer comment la cbind(c(1,1,1), c(2,3,4))matrice décrit la disposition des figures?
Ron Gejman
5
@RonGejman c'est facile si vous imprimez la matrice 3x2 à l'écran: la première colonne contient tous les 1, c'est là que vit le premier tracé, couvrant les trois lignes; la deuxième colonne contient les graphiques 2, 3, 4, chacun occupant une ligne.
baptiste
17

J'ai essayé de le comprendre avec la grille et je pensais l'avoir en panne mais j'ai fini par échouer (bien qu'en regardant maintenant le code dans la fonction que je cite ci-dessous, je peux voir que j'étais vraiment proche ... :-)

Le package 'wq' a une layOutfonction qui le fera pour vous:

p1 <- qplot(mpg, wt, data=mtcars)
layOut(list(p1, 1:3, 1),   # takes three rows and the first column
        list(p1, 1, 2),    # next three are on separate rows
         list(p1, 2,2), 
          list(p1, 3,2))

entrez la description de l'image ici

IRTFM
la source
Wow, c'est une fonction utile! Je pense que le copier-coller vous a peut-être échoué, cependant; avez - vous dire pour g1, g2, etc à être tous p1?
joran
3
@joran: Je l'ai fait. Je ne me souviens pas laquelle des «trois vertus de la programmation» est la paresse, mais je sais que c'est là quelque part.
IRTFM
Merci! A très bien fonctionné. Voir au dessus.
user441706
2

Une autre alternative est le patchworkpackage de Thomas Lin Pedersen.

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

Générez des graphiques.

p1 <- ggplot(mtcars) + geom_point(aes(mpg, disp)) + facet_grid(rows = vars(gear))
p2 <- ggplot(mtcars) + geom_boxplot(aes(gear, disp, group = gear))
p3 <- ggplot(mtcars) + geom_smooth(aes(disp, qsec))
p4 <- ggplot(mtcars) + geom_bar(aes(carb))

Maintenant, organisez les parcelles.

p1 + (p2 / p3 / p4)

entrez la description de l'image ici

Markus
la source
1

Il existe également un package multipanelfigure qui mérite d'être mentionné. Voir aussi cette réponse .

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 = 3, panel_label_type = "upper-roman")

figure1 %<>%
  fill_panel(q1, column = 1, row = 1:3) %<>%
  fill_panel(q2, column = 2, row = 1) %<>%
  fill_panel(q3, column = 2, row = 2) %<>%
  fill_panel(q4, column = 2, row = 3)
#> `geom_smooth()` using method = 'loess' and formula 'y ~ x'
figure1

Créé le 16/07/2018 par le package reprex (v0.2.0.9000).

Tung
la source