--- title: "ggplot2 examples and exercises" subtitle: "slides 50-72" output: html_document author: Thomas Lin Pederson (slightly modified by Elizabeth Stanny) --- ```{r setup, include=FALSE} knitr::opts_chunk$set(echo = TRUE, warning = FALSE, message = FALSE) ``` ```{r load-packages, echo=FALSE} library(pacman) #load package manager p_load(tidyverse, maps, sf, patchwork) theme_set(theme_minimal()) # change plot theme for all plots ``` ### Facets The facet defines how data is split among panels. The default facet (`facet_null()`) puts all the data in a single panel, while `facet_wrap()` and `facet_grid()` allows you to specify different types of small multiples ```{r facet-wrap-slide-51} ## This is the preferred method now ## Use vars(class) instead of ~ class ## See https://ggplot2.tidyverse.org/reference/facet_wrap.html ggplot(mpg) + geom_point(aes(x = displ, y = hwy)) + facet_wrap(vars(class)) ``` ```{r facet-grid-slide-52} ## See https://ggplot2.tidyverse.org/reference/facet_grid.html ggplot(mpg) + geom_point(aes(x = displ, y = hwy)) + facet_grid(rows = vars(year), cols = vars(drv)) ``` #### Exercises facet One of the great things about facets is that they share the axes between the different panels. Sometimes this is undesirable though, and the behaviour can be changed with the `scales` argument. Experiment with the different possible settings in the plot below: ```{r facet-ex-1} ggplot(mpg) + geom_point(aes(x = displ, y = hwy)) + facet_wrap(vars(drv)) ``` * * * Usually the space occupied by each panel is equal. This can create problems when different scales are used. Modify the code below so that the y scale differs between the panels in the plot. What happens? ```{r facet-ex-2} ggplot(mpg) + geom_bar(aes(y = manufacturer)) + facet_grid(rows = vars(class)) ``` Use the `space` argument in `facet_grid()` to change the plot above so each bar has the same width again. * * * Facets can be based on multiple variables by adding them together. Try to recreate the same panels present in the plot below by using `facet_wrap()` ```{r facet-ex-3} ggplot(mpg) + geom_point(aes(x = displ, y = hwy)) + facet_grid(rows = vars(year), cols = vars(drv)) ggplot(mpg) + geom_point(aes(x = displ, y = hwy)) + facet_wrap(vars(year, drv)) ``` ### Coordinates The coordinate system is the fabric you draw your layers on in the end. The default `coord_cartesion provides the standard rectangular x-y coordinate system. Changing the coordinate system can have dramatic effects ```{r coord-slide-54} ggplot(mpg) + geom_bar(aes(x = class)) + coord_polar() ``` ```{r coord-slide-55} ggplot(mpg) + geom_bar(aes(x = class)) + coord_polar(theta = 'y') + expand_limits(y = 70) ``` You can zoom both on the scale... ```{r coord-slide-56} ggplot(mpg) + geom_bar(aes(x = class)) + scale_y_continuous(limits = c(0, 40)) ``` and in the coord. You usually want the latter as it avoids changing the plotted data ```{r coord-slide-57} ggplot(mpg) + geom_bar(aes(x = class)) + coord_cartesian(ylim = c(0, 40)) ``` #### Coordinates exercises In the same way as limits can be set in both the positional scale and the coord, so can transformations, using `coord_trans()`. Modify the code below to apply a log transformation to the y axis; first using `scale_y_continuous()`, and then using `coord_trans()`. Compare the results — how do they differ? ```{r coord-ex-1} ggplot(mpg) + geom_point(aes(x = hwy, y = displ)) ggplot(mpg) + geom_point(aes(x = hwy, y = displ)) + scale_y_log10() ggplot(mpg) + geom_point(aes(x = hwy, y = displ)) + coord_trans(y = "log10") ``` * * * Coordinate systems are particularly important in cartography. While we will not spend a lot of time with it in this workshop, spatial plotting is well supported in ggplot2 with `geom_sf()` and `coord_sf()` (which interfaces with the sf package). The code below produces a world map. Try changing the `crs` argument in `coord_sf()` to be `'+proj=robin'` (This means using the Robinson projection). ```{r coord-ex-2} # Get the borders of all countries world <- sf::st_as_sf(maps::map('world', plot = FALSE, fill = TRUE)) world <- sf::st_wrap_dateline(world, options = c("WRAPDATELINE=YES", "DATELINEOFFSET=180"), quiet = TRUE) # Plot code ggplot(world) + geom_sf() + coord_sf(crs = "+proj=moll") ``` Maps are a huge area in data visualisation and simply too big to cover in this workshop. If you want to explore further I advice you to explore the [r-spatial wbsite](https://www.r-spatial.org) as well as the website for the [sf package](https://r-spatial.github.io/sf) ### Theme Theming defines the feel and look of your final visualisation and is something you will normally defer to the final polishing of the plot. It is very easy to change looks with a prebuild theme ```{r theme-slide-59} ggplot(mpg) + geom_bar(aes(y = class)) + facet_wrap(vars(year)) + theme_minimal() ``` Further adjustments can be done in the end to get exactly the look you want ```{r theme-slide-60} ggplot(mpg) + geom_bar(aes(y = class)) + facet_wrap(vars(year)) + labs(title = "Number of car models per class", caption = "source: http://fueleconomy.gov", x = NULL, y = NULL) + scale_x_continuous(expand = c(0, NA)) + theme_minimal() + theme( text = element_text('Avenir Next Condensed'), strip.text = element_text(face = 'bold', hjust = 0), plot.caption = element_text(face = 'italic'), panel.grid.major = element_line('white', size = 0.5), panel.grid.minor = element_blank(), panel.grid.major.y = element_blank(), panel.ontop = TRUE ) ``` #### Theme exercises Themes can be overwhelming, especially as you often try to optimise for beauty while you learn. To remove the last part of the equation, the exercise is to take the plot given below and make it as hideous as possible using the theme function. Go absolutely crazy, but take note of the effect as you change different settings. ```{r theme-ex-1} ggplot(mpg) + geom_bar(aes(y = class, fill = drv)) + facet_wrap(vars(year)) + labs(title = "Number of car models per class", caption = "source: http://fueleconomy.gov", x = 'Number of cars', y = NULL) ``` ## Extensions While ggplot2 comes with a lot of batteries included, the extension ecosystem provides priceless additional features ### Plot composition We start by creating 3 separate plots ```{r patchwork-slide-64} # ?msleep p1 <- ggplot(msleep) + geom_boxplot(aes(x = sleep_total, y = vore, fill = vore)) p1 ``` ```{r patchwork-slide-65} p2 <- ggplot(msleep) + geom_bar(aes(y = vore, fill = vore)) p2 ``` ```{r patchwork-slide-66} p3 <- ggplot(msleep) + geom_point(aes(x = bodywt, y = sleep_total, colour = vore)) + scale_x_log10() p3 ``` Combining them with patchwork is a breeze using the different operators ```{r patchwork-slides-67-72} p1 + p2 + p3 (p1 | p2) / p3 p_all <- (p1 | p2) / p3 p_all + plot_layout(guides = 'collect') p_all & theme(legend.position = 'none') p_all <- p_all & theme(legend.position = 'none') p_all + plot_annotation( title = 'Mammalian sleep patterns', tag_levels = 'A' ) ``` #### Excercises Patchwork will assign the same amount of space to each plot by default, but this can be controlled with the `widths` and `heights` argument in `plot_layout()`. This can take a numeric vector giving their relative sizes (e.g. `c(2, 1)` will make the first plot twice as big as the second). Modify the code below so that the middle plot takes up half of the total space: ```{r patchwork-ex-1} p <- ggplot(mtcars) + geom_point(aes(x = disp, y = mpg)) p + p + p ``` * * * The `&` operator can be used with any type of ggplot2 object, not just themes. Modify the code below so the two plots share the same y-axis (same limits) ```{r patchwork-ex-2} p1 <- ggplot(mtcars[mtcars$gear == 3,]) + geom_point(aes(x = disp, y = mpg)) p2 <- ggplot(mtcars[mtcars$gear == 4,]) + geom_point(aes(x = disp, y = mpg)) p1 + p2 ``` * * * Patchwork contains many features for fine tuning the layout and annotation. Very complex layouts can be obtained by providing a design specification to the `design` argument in `plot_layout()`. The design can be defined as a textual representation of the cells. Use the layout given below. How should the textual representation be understood. ```{r patchwork-ex-3} p1 <- ggplot(mtcars) + geom_point(aes(x = disp, y = mpg)) p2 <- ggplot(mtcars) + geom_bar(aes(x = factor(gear))) p3 <- ggplot(mtcars) + geom_boxplot(aes(x = factor(gear), y = mpg)) layout <- ' AA# #BB C## ' p1 + p2 + p3 + plot_layout(design = layout) ```