Jak mogę uzyskać „niezrównoważoną” siatkę ggplots?

94

Dzięki grid.arrangemogę ułożyć wiele ggplotfigur w siatce, aby uzyskać figurę wielopanelową, używając czegoś takiego:

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

wygeneruj więc kilka wykresów ggplot2

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

Jak mogę uzyskać „niezrównoważony” układ 2-kolumnowy z jednym wykresem w całej pierwszej kolumnie i trzema wykresami w drugiej kolumnie? Bawiłem się podejściem „siatki sieci”, próbując grid.arrangewykreślić jedną siatkę (np. plot5Powyżej) z innym wykresem, ale uzyskałem:

Błąd w aranżacji Grob (..., as.table = as.table, clip = clip, main = main,: wejście musi być grobami!

Aktualizacja:

Dzięki za radę. Zajrzę do viewportsi grid. W międzyczasie dzięki @DWin layOutfunkcja w pakiecie 'wq' działała bardzo dobrze na figurze kompilacji w moim Sweavedokumencie: wprowadź opis obrazu tutaj

Aktualizacja 2:

arrangeGrobPoleceń (jak sugeruje @baptiste) również działa dobrze, i wydaje się bardzo intuicyjny - przynajmniej to było łatwe do zmiany szerokości dwóch kolumnach. Ma również tę zaletę, że nie wymaga pakietu `wq '.

np. Oto kod z mojego pliku 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}

co daje następujący wynik: wprowadź opis obrazu tutaj

BTW, ktoś mi powie, dlaczego pojawia się '> NA'?

user441706
źródło
Konieczne może być samodzielne skonfigurowanie rzutni - grid.arrangemoże nie być wystarczająco elastyczne (
przepełnienie stosu
2
@BenBolker wskazał Ci owocny kierunek za pomocą grid. Zobacz także książkę Hadley o ggplot2, Rozdział 8.4.2.
Ari B. Friedman
1
@BenBolker grid.arrangemoże być używany z zagnieżdżonymi rzutniami przy użyciu jego arrangeGrobelementu towarzyszącego (zasadniczo zwracającego a gTree), jak w przykładzie, który podałem poniżej.
baptiste
1
Twoje ostatnie przypisanie do plot5nie jest wymagane, ponieważ grid.arrangenic nie zwraca (NULL). Jeśli chcesz zapisać wynikowy grob, użyj arrangeGrobponownie (i grid.drawwyświetl go).
baptiste

Odpowiedzi:

73

grid.arrangerysuje bezpośrednio na urządzeniu; jeśli chcesz połączyć go z innymi potrzebnymi obiektami siatki arrangeGrob, jak w

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

Edycja (07/2015): przy v> 2.0.0 można użyć layout_matrixargumentu,

 grid.arrange(p,p,p,p, layout_matrix = cbind(c(1,1,1), c(2,3,4)))
baptiste
źródło
6
Czy mógłbyś wyjaśnić, w jaki sposób cbind(c(1,1,1), c(2,3,4))macierz opisuje rozmieszczenie figur?
Ron Gejman
5
@RonGejman to proste, jeśli wydrukujesz macierz 3x2 na ekranie: pierwsza kolumna to wszystkie jedynki, czyli tam znajduje się pierwszy wykres obejmujący trzy rzędy; druga kolumna zawiera działki 2, 3, 4, z których każda zajmuje jeden rząd.
baptiste
17

Próbowałem to rozgryźć za pomocą siatki i pomyślałem, że to źle, ale skończyło się niepowodzeniem (chociaż patrząc teraz na kod w funkcji, którą cytuję poniżej, widzę, że byłem naprawdę blisko ... :-)

Pakiet 'wq' ma layOutfunkcję, która zrobi to za Ciebie:

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

wprowadź opis obrazu tutaj

IRTFM
źródło
Wow, to przydatna funkcja! Myślę, że kopiowanie + wklejanie mogło cię jednak zawieść; pan myśli o g1, g2itp, aby być w całości p1?
joran
3
@joran: Tak. Nie pamiętam, która z „trzech zalet programowania” to lenistwo, ale wiem, że gdzieś tam jest.
IRTFM
Dzięki! Działało bardzo ładnie. Patrz wyżej.
user441706
2

Inną alternatywą jest patchworkpakiet autorstwa Thomasa Lin Pedersena.

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

Wygeneruj kilka wykresów.

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

Teraz ułóż działki.

p1 + (p2 / p3 / p4)

wprowadź opis obrazu tutaj

markus
źródło
1

Istnieje również pakiet multipanelfigure że warto wspomnieć. Zobacz także tę odpowiedź .

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

Utworzony 2018-07-16 przez pakiet reprex (v0.2.0.9000).

Tung
źródło