Organisering og layout af figurer med flere paneler

I kapitlet Facets (undergrafer) blev det demonstreret, hvordan en kategorisk variabel kan bruges til at lave flere undergrafer (facets), der præsenterer undergrupper af data. Det gøres med funktioner i ggplot2 (facet_wrap() og facet_grid()). Disse funktioner kan ikke bruges til at placere separate grafer ved siden af hinanden. Til det formål kræves tilføjelsespakker til ggplot2. De to mest populære pakker er gridExtra og cowplot. Her demonstreres kun cowplot, da den tilbyder alle de funktioner, der er brug for, selv for de mest avancerede brugere. Cowplot har en intuitiv syntaks og skaber ensartede og velorganiserede layouts med meget høj fleksibilitet.

Begynd med at installere og aktivere cowplot. Aktivér også tidyverse, som blandt andet indeholder ggplot2, og gapminder, som indeholder øvelsesdata.

install.packages("cowplot")

library(cowplot)
library(tidyverse)
library(gapminder)

## Inspicér de første 5 rækker i gapminder
head(gapminder)
country<fctr> continent<fctr> year<int> lifeExp<dbl> pop<int> gdpPercap<dbl>
Afghanistan Asia 1952 28.801 8425333 779.4453
Afghanistan Asia 1957 30.332 9240934 820.8530
Afghanistan Asia 1962 31.997 10267083 853.1007
Afghanistan Asia 1967 34.020 11537966 836.1971
Afghanistan Asia 1972 36.088 13079460 739.9811
Afghanistan Asia 1977 38.438 14880372 786.1134

De første 5 rækker i gapminder.

For at organisere flere grafer i ét layout skal hver graf gemmes som et objekt. Objekterne i dette kapitel kaldes plot_1, plot_2, plot_3 og plot_4. Forskellen mellem disse grafer vil være lille, men det har ingen betydning for at demonstrere, hvordan grafer organiseres.

Vi begynder med at lave plot_1, plot_2, plot_3 og plot_4 med data fra gapminder. Forskellen på nedenstående grafer er kun, hvad der er på x-aksen og y-aksen, samt farvetemaet.

## Første graf
plot_1 <- ggplot(gapminder, aes(x=log(pop),
                                y=log(lifeExp),
                                color=year)) +
  geom_point() +
  scale_color_viridis_c(option = "plasma") +
  theme(legend.position = "none")

## Anden graf
plot_2 <- ggplot(gapminder, aes(x=log(pop),
                                y=continent,
                                color=year)) +
  geom_point(size=3, alpha=.5) +
  scale_color_viridis_c(option = "magma") +
  theme(legend.position = "none")

## Tredje graf
plot_3 <- ggplot(gapminder, aes(x=log(gdpPercap),
                                y=continent,
                                color=year)) +
  geom_point(size=3, alpha=.5) +
  scale_color_viridis_c(option = "plasma") +
  theme(legend.position = "none")

## Fjerde graf
plot_4 <- ggplot(gapminder, aes(x=gdpPercap,
                                y=continent,
                                color=year)) +
  geom_point(size=3, alpha=.5) +
  scale_color_viridis_c(option = "magma") +
  theme(legend.position = "none")

Vi bruger nu plot_grid() fra cowplot til at organisere plot_1 og plot_2 i én figur med 2 kolonner (ncol). Vi laver også labels, som det fremgår nedenfor.

plot_grid(plot_1, plot_2, ncol = 2, labels = c('A', 'B'))
To punktdiagrammer side om side, A: log(lifeExp) mod log(pop) og B: kontinent mod log(pop), farvet efter år

Figurerne kan i stedet placeres lodret ved at ændre ncol til ncol=1. Nedenfor bruger vi i stedet labels="AUTO" for at få etiketterne automatisk.

plot_grid(plot_1, plot_2, ncol = 1, labels = "AUTO")
De samme to punktdiagrammer stablet lodret med etiketterne A og B, henholdsvis log(lifeExp) og kontinent mod log(pop)

Vi kan også bruge align="h" til vandret placering af figurer og align="v" til lodret placering.

plot_grid(plot_1, plot_2, aligh = "h")
To punktdiagrammer side om side, A: log(lifeExp) mod log(pop) og B: kontinent mod log(pop), farvet efter år

Vi kan justere, hvor stor en andel af pladsen hver graf skal optage, med argumentet rel_widths(). Nedenfor får den første graf halvt (1) så meget plads som den anden graf (2).

plot_grid(plot_1, plot_2, ncol=2, rel_widths = c(1, 2))
To punktdiagrammer side om side, hvor det højre panel, kontinent mod log(pop), er dobbelt så bredt som det venstre

Bemærk i nedenstående graf, at titlen på den øverste figurs y-akse har større afstand til y-aksens tal.

plot_grid(plot_1, plot_2, ncol = 1, align = 'v')
To lodret stablede punktdiagrammer, hvor den øverste y-akses titel log(lifeExp) står længere fra aksen end den nederste

Når figurerne i en plot_grid() ikke står på linje med hensyn til titler og akser, bruges argumentet axis til at justere dette. Axis har værdierne none, l (left), r (right), b (bottom) og t (top). Du kan bruge en eller flere af disse til at justere den pågældende side. Nedenfor venstrejusterer vi graferne med axis="l".

plot_grid(plot_1, plot_2, ncol = 1, align = 'v', axis = 'l')
To lodret stablede punktdiagrammer venstrejusteret, så y-akserne for log(lifeExp) og kontinent står på linje

Du kan lave tomme figurfelter med argumentet NULL i plot_grid(). Nedenfor laver vi en matrix med fire figurer, hvoraf to er NULL, og vi tilføjer etiketter automatisk.

plot_grid(
  plot_1, NULL, NULL, plot_2,
  labels = "AUTO",
  ncol = 2
)
Gitter på to gange to med punktdiagrammer i felt A og D samt tomme felter B og C

Du kan lave matricer med figurer i flere rækker og med varierende størrelser på disse rækker. Det gøres ved at lave flere plot_grid(), som derefter bruges som objekter i en endelig plot_grid().

## Første række med plot_grid()
upper_row <- plot_grid(plot_1, plot_2, ncol = 2, labels=c("A", "B"))

## Anden række med plot_grid()
middle_row <- plot_grid(plot_3, labels=c("C"))

## Tredje række med plot_grid()
bottom_row <- plot_grid(plot_4, plot_1, ncol = 2, labels=c("D", "E"))

## Endelig plot_grid()
plot_grid(upper_row, middle_row, bottom_row, ncol=1)
Layout i tre rækker med fem paneler A til E: to diagrammer øverst, et bredt i midten og to nederst, data fra gapminder

Fælles overskrift for mange paneler

Med plot_grid() kan man give hvert panel en label, og selve panelet kan have en titel lavet med ggplot(). Det kan dog være ønskeligt at have en titel, der strækker sig over flere paneler. Det opnår man med ggdraw(), som følger:

plot_title <- ggdraw() +
  draw_label(
    "Här skriver vi en titel för samtliga paneler på en gång",
    fontface = 'bold',
    x = 0,
    hjust = 0) +
  # Tilføjer en margen på 7 pixels til venstre, så titlen står på linje med det første panel
  theme(plot.margin = margin(0, 0, 0, 7))

plot_row <- plot_grid(plot_1, plot_2, labels="AUTO")

plot_grid(
  plot_title,
  plot_row,
  ncol = 1,
  rel_heights = c(0.1, 1) # titlen får en lille andel af højden
)
To punktdiagrammer A og B under en fælles overskrift med fed skrift, der strækker sig over begge paneler

Overlap figurer

Det kan være nyttigt at lade figurer overlappe for tydeligere at anskueliggøre sammenhænge. Det er nyttigt, hvis figurerne deler en akse (oftest x-aksen). Hvis to figurer har den samme x-akse, men forskellige y-akser, kan figurerne overlappes, så sammenhængen mellem x-aksen og begge y-akser kan visualiseres med overlapning. Det kan undertiden give tydeligere illustrationer, selvom gevinsten (sammenlignet med to separate figurer placeret ved siden af hinanden) egentlig er ret lille.

Til denne øvelse bruger vi mpg-data (miles per gallon), som indeholder data om brændstofforbrug (variablerne cty og hwy) for forskellige biler. Disse data findes i tidyverse, hvilket betyder, at de burde være tilgængelige nu (ellers skal tidyverse aktiveres med kommandoen library(tidyverse)). Begynd med at inspicere data:

head(mpg)
manufacturer <chr> model <chr> displ <dbl> year <int> cyl <int> trans <chr> drv <chr> cty <int> hwy <int> fl <chr>
audi a4 1.8 1999 4 auto(l5) f 18 29 p
audi a4 1.8 1999 4 manual(m5) f 21 29 p
audi a4 2.0 2008 4 manual(m6) f 20 31 p
audi a4 2.0 2008 4 auto(av) f 21 30 p
audi a4 2.8 1999 6 auto(l5) f 16 26 p
audi a4 2.8 1999 6 manual(m5) f 18 26 p

Vi laver den første figur (se kommentarerne for forklaringer) som følger:

plot_1 <- ggplot(mpg, aes(x=manufacturer,
                          y=hwy)) +
  geom_boxplot() +
  # Temaet "half open" har intet gitter og kun to linjer (x-akse og y-akse)
  theme_half_open() +
  theme(
    # Roterer etiketterne på x-aksen 45°
    axis.text.x = element_text(angle = 45, hjust = 1, vjust= 1),
    # Fjerner titlen på x-aksen
    axis.title.x = element_blank())

plot_1
Boksplot af hwy pr. bilproducent med roterede producentnavne på x-aksen, uden gitter

Bemærk, at figuren ikke har linjer i højre side og øverst. Vi fortsætter med den anden figur:

plot_2 <- ggplot(mpg, aes(x=manufacturer,
                          y=cty,
                          color=drv)) +
  geom_point(size=3) +
  # Flytter y-aksen til højre side
  scale_y_continuous(position = "right") +
  # Samme tema som ovenfor
  theme_half_open() +
  # Fjerner titel og etiketter på x-aksen
  theme(axis.text.x = element_blank(),
        axis.title.x = element_blank()) +
  # Bruger et smukt farvetema til color=drv
  scale_color_viridis_d()

plot_2
Punktdiagram af cty pr. producent farvet efter drv, med y-aksen til højre og uden tekst på x-aksen

Til sidst skal de to grafer overlappes. Det gøres med align_plots() og ggdraw(), som følger:

## Placér graferne oven på hinanden
aligned_plots <- align_plots(plot_1, plot_2, align="hv", axis="tblr")

## Vis den færdige graf
ggdraw(aligned_plots[[1]]) + draw_plot(aligned_plots[[2]])
Boksplot af hwy og punktdiagram af cty pr. bilproducent lagt oven på hinanden med hwy-akse til venstre og cty-akse til højre