Organisering og layout av figurer med flere paneler

I kapittelet Facets (Subgrafer) ble det vist hvordan en kategorisk variabel kan brukes til å lage flere subgrafer (facets) som presenterer undergrupper av data. Dette gjøres med funksjoner i ggplot2 (facet_wrap() og facet_grid()). Disse funksjonene kan ikke brukes til å plassere separate grafer ved siden av hverandre. Til det formålet trengs tilleggspakker til ggplot2. De to mest populære pakkene er gridExtra og cowplot. Her vises bare cowplot, fordi den tilbyr alle funksjoner som trengs, også for de mest avanserte brukerne. Cowplot har en intuitiv syntaks og lager enhetlige og organiserte layouter med svært høy fleksibilitet.

Begynn med å installere og aktivere cowplot. Aktiver også tidyverse, som blant annet inneholder ggplot2, og gapminder, som inneholder øvingsdata.

install.packages("cowplot")

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

## Inspiser de første 5 radene 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 radene i gapminder.

For å organisere flere grafer i en layout må hver graf lagres som et objekt. Objektene i dette kapittelet kalles plot_1, plot_2, plot_3 og plot_4. Forskjellen mellom disse grafene vil være liten, men det har ingen betydning for å vise hvordan grafer organiseres.

Vi begynner med å lage plot_1, plot_2, plot_3 og plot_4 med data fra gapminder. Forskjellen mellom grafene nedenfor er bare hva som står på x-aksen og y-aksen, samt fargetemaet.

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

## Andre 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 bruker nå plot_grid() fra cowplot til å organisere plot_1 og plot_2 i én figur med 2 kolonner (ncol). Vi lager også labels, som vist nedenfor.

plot_grid(plot_1, plot_2, ncol = 2, labels = c('A', 'B'))
To spredningsdiagrammer side om side, A: log(lifeExp) mot log(pop) og B: kontinent mot log(pop), farget etter år

Figurene kan i stedet plasseres vertikalt ved å endre ncol til ncol=1. Nedenfor bruker vi labels="AUTO" i stedet for å få etiketter automatisk.

plot_grid(plot_1, plot_2, ncol = 1, labels = "AUTO")
De samme to spredningsdiagrammene stablet vertikalt med etikettene A og B, henholdsvis log(lifeExp) og kontinent mot log(pop)

Vi kan også bruke align="h" for horisontal plassering av figurer, og align="v" for vertikal plassering.

plot_grid(plot_1, plot_2, aligh = "h")
To spredningsdiagrammer side om side, A: log(lifeExp) mot log(pop) og B: kontinent mot log(pop), farget etter år

Vi kan justere hvor stor andel av plassen hver graf skal ta opp med argumentet rel_widths(). Nedenfor får den første grafen halvparten (1) så mye plass som den andre grafen (2).

plot_grid(plot_1, plot_2, ncol=2, rel_widths = c(1, 2))
To spredningsdiagrammer side om side der det høyre panelet, kontinent mot log(pop), er dobbelt så bredt som det venstre

Legg merke til at tittelen på y-aksen i den øvre figuren i grafen nedenfor står lenger fra tallene på y-aksen.

plot_grid(plot_1, plot_2, ncol = 1, align = 'v')
To vertikalt stablede spredningsdiagrammer der tittelen log(lifeExp) på den øvre y-aksen står lenger fra aksen enn på den nedre

Når figurene i en plot_grid() ikke står på linje med hensyn til titler og akser, brukes argumentet axis for å justere dette. Axis har argumentene none, l (left), r (right), b (bottom) og t (top). Du kan bruke ett eller flere av disse for å justere den aktuelle siden. Nedenfor justerer vi grafene mot venstre med axis="l".

plot_grid(plot_1, plot_2, ncol = 1, align = 'v', axis = 'l')
To vertikalt stablede spredningsdiagrammer venstrejustert slik at y-aksene for log(lifeExp) og kontinent står på linje

Du kan lage tomme figurfelt med argumentet NULL i plot_grid(). Nedenfor lager vi en matrise med fire figurer, der to er NULL, og vi legger til etiketter automatisk.

plot_grid(
  plot_1, NULL, NULL, plot_2,
  labels = "AUTO",
  ncol = 2
)
Rutenett to ganger to med spredningsdiagrammer i rute A og D og tomme ruter B og C

Du kan lage matriser med figurer på flere rader og med ulik størrelse på radene. Dette gjøres ved å lage flere plot_grid() som deretter brukes som objekter i en endelig plot_grid().

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

## Andre rad med plot_grid()
middle_row <- plot_grid(plot_3, labels=c("C"))

## Tredje rad 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 rader med fem paneler A til E: to diagrammer øverst, ett bredt i midten og to nederst, data fra gapminder

Felles overskrift for mange paneler

Med plot_grid() kan man gi hvert panel en label, og selve panelet kan ha en tittel laget med ggplot(). Det kan likevel være ønskelig å ha en tittel som strekker seg over flere paneler. Dette oppnår man med ggdraw(), slik:

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) +
  # Legger til en marg på 7 piksler til venstre, slik at tittelen står på linje med det første panelet
  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) # tittelen får en liten andel av høyden
)
To spredningsdiagrammer A og B under en felles overskrift i fet skrift som strekker seg over begge panelene

Overlappe figurer

Det kan være nyttig å overlappe figurer for å vise sammenhenger tydeligere. Dette er nyttig dersom figurene deler en akse (oftest x-aksen). Hvis to figurer har samme x-akse, men ulike y-akser, kan figurene overlappes slik at sammenhengen mellom x-aksen og begge y-aksene kan visualiseres med overlapping. Dette kan noen ganger gi tydeligere illustrasjoner, selv om gevinsten (sammenlignet med to separate figurer plassert ved siden av hverandre) egentlig er ganske liten.

Til denne øvelsen bruker vi mpg-data (miles per gallon), som inneholder data om drivstofforbruk (variablene cty og hwy) for ulike biler. Disse dataene finnes i tidyverse, noe som betyr at de bør være tilgjengelige nå (ellers må tidyverse aktiveres med kommandoen library(tidyverse)). Begynn med å inspisere dataene:

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 lager den første figuren (se kommentarene for forklaringer) slik:

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

plot_1
Boksplott av hwy per bilprodusent med roterte produsentnavn på x-aksen, uten rutenett

Legg merke til at figuren ikke har linjer på høyre side og øverst. Vi fortsetter med den andre figuren:

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

plot_2
Punktdiagram av cty per produsent farget etter drv, med y-aksen til høyre og uten tekst på x-aksen

Til slutt skal disse to grafene overlappes. Dette gjøres med align_plots() og ggdraw(), slik:

## Plasser grafene oppå hverandre
aligned_plots <- align_plots(plot_1, plot_2, align="hv", axis="tblr")

## Vis den ferdige grafen
ggdraw(aligned_plots[[1]]) + draw_plot(aligned_plots[[2]])
Boksplott av hwy og punktdiagram av cty per bilprodusent lagt oppå hverandre med hwy-akse til venstre og cty-akse til høyre