class: title-slide
# Plotting data ## with `ggplot2` .center[<img src="img/00/logo_ggplot2.png" width="100px"/>] ### A. Ginolhac | rworkshop | 2021-09-09 --- background-image: url(img/plot_ggplot2_overview.png) background-position: center background-size: contains # ggplot2 --- # About this lecture .flex[ .w-10[ ] .w-70.bg-washed-green.b--green.ba.bw2.br3.shadow-5.ph3.mt3.mr1[ .large[.gbox[Learning objectives] .right[<img src="img/00/kt.png" class="float-img"/>] - Learn the basic grammar of graphics - Understand how it is implemented in `ggplot2` + Input data structures as `data.frame/tibble` + Mapping columns to display features (*aesthetics*) + Types of graphics (*geometries*) + Multiple and repeating graphics (*facets*) + Transforming plots (*scales*) + Using different coordinate systems + Customizing graphs with *themes* - Make quick exploratory plots of your multidimensional data.] ]] --- # Introduction .flex.justify-around[ .w-50.bg-washed-green.b--green.ba.bw2.br3.shadow-5.ph3.mt3.mr1[ .large[.gbox[`ggplot2`]] - stands for **g**rammar of **graphics** plot v2 - Inspired by Leland Wilkinson work on the [grammar of graphics](https://www.amazon.com/Grammar-Graphics-Statistics-Computing/dp/0387245448) in 2005. ] .w-50.bg-washed-yellow.b--gold.ba.bw2.br3.shadow-5.ph3.mt3.mr1[ .large[.bbox[Idea: split a graph into layers]] - such as axis, curve(s), labels. - **3** elements are required: **data**, **aesthetics**, **geometry** `\(\geqslant 1\)` ]] -- .center[<img src="img/plot_graphic_objects.png" style="height: 300px" />] .footnote[[Wickham H. 2007. _J. Comp. Graph. Stat._ **19**:3–28](http://www.tandfonline.com/doi/abs/10.1198/jcgs.2009.07098)] --- background-image: url(img/plot_gglayers.png) background-position: center background-size: contains class: hide_logo # ggplot2 layers .footnote[Adapted from this [article](https://www.thinkr.fr/guide-survie-ggplot2-datajournalistes/) by [Colin Fay](https://thinkr.fr/equipe/colin-fay/) ([thinkR]((https://www.thinkr.fr))] --- background-image: url(img/plot_gglayers_example.png) background-position: center background-size: contains class: hide_logo # ggplot2 layers .footnote[Adapted from this [article](https://www.thinkr.fr/guide-survie-ggplot2-datajournalistes/) by [Colin Fay](https://thinkr.fr/equipe/colin-fay/) ([thinkR]((https://www.thinkr.fr))] --- # Basic example .flex[ .w-33.bg-washed-yellow.b--yellow.ba.bw2.br3.shadow-5.ph3.mt3.mr2[ .large.gbox[data] .large[ x | y | shape ---|-----|------- 25 | 11 | circle 0 | 0 | circle 75 | 53 | square 200| 300| square ]] .w-33.bg-washed-green.b--green.ba.bw2.br3.shadow-5.ph3.mt3.mr2[ .large.gbox[aesthetics] .center[.Large[ - `x = x` - `y = y` - `shape = shape`]] ] .w-33.bg-washed-blue.b--blue.ba.bw2.br3.shadow-5.ph3.mt3.mr1[ .large.bbox[geometry] .center[.Large[ - **dot / point** ]] ] ] .footnote[Wickham: [A Layered Grammar of Graphics](https://www.tandfonline.com/doi/abs/10.1198/jcgs.2009.07098) (2007)] --- # Result .center[] -- .center.huge[What if we want to split into panels _circles_ and _squares_?] --- # Faceting ### Split by **shape**, _aka_ trellis or lattice plots -- .flex[ .w-50.ph3.mt3.mr2[  ] .w-50.bg-washed-yellow.b--yellow.ba.bw2.br3.shadow-5.ph3.mt3.mr2[ .large.gbox[Redundancy 💡] .large[ - **shape** and **facets** provide the same information. - The `shape` aesthetic is free for another variable. ] ] .footnote[Wickham: [A Layered Grammar of Graphics](https://www.tandfonline.com/doi/abs/10.1198/jcgs.2009.07098) (2007) ]] --- background-image: url(img/plot_geofacet.png) background-position: center # Faceting can also carry a message .footnote[[geofacet, US states](https://ryanhafen.com/blog/geofacet/) by Ryan Hafen] --- class: hide_logo # Layers .flex[ .w-50.b--blue.ba.bw2.br3.shadow-5.ph3.mt3.mr2[ .center[] ] .w-50.bg-washed-yellow.b--yellow.ba.bw2.br3.shadow-5.ph5.pb2.mt3.mr2[ .large.gbox[data] .large[ x | y | shape ---|-----|------- 25 | 11 | circle 0 | 0 | circle 75 | 53 | square 200| 300| square ]]] .flex[ .w-60.bg-washed-yellow.b--yellow.ba.bw2.br3.shadow-5.ph4.pb1.mt2.ml6.mr2[ .large.bbox[Motivation for this layered system] .Large[ > *Data visualisation* is not meant just to be seen but to be .bold[read], like written text .tr[ — _Alberto Cairo_] ] ]] --- class: hide_logo # Combine layers but not with pipes! .flex[ .w-60.bg-washed-yellow.b--red.ba.bw2.br3.shadow-5.ph2.pb2.mt2.ml6.mr2[ .large.rbox[Warning]
`ggplot2` layers are combined with .huge[`+`], .bold[not] .Large[`%>%`, `|>`]. This introduces .bold[a break] in the .bolder[workflow]. (`ggplot1` would have been fine) ]] -- .flex[ .w-50.bg-washed-green.b--green.ba.bw2.br3.shadow-5.ph2.pb4.mt2.ml0.mr1[ .large.gbox[`ggplot` lines combined with .Large[`+`]] ```r library(ggplot2) swiss %>% ggplot(aes(x = Education, y = Examination)) + geom_point() + scale_colour_brewer() ``` ] .w-50.bg-washed-red.b--red.ba.bw2.br3.shadow-5.ph2.pb2.mt2.ml0.mr2[ .large.rbox[if not, the error is explicit] ```r swiss %>% ggplot(aes(x = Education, y = Examination)) %>% geom_point() + scale_colour_brewer() ``` ``` Error: `mapping` must be created by `aes()` Did you use %>% instead of +? ``` ]] --- --- count: false # Build a plot by layers .panel1-first_plot-auto[ ```r *swiss ``` ] .panel2-first_plot-auto[ ``` Fertility Agriculture Examination Education Catholic Courtelary 80.2 17.0 15 12 9.96 Delemont 83.1 45.1 6 9 84.84 Franches-Mnt 92.5 39.7 5 5 93.40 Moutier 85.8 36.5 12 7 33.77 Neuveville 76.9 43.5 17 15 5.16 Porrentruy 76.1 35.3 9 7 90.57 Broye 83.8 70.2 16 7 92.85 Glane 92.4 67.8 14 8 97.16 Gruyere 82.4 53.3 12 7 97.67 Sarine 82.9 45.2 16 13 91.38 Veveyse 87.1 64.5 14 6 98.61 Aigle 64.1 62.0 21 12 8.52 Aubonne 66.9 67.5 14 7 2.27 Avenches 68.9 60.7 19 12 4.43 Cossonay 61.7 69.3 22 5 2.82 Echallens 68.3 72.6 18 2 24.20 Grandson 71.7 34.0 17 8 3.30 Lausanne 55.7 19.4 26 28 12.11 La Vallee 54.3 15.2 31 20 2.15 Lavaux 65.1 73.0 19 9 2.84 Morges 65.5 59.8 22 10 5.23 Moudon 65.0 55.1 14 3 4.52 Nyone 56.6 50.9 22 12 15.14 Orbe 57.4 54.1 20 6 4.20 Oron 72.5 71.2 12 1 2.40 Payerne 74.2 58.1 14 8 5.23 Paysd'enhaut 72.0 63.5 6 3 2.56 Rolle 60.5 60.8 16 10 7.72 Vevey 58.3 26.8 25 19 18.46 Yverdon 65.4 49.5 15 8 6.10 Conthey 75.5 85.9 3 2 99.71 Entremont 69.3 84.9 7 6 99.68 Herens 77.3 89.7 5 2 100.00 Martigwy 70.5 78.2 12 6 98.96 Monthey 79.4 64.9 7 3 98.22 St Maurice 65.0 75.9 9 9 99.06 Sierre 92.2 84.6 3 3 99.46 Sion 79.3 63.1 13 13 96.83 Boudry 70.4 38.4 26 12 5.62 La Chauxdfnd 65.7 7.7 29 11 13.79 Le Locle 72.7 16.7 22 13 11.22 Neuchatel 64.4 17.6 35 32 16.92 Val de Ruz 77.6 37.6 15 7 4.97 ValdeTravers 67.6 18.7 25 7 8.65 V. De Geneve 35.0 1.2 37 53 42.34 Rive Droite 44.7 46.6 16 29 50.43 Rive Gauche 42.8 27.7 22 29 58.33 Infant.Mortality Courtelary 22.2 Delemont 22.2 Franches-Mnt 20.2 Moutier 20.3 Neuveville 20.6 Porrentruy 26.6 Broye 23.6 Glane 24.9 Gruyere 21.0 Sarine 24.4 Veveyse 24.5 Aigle 16.5 Aubonne 19.1 Avenches 22.7 Cossonay 18.7 Echallens 21.2 Grandson 20.0 Lausanne 20.2 La Vallee 10.8 Lavaux 20.0 Morges 18.0 Moudon 22.4 Nyone 16.7 Orbe 15.3 Oron 21.0 Payerne 23.8 Paysd'enhaut 18.0 Rolle 16.3 Vevey 20.9 Yverdon 22.5 Conthey 15.1 Entremont 19.8 Herens 18.3 Martigwy 19.4 Monthey 20.2 St Maurice 17.8 Sierre 16.3 Sion 18.1 Boudry 20.3 La Chauxdfnd 20.5 Le Locle 18.9 Neuchatel 23.0 Val de Ruz 20.0 ValdeTravers 19.5 V. De Geneve 18.0 Rive Droite 18.2 Rive Gauche 19.3 ``` ] --- count: false # Build a plot by layers .panel1-first_plot-auto[ ```r swiss %>% * ggplot() ``` ] .panel2-first_plot-auto[ <img src="lecture06_plotting_files/figure-html/first_plot_auto_02_output-1.png" width="504" /> ] --- count: false # Build a plot by layers .panel1-first_plot-auto[ ```r swiss %>% ggplot() + * aes(x = Education) ``` ] .panel2-first_plot-auto[ <img src="lecture06_plotting_files/figure-html/first_plot_auto_03_output-1.png" width="504" /> ] --- count: false # Build a plot by layers .panel1-first_plot-auto[ ```r swiss %>% ggplot() + aes(x = Education) + * aes(y = Examination) ``` ] .panel2-first_plot-auto[ <img src="lecture06_plotting_files/figure-html/first_plot_auto_04_output-1.png" width="504" /> ] --- count: false # Build a plot by layers .panel1-first_plot-auto[ ```r swiss %>% ggplot() + aes(x = Education) + aes(y = Examination) + * geom_point() ``` ] .panel2-first_plot-auto[ <img src="lecture06_plotting_files/figure-html/first_plot_auto_05_output-1.png" width="504" /> ] --- count: false # Build a plot by layers .panel1-first_plot-auto[ ```r swiss %>% ggplot() + aes(x = Education) + aes(y = Examination) + geom_point() + * theme_bw(18) ``` ] .panel2-first_plot-auto[ <img src="lecture06_plotting_files/figure-html/first_plot_auto_06_output-1.png" width="504" /> ] <style> .panel1-first_plot-auto { color: black; width: 38.6060606060606%; hight: 32%; float: left; padding-left: 1%; font-size: 80% } .panel2-first_plot-auto { color: black; width: 59.3939393939394%; hight: 32%; float: left; padding-left: 1%; font-size: 80% } .panel3-first_plot-auto { color: black; width: NA%; hight: 33%; float: left; padding-left: 1%; font-size: 80% } </style> .left.footnote[.bold[[`flipbookr`](https://evamaerey.github.io/flipbooks/about)] by [Gina Reynolds](https://github.com/EvaMaeRey)] --- background-image: url("img/plot_lter_penguins.png") background-size: cover class: nvs1 # .small[Palmer penguins] .footnote[ .flex[ .w100.bg-light-gray.shadow-5.pt1.mh1[ .center[install with .large[`install.packages("palmerpenguins")`]]  Horst AM, Hill AP, Gorman KB (2020). [palmerpenguins: Palmer Archipelago (Antarctica) penguin data](https://github.com/allisonhorst/palmerpenguins). R package `v0.1.0` ]]] --- --- count: false ### A more interesting example .panel1-first_palmer-auto[ ```r *library(palmerpenguins) ``` ] .panel2-first_palmer-auto[ ] --- count: false ### A more interesting example .panel1-first_palmer-auto[ ```r library(palmerpenguins) *penguins ``` ] .panel2-first_palmer-auto[ ``` # A tibble: 344 × 8 species island bill_length_mm bill_depth_mm flipper_length_mm body_mass_g <fct> <fct> <dbl> <dbl> <int> <int> 1 Adelie Torgersen 39.1 18.7 181 3750 2 Adelie Torgersen 39.5 17.4 186 3800 3 Adelie Torgersen 40.3 18 195 3250 4 Adelie Torgersen NA NA NA NA 5 Adelie Torgersen 36.7 19.3 193 3450 6 Adelie Torgersen 39.3 20.6 190 3650 7 Adelie Torgersen 38.9 17.8 181 3625 8 Adelie Torgersen 39.2 19.6 195 4675 9 Adelie Torgersen 34.1 18.1 193 3475 10 Adelie Torgersen 42 20.2 190 4250 # … with 334 more rows, and 2 more variables: sex <fct>, year <int> ``` ] --- count: false ### A more interesting example .panel1-first_palmer-auto[ ```r library(palmerpenguins) penguins %>% * ggplot() ``` ] .panel2-first_palmer-auto[ <img src="lecture06_plotting_files/figure-html/first_palmer_auto_03_output-1.png" width="504" /> ] --- count: false ### A more interesting example .panel1-first_palmer-auto[ ```r library(palmerpenguins) penguins %>% ggplot() + * aes(x = flipper_length_mm, * y = body_mass_g) ``` ] .panel2-first_palmer-auto[ <img src="lecture06_plotting_files/figure-html/first_palmer_auto_04_output-1.png" width="504" /> ] --- count: false ### A more interesting example .panel1-first_palmer-auto[ ```r library(palmerpenguins) penguins %>% ggplot() + aes(x = flipper_length_mm, y = body_mass_g) + * aes(color = sex) ``` ] .panel2-first_palmer-auto[ <img src="lecture06_plotting_files/figure-html/first_palmer_auto_05_output-1.png" width="504" /> ] --- count: false ### A more interesting example .panel1-first_palmer-auto[ ```r library(palmerpenguins) penguins %>% ggplot() + aes(x = flipper_length_mm, y = body_mass_g) + aes(color = sex) + * geom_point() ``` ] .panel2-first_palmer-auto[ <img src="lecture06_plotting_files/figure-html/first_palmer_auto_06_output-1.png" width="504" /> ] --- count: false ### A more interesting example .panel1-first_palmer-auto[ ```r library(palmerpenguins) penguins %>% ggplot() + aes(x = flipper_length_mm, y = body_mass_g) + aes(color = sex) + geom_point() + * theme_xaringan(text_font = "Roboto Condensed", text_font_size = 13) ``` ] .panel2-first_palmer-auto[ <img src="lecture06_plotting_files/figure-html/first_palmer_auto_07_output-1.png" width="504" /> ] --- count: false ### A more interesting example .panel1-first_palmer-auto[ ```r library(palmerpenguins) penguins %>% ggplot() + aes(x = flipper_length_mm, y = body_mass_g) + aes(color = sex) + geom_point() + theme_xaringan(text_font = "Roboto Condensed", text_font_size = 13) + * scale_color_manual(values = c("darkorange", "cyan4"), na.translate = FALSE) ``` ] .panel2-first_palmer-auto[ <img src="lecture06_plotting_files/figure-html/first_palmer_auto_08_output-1.png" width="504" /> ] --- count: false ### A more interesting example .panel1-first_palmer-auto[ ```r library(palmerpenguins) penguins %>% ggplot() + aes(x = flipper_length_mm, y = body_mass_g) + aes(color = sex) + geom_point() + theme_xaringan(text_font = "Roboto Condensed", text_font_size = 13) + scale_color_manual(values = c("darkorange", "cyan4"), na.translate = FALSE) + * labs(title = "Penguin flipper and body mass", * caption = "Horst AM, Hill AP, Gorman KB (2020)", * subtitle = "Dimensions for male/female Adelie, Chinstrap and Gentoo Penguins at Palmer Station LTER") ``` ] .panel2-first_palmer-auto[ <img src="lecture06_plotting_files/figure-html/first_palmer_auto_09_output-1.png" width="504" /> ] --- count: false ### A more interesting example .panel1-first_palmer-auto[ ```r library(palmerpenguins) penguins %>% ggplot() + aes(x = flipper_length_mm, y = body_mass_g) + aes(color = sex) + geom_point() + theme_xaringan(text_font = "Roboto Condensed", text_font_size = 13) + scale_color_manual(values = c("darkorange", "cyan4"), na.translate = FALSE) + labs(title = "Penguin flipper and body mass", caption = "Horst AM, Hill AP, Gorman KB (2020)", subtitle = "Dimensions for male/female Adelie, Chinstrap and Gentoo Penguins at Palmer Station LTER") + * theme(plot.subtitle = element_text(size = 13)) ``` ] .panel2-first_palmer-auto[ <img src="lecture06_plotting_files/figure-html/first_palmer_auto_10_output-1.png" width="504" /> ] --- count: false ### A more interesting example .panel1-first_palmer-auto[ ```r library(palmerpenguins) penguins %>% ggplot() + aes(x = flipper_length_mm, y = body_mass_g) + aes(color = sex) + geom_point() + theme_xaringan(text_font = "Roboto Condensed", text_font_size = 13) + scale_color_manual(values = c("darkorange", "cyan4"), na.translate = FALSE) + labs(title = "Penguin flipper and body mass", caption = "Horst AM, Hill AP, Gorman KB (2020)", subtitle = "Dimensions for male/female Adelie, Chinstrap and Gentoo Penguins at Palmer Station LTER") + theme(plot.subtitle = element_text(size = 13)) + * labs(x = "Flipper length (mm)", * y = "Body mass (g)", * color = "Penguin sex") ``` ] .panel2-first_palmer-auto[ <img src="lecture06_plotting_files/figure-html/first_palmer_auto_11_output-1.png" width="504" /> ] --- count: false ### A more interesting example .panel1-first_palmer-auto[ ```r library(palmerpenguins) penguins %>% ggplot() + aes(x = flipper_length_mm, y = body_mass_g) + aes(color = sex) + geom_point() + theme_xaringan(text_font = "Roboto Condensed", text_font_size = 13) + scale_color_manual(values = c("darkorange", "cyan4"), na.translate = FALSE) + labs(title = "Penguin flipper and body mass", caption = "Horst AM, Hill AP, Gorman KB (2020)", subtitle = "Dimensions for male/female Adelie, Chinstrap and Gentoo Penguins at Palmer Station LTER") + theme(plot.subtitle = element_text(size = 13)) + labs(x = "Flipper length (mm)", y = "Body mass (g)", color = "Penguin sex") + * theme(legend.position = "bottom", * legend.background = element_rect(fill = "white", color = NA)) ``` ] .panel2-first_palmer-auto[ <img src="lecture06_plotting_files/figure-html/first_palmer_auto_12_output-1.png" width="504" /> ] --- count: false ### A more interesting example .panel1-first_palmer-auto[ ```r library(palmerpenguins) penguins %>% ggplot() + aes(x = flipper_length_mm, y = body_mass_g) + aes(color = sex) + geom_point() + theme_xaringan(text_font = "Roboto Condensed", text_font_size = 13) + scale_color_manual(values = c("darkorange", "cyan4"), na.translate = FALSE) + labs(title = "Penguin flipper and body mass", caption = "Horst AM, Hill AP, Gorman KB (2020)", subtitle = "Dimensions for male/female Adelie, Chinstrap and Gentoo Penguins at Palmer Station LTER") + theme(plot.subtitle = element_text(size = 13)) + labs(x = "Flipper length (mm)", y = "Body mass (g)", color = "Penguin sex") + theme(legend.position = "bottom", legend.background = element_rect(fill = "white", color = NA)) + * theme(plot.caption = element_text(hjust = 0, face = "italic")) ``` ] .panel2-first_palmer-auto[ <img src="lecture06_plotting_files/figure-html/first_palmer_auto_13_output-1.png" width="504" /> ] --- count: false ### A more interesting example .panel1-first_palmer-auto[ ```r library(palmerpenguins) penguins %>% ggplot() + aes(x = flipper_length_mm, y = body_mass_g) + aes(color = sex) + geom_point() + theme_xaringan(text_font = "Roboto Condensed", text_font_size = 13) + scale_color_manual(values = c("darkorange", "cyan4"), na.translate = FALSE) + labs(title = "Penguin flipper and body mass", caption = "Horst AM, Hill AP, Gorman KB (2020)", subtitle = "Dimensions for male/female Adelie, Chinstrap and Gentoo Penguins at Palmer Station LTER") + theme(plot.subtitle = element_text(size = 13)) + labs(x = "Flipper length (mm)", y = "Body mass (g)", color = "Penguin sex") + theme(legend.position = "bottom", legend.background = element_rect(fill = "white", color = NA)) + theme(plot.caption = element_text(hjust = 0, face = "italic")) + * theme(plot.caption.position = "plot") ``` ] .panel2-first_palmer-auto[ <img src="lecture06_plotting_files/figure-html/first_palmer_auto_14_output-1.png" width="504" /> ] --- count: false ### A more interesting example .panel1-first_palmer-auto[ ```r library(palmerpenguins) penguins %>% ggplot() + aes(x = flipper_length_mm, y = body_mass_g) + aes(color = sex) + geom_point() + theme_xaringan(text_font = "Roboto Condensed", text_font_size = 13) + scale_color_manual(values = c("darkorange", "cyan4"), na.translate = FALSE) + labs(title = "Penguin flipper and body mass", caption = "Horst AM, Hill AP, Gorman KB (2020)", subtitle = "Dimensions for male/female Adelie, Chinstrap and Gentoo Penguins at Palmer Station LTER") + theme(plot.subtitle = element_text(size = 13)) + labs(x = "Flipper length (mm)", y = "Body mass (g)", color = "Penguin sex") + theme(legend.position = "bottom", legend.background = element_rect(fill = "white", color = NA)) + theme(plot.caption = element_text(hjust = 0, face = "italic")) + theme(plot.caption.position = "plot") + * facet_wrap(~ species) ``` ] .panel2-first_palmer-auto[ <img src="lecture06_plotting_files/figure-html/first_palmer_auto_15_output-1.png" width="504" /> ] --- count: false ### A more interesting example .panel1-first_palmer-auto[ ```r library(palmerpenguins) penguins %>% ggplot() + aes(x = flipper_length_mm, y = body_mass_g) + aes(color = sex) + geom_point() + theme_xaringan(text_font = "Roboto Condensed", text_font_size = 13) + scale_color_manual(values = c("darkorange", "cyan4"), na.translate = FALSE) + labs(title = "Penguin flipper and body mass", caption = "Horst AM, Hill AP, Gorman KB (2020)", subtitle = "Dimensions for male/female Adelie, Chinstrap and Gentoo Penguins at Palmer Station LTER") + theme(plot.subtitle = element_text(size = 13)) + labs(x = "Flipper length (mm)", y = "Body mass (g)", color = "Penguin sex") + theme(legend.position = "bottom", legend.background = element_rect(fill = "white", color = NA)) + theme(plot.caption = element_text(hjust = 0, face = "italic")) + theme(plot.caption.position = "plot") + facet_wrap(~ species) + * scale_x_continuous(guide = guide_axis(n.dodge = 2)) ``` ] .panel2-first_palmer-auto[ <img src="lecture06_plotting_files/figure-html/first_palmer_auto_16_output-1.png" width="504" /> ] --- count: false ### A more interesting example .panel1-first_palmer-auto[ ```r library(palmerpenguins) penguins %>% ggplot() + aes(x = flipper_length_mm, y = body_mass_g) + aes(color = sex) + geom_point() + theme_xaringan(text_font = "Roboto Condensed", text_font_size = 13) + scale_color_manual(values = c("darkorange", "cyan4"), na.translate = FALSE) + labs(title = "Penguin flipper and body mass", caption = "Horst AM, Hill AP, Gorman KB (2020)", subtitle = "Dimensions for male/female Adelie, Chinstrap and Gentoo Penguins at Palmer Station LTER") + theme(plot.subtitle = element_text(size = 13)) + labs(x = "Flipper length (mm)", y = "Body mass (g)", color = "Penguin sex") + theme(legend.position = "bottom", legend.background = element_rect(fill = "white", color = NA)) + theme(plot.caption = element_text(hjust = 0, face = "italic")) + theme(plot.caption.position = "plot") + facet_wrap(~ species) + scale_x_continuous(guide = guide_axis(n.dodge = 2)) + * scale_y_continuous(labels = scales::comma) ``` ] .panel2-first_palmer-auto[ <img src="lecture06_plotting_files/figure-html/first_palmer_auto_17_output-1.png" width="504" /> ] <style> .panel1-first_palmer-auto { color: black; width: 44.1%; hight: 32%; float: left; padding-left: 1%; font-size: 80% } .panel2-first_palmer-auto { color: black; width: 53.9%; hight: 32%; float: left; padding-left: 1%; font-size: 80% } .panel3-first_palmer-auto { color: black; width: NA%; hight: 33%; float: left; padding-left: 1%; font-size: 80% } </style> --- class: nvs1, hide_logo # .tiny[Geometric objects define the plot type to be drawn] .flex[ .w-30.bg-washed-green.b--green.ba.bw2.br3.shadow-5.ph3.mt3.mr1[ .large[.wbox[`geom_point()`]] <img src="lecture06_plotting_files/figure-html/p1-1.png" width="504" /> ] .w-30.bg-washed-green.b--green.ba.bw2.br3.shadow-5.ph3.mt3.mr1[ .large[.wbox[`geom_line()`]] <img src="lecture06_plotting_files/figure-html/p2-1.png" width="504" /> ] .w-30.bg-washed-green.b--green.ba.bw2.br3.shadow-5.ph3.mt3.mr1[ .large[.wbox[`geom_bar()`]] <img src="lecture06_plotting_files/figure-html/p3-1.png" width="504" /> ]] -- .flex[ .w-30.bg-washed-green.b--green.ba.bw2.br3.shadow-5.ph3.mt3.mr1[ .large[.wbox[`geom_violin()`]] <img src="lecture06_plotting_files/figure-html/p4-1.png" width="504" /> ] .w-30.bg-washed-green.b--green.ba.bw2.br3.shadow-5.ph3.mt3.mr1[ .large[.wbox[`geom_histogram()`]] <img src="lecture06_plotting_files/figure-html/p5-1.png" width="504" /> ] .w-30.bg-washed-green.b--green.ba.bw2.br3.shadow-5.ph3.mt3.mr1[ .large[.wbox[`geom_density()`]] <img src="lecture06_plotting_files/figure-html/p6-1.png" width="504" /> ]] -- .flex[ .w-90.bg-washed-yellow.b--yellow.ba.bw2.br3.shadow-5.ph5.mt1[ Have a look at the [cheatsheet](https://www.rstudio.org/links/data_visualization_cheat_sheet) or the [documentation](http://ggplot2.tidyverse.org/) for more possibilities. ]] --- # Core layers .pull-left[  ] .pull-right[ ### Other layers .large[ they are present, it works because they have _sensible_ default: - **theme** is `theme_grey` - **coordinate** is `cartesian` - **statistic** is `identity` - **facets** are `disabled` ] ] -- .pull-right[ ### 3 layers are enough .large[ - **data** - **aesthetics** mapping data to plot component - **geometry** at least one ] ] --- class: slide-practical # Your first plot .pull-left[ ```r library(palmerpenguins) library(ggplot2) ggplot(data = penguins) + geom_point(mapping = aes(x = bill_length_mm, y = bill_depth_mm, colour = species)) ``` .center[] .footnote[Artwork by [@allison_horst](https://twitter.com/allison_horst)] ] -- .pull-right[ <img src="lecture06_plotting_files/figure-html/plot_toy-1.png" width="504" /> ] --- # Mapping aesthetics .flex[ .w-50.bg-washed-green.b--green.ba.bw2.br3.shadow-5.ph2.mr1[ .large[.gbox[Requirements]] - `aes()` .bold[map] columns/variables **data** to **aesthetics** - specific **geometries** (`geom`) have different expectations: + univariate, one **x** or **y** for flipped axes + bivariate, **x** and **y** like scatterplot - **continuous** or **discrete** variables + **continuous** for color ➡️ **gradient** + **discrete** for color ➡️ **qualitative** .footnote[**NB:** `mapping =` and `data = ` are often skipped.] ] .w-50.ml1.ph3[ `geom_point()` requires .bold[both] _**x**_ and _**y**_ coordinates ```r ggplot(penguins) + geom_point(aes(x = bill_length_mm, y = bill_depth_mm)) ``` ] ] -- .pull-right[ - same as previous slide - .bold[without] `colour` mapping - on your laptop, default to .bold[black] <img src="lecture06_plotting_files/figure-html/bp2-1.png" width="360" /> ] --- # Unmapped parameters .pull-left[ - `geom_point()` accepts additional arguments such as the `colour` - Define them to a **fixed** value **without** mapping ```r ggplot(penguins) + geom_point(aes(x = bill_length_mm, y = bill_depth_mm), colour = "black") ``` ] -- .pull-right[ <img src="lecture06_plotting_files/figure-html/unnamed-chunk-2-1.png" width="360" /> ] -- .flex[ .w-60.bg-washed-yellow.b--red.ba.bw2.br3.shadow-5.ph4.mt2.ml6[ .large[.gbox[Important]] Parameters defined .large[**outside**] the aesthetics `aes()` are applied to .Large[**all**] data. ] ] --- # Mapped parameters .pull-left[ `mapped` parameters require .Large[two] conditions: - being defined .large[**inside**] the aesthetics `aes()` - refer to one of the column data, here: .bold.red[mistake] ```r ggplot(penguins) + geom_point(aes(x = bill_length_mm, y = bill_depth_mm, * colour = country)) ``` ``` Error in FUN(X[[i]], ...): object 'country' not found ``` - passing the unknown column as `string` as a different effect: ```r ggplot(penguins) + geom_point(aes(x = bill_length_mm, y = bill_depth_mm, colour = "country")) ``` ] -- .pull-right[ <img src="lecture06_plotting_files/figure-html/unnamed-chunk-4-1.png" width="360" /> .large[ - this is hardly useful, but we shall see an application later. - stick to the 2 mapping rules: + in `aes()` + refer to a valid column. ] ] --- # Mapping aesthetics correctly ### In `aes()` _and_ refer to a data column .pull-left[ ```r ggplot(penguins) + geom_bar(aes(y = species, fill = sex)) ``` <img src="lecture06_plotting_files/figure-html/unnamed-chunk-5-1.png" width="504" /> ] .pull-right[ .large[ `species` and `sex` are 2 .bold[valid columns] in `penguins` .bold[Advantages]: - The **legend** 🟥/🟦 for free - Missing data are highlighted in .grey[grey] ⬜️ - Using `y` axis for categories eases reading ] ] --- # .small[How not using a string for mapping is useful?] .pull-left[ .Large.bold[Fair question] .large[ - could we pass an `expression`? - which penguins are above 4 kg? - use `body_mass_g > 4000` that return a boolean to find out ] ] -- .pull-right[ ```r ggplot(penguins) + geom_bar(aes(y = species, fill = body_mass_g > 4000)) ``` <img src="lecture06_plotting_files/figure-html/unnamed-chunk-6-1.png" width="504" /> .large[ The .bold[expression] was evaluated in `penguins` context Obvious that `Gentoo` are bigger than the 2 other species ] ] --- class: slide-compact # .small[Inheritance of arguments across layers] .Large.bold[Compare the two following (great example of a Simpson's paradox):] .pull-left[ ```r ggplot(penguins, aes(x = bill_length_mm, y = bill_depth_mm)) + geom_point(aes(colour = species)) + geom_smooth(method = "lm", formula = 'y ~ x') ``` <img src="lecture06_plotting_files/figure-html/unnamed-chunk-7-1.png" width="504" /> ] .pull-right[ ```r ggplot(penguins, aes(x = bill_length_mm, y = bill_depth_mm, colour = species)) + geom_point() + geom_smooth(method = "lm", formula = 'y ~ x') ``` <img src="lecture06_plotting_files/figure-html/unnamed-chunk-8-1.png" width="504" /> ] -- .flex[ .w-80.bg-washed-yellow.b--yellow.ba.bw2.br3.shadow-5.ph5.mt0.ml0.center[ .left[ - `aesthetics` in `ggplot()` are .bold[passed on] to .Large[**all**] `geometries`. - `aesthetics` in `geom_*()` are .bold[specific] (and can .bold[overwrite] inherited) ] ]] --- class: slide-practical # Try it - map the `island` variable to a `shape` aesthetics for .bold[both] dots and linear models - .bold[all] dots (circles / triangles / squares) with: + a size of `5` + a transparency of 30% (`alpha = 0.7`) .pull-left[ .bold.Large[Aim plot:] <img src="lecture06_plotting_files/figure-html/island_shape-1.png" width="504" /> ]
05
:
00
-- .pull-right[ .bold.Large[Answer:] ```r ggplot(penguins, aes(x = bill_length_mm, y = bill_depth_mm, * shape = island, colour = species)) + geom_point(size = 5, alpha = 0.7) + geom_smooth(method = "lm", formula = 'y ~ x') ``` ] --- # Joining observations .pull-left[ ```r set.seed(212) # tidyr::crossing generate combinations tib <- tibble(crossing(x = letters[1:4], g = factor(1:2)), y = rnorm(8)) ``` .large[Suppose we want to .bold[connect] dots by colors] ] .pull-right[ ```r tib ``` ``` # A tibble: 8 × 3 x g y <chr> <fct> <dbl> 1 a 1 -0.239 2 a 2 0.677 3 b 1 -2.44 4 b 2 1.24 5 c 1 -0.327 6 c 2 0.154 7 d 1 1.04 8 d 2 -0.780 ``` ] -- .pull-left[ .large[Should be the job of `geom_line()`] ] .pull-right[ <img src="lecture06_plotting_files/figure-html/unnamed-chunk-13-1.png" width="504" /> ] --- # Invisible aesthetic: grouping .flex[ .w-33.b--red.ba.bw1.br3.shadow-5.ph3.mt1.mr1[ ```r ggplot(tib, aes(x, y, colour = g)) + geom_line() + geom_point(size = 4) ``` ``` geom_path: Each group consists of only one observation. Do you need to adjust the group aesthetic? ``` <img src="lecture06_plotting_files/figure-html/unnamed-chunk-14-1.png" width="504" /> ] .w-33.b--green.ba.bw1.br3.shadow-5.ph3.mt1.mr1[ ```r ggplot(tib, aes(x, y, colour = g)) + * geom_line(aes(group = g)) + geom_point(size = 4) ``` <img src="lecture06_plotting_files/figure-html/unnamed-chunk-15-1.png" width="504" /> ] .w-33.b--red.ba.bw1.br3.shadow-5.ph3.mt1[ ```r ggplot(tib, aes(x, y, colour = g)) + * geom_line(aes(group = 1)) + geom_point(size = 4) ``` <img src="lecture06_plotting_files/figure-html/unnamed-chunk-16-1.png" width="504" /> ] ] .footnote[Source: koshske blog: [`geom_line()` doesn't draw lines](https://kohske.wordpress.com/2010/12/27/faq-geom_line-doesnt-draw-lines/)] --- # Labels .pull-left[ ```r ggplot(penguins, aes(x = bill_length_mm, y = bill_depth_mm, shape = island, colour = species)) + geom_point() + geom_smooth(method = "lm", formula = 'y ~ x') + labs(title = "Bill ratios of Palmer penguins", caption = "Horst AM, Hill AP, Gorman KB (2020)", subtitle = "Split per species / island", shape = "Islands", x = "cumen length (mm)", y = "cumen depth (mm)") ``` ] -- .pull-right[ <img src="lecture06_plotting_files/figure-html/unnamed-chunk-17-1.png" width="504" /> ] --- # Statistics / geometries are interchangeable .pull-left[ ```r ggplot(penguins) + geom_bar(aes(y = species)) ``` <img src="lecture06_plotting_files/figure-html/unnamed-chunk-18-1.png" width="504" /> ] .pull-right[ ```r ggplot(penguins) + stat_count(aes(y = species)) ``` <img src="lecture06_plotting_files/figure-html/unnamed-chunk-19-1.png" width="504" /> ] -- .flex[ .w-50.bg-washed-yellow.b--yellow.ba.bw2.br3.shadow-5.ph3.ml0.center[ .left[ .large[ - Feels more natural since visual - But just a preference - Most code in the wild use `geom` ] ] ]] --- # Let `ggplot2` doing the stat for you .pull-left[ #### `stat_count` could be omitted since default ```r ggplot(penguins, aes(x = species)) + geom_bar(stat = "count") ``` <img src="lecture06_plotting_files/figure-html/unnamed-chunk-20-1.png" width="504" /> ] .pull-right[ .large[ `stat_count` acts on the mapped var like `dplyr::count()` ] ```r count(penguins, species) ``` ``` # A tibble: 3 × 2 species n <fct> <int> 1 Adelie 152 2 Chinstrap 68 3 Gentoo 124 ``` ] --- # Or do it yourselft, but with `geom_col()` .pull-left[ #### If you give counts, change the stat ```r count(penguins, species) %>% ggplot(aes(x = species, y = n)) + * geom_bar(stat = "identity") ``` <img src="lecture06_plotting_files/figure-html/unnamed-chunk-22-1.png" width="504" /> ] .pull-right[ #### `geom_col()` has the default identity ```r count(penguins, species) %>% ggplot(aes(x = species, y = n)) + * geom_col() ``` <img src="lecture06_plotting_files/figure-html/unnamed-chunk-23-1.png" width="504" /> ] --- # The stat function allows computation, like proportions .pull-left[ #### Classic counting ```r ggplot(penguins, aes(y = species)) + geom_bar(aes(x = stat(count))) ``` <img src="lecture06_plotting_files/figure-html/unnamed-chunk-24-1.png" width="504" /> ] -- .pull-right[ .large[ - Now compute proportions - .bold[Bonus]: get `x` scale in `%` using [`scales`](https://cran.r-project.org/web/packages/scales/index.html) ] ```r ggplot(penguins, aes(y = species)) + geom_bar(aes(x = stat(count) / sum(count))) + scale_x_continuous(labels = scales::percent) ``` <img src="lecture06_plotting_files/figure-html/unnamed-chunk-25-1.png" width="504" /> ] -- .plot-callout[ .bold[See list in help pages]  ] --- # Flexibility in the asthetics for flipping axes (> v3.3.0) .pull-left[ #### `geom_bar()` requires `x` OR `y` ```r penguins %>% # horizontal brings readability ggplot(aes(y = species)) + geom_bar() ``` <img src="lecture06_plotting_files/figure-html/unnamed-chunk-26-1.png" width="504" /> ] .pull-right[ #### Cleanup plot ```r penguins %>% ggplot(aes(y = species)) + geom_bar() + labs(y = NULL) + scale_x_continuous(expand = c(0, NA)) ``` <img src="lecture06_plotting_files/figure-html/unnamed-chunk-27-1.png" width="504" /> ] -- .center.huge[Annoying to see those 3 bars in disorder] --- # Reorder the categorical variable (`forcats`) .pull-left[ .large[Using the function `fct_infreq()`] ```r library(forcats) penguins %>% * ggplot(aes(y = fct_infreq(species))) + geom_bar() + scale_x_continuous(expand = c(0, NA)) + labs(title = "Palmer penguins species", y = NULL) + theme_minimal(14) + # nice trick from T. Pedersen theme(panel.ontop = TRUE, # better to hide the horizontal grid lines panel.grid.major.y = element_blank()) ``` - See the new [article FAQ](https://ggplot2.tidyverse.org/articles/articles/faq-reordering.html) about reordering. ] -- .pull-right[ <img src="lecture06_plotting_files/figure-html/unnamed-chunk-28-1.png" width="504" /> ] --- class: inverse, center, middle # Geometries catalogue  --- # Histograms .pull-left[ ```r penguins %>% ggplot(aes(x = body_mass_g, fill = species)) + geom_histogram(bins = 35, alpha = 0.7, position = "identity") ``` ] .pull-right[ <img src="lecture06_plotting_files/figure-html/sw_histo-1.png" width="504" /> - default `bin` value is `30` and will be printed out as a message - default is `stack` for the `position`. Here we overlay and use transparency ] --- # Density plots .pull-left[ ```r penguins %>% ggplot(aes(x = body_mass_g, fill = species, colour = species)) + geom_density(alpha = 0.7) ``` ] .pull-right[ <img src="lecture06_plotting_files/figure-html/sw_dens-1.png" width="504" /> - use both `colour` and `fill` mapped to the same variable for cosmetic purposes ] --- # Overlay density and histogram .pull-left[ #### Naive approach: scale issue ```r ggplot(penguins, aes(x = body_mass_g)) + geom_histogram(bins = 30) + geom_density(colour = "red") ``` <img src="lecture06_plotting_files/figure-html/unnamed-chunk-29-1.png" width="504" /> ] -- .pull-right[ #### Solution: scale histogram to density one ```r ggplot(penguins, aes(x = body_mass_g)) + geom_histogram(bins = 30, * aes(y = stat(density))) + geom_density(colour = "red") ``` <img src="lecture06_plotting_files/figure-html/unnamed-chunk-30-1.png" width="504" /> ] --- # Barplot, categories .pull-left[ #### Get stacked by default (`position = "stack"`) ```r ggplot(penguins) + geom_bar(aes(y = species, fill = island)) ``` <img src="lecture06_plotting_files/figure-html/unnamed-chunk-31-1.png" width="504" /> ] -- .pull-right[ #### Dodging `island`: side by side ```r ggplot(penguins) + geom_bar(aes(y = species, fill = island), position = "dodge") ``` <img src="lecture06_plotting_files/figure-html/unnamed-chunk-32-1.png" width="504" /> .Large[But global width per species is preserved] ] --- # Preserve single bar (same width) .pull-left[ ```r ggplot(penguins) + geom_bar(aes(y = species, fill = island), position = position_dodge2(preserve = "single")) + labs(y = NULL) ``` ] .pull-right[ <img src="lecture06_plotting_files/figure-html/unnamed-chunk-33-1.png" width="504" /> ] --- # Stacked barchart for proportions .pull-left[ ```r penguins %>% drop_na(sex) %>% # from tidyr ggplot() + geom_bar(aes(y = species, fill = sex), * position = "fill") + scale_x_continuous(labels = scales::percent, position = "top", expand = c(0, 0)) + labs(x = NULL, y = NULL) + theme_classic(16) ``` ] -- .pull-right[ <img src="lecture06_plotting_files/figure-html/unnamed-chunk-34-1.png" width="504" /> ] --- # Pie charts involved another coordinate system .pull-left[ ```r ggplot(penguins) + geom_bar(aes(y = species, fill = island), position = "fill") + labs(x = NULL, y = NULL) + * coord_polar() ``` <img src="lecture06_plotting_files/figure-html/unnamed-chunk-35-1.png" width="504" /> ] .pull-right[ ```r penguins %>% ggplot() + geom_bar(aes(y = species, fill = island)) + labs(x = NULL, y = NULL) + * coord_polar() ``` <img src="lecture06_plotting_files/figure-html/unnamed-chunk-36-1.png" width="504" /> ] --- # Boxplot, a continuous `y` by a categorical `x` .pull-left[ ```r ggplot(penguins) + geom_boxplot(aes(y = body_mass_g, x = species)) ``` .large[ `geom_boxplot()` is assessing that: - `body_mass_g` is .bold[continuous] - `species` is .bold[categorical/discrete] ]
.footnote[.bold[Artwork] by [Allison Horst](https://github.com/allisonhorst/stats-illustrations)] ] .pull-right[ <img src="lecture06_plotting_files/figure-html/unnamed-chunk-38-1.png" width="504" /> ] --- # Boxplot, dodging by default .pull-left[ #### Filter out `NA` to avoid this category ```r penguins %>% # alternative to tidyr::drop_na() filter(!is.na(sex)) %>% ggplot() + geom_boxplot(aes(y = body_mass_g, x = species, fill = sex)) ``` ] .pull-right[ <img src="lecture06_plotting_files/figure-html/unnamed-chunk-39-1.png" width="504" /> ] --- class: hide_logo # Better: violin and jitter .pull-left[ #### Show the data ```r penguins %>% filter(!is.na(sex)) %>% # define aes here for both geometries ggplot(aes(y = body_mass_g, x = species, fill = sex, # for violin contours and dots colour = sex )) + # very transparent filling geom_violin(alpha = 0.1, trim = FALSE) + geom_point(position = position_jitterdodge(dodge.width = 0.9), alpha = 0.5, # don't need dots in legend show.legend = FALSE) ```
] .pull-right[ <img src="lecture06_plotting_files/figure-html/unnamed-chunk-41-1.png" width="504" /> .footnote[GIF source: [Linh Ngo @BioTuring](https://blog.bioturing.com/2018/05/16/5-reasons-you-should-use-a-violin-graph/)] ] --- # Even better: beeswarm .pull-left[ #### ggplot extension [`ggbeeswarm`](https://github.com/eclarke/ggbeeswarm) ```r library(ggbeeswarm) penguins %>% filter(!is.na(sex)) %>% ggplot(aes(y = body_mass_g, x = species, colour = sex)) + * geom_quasirandom(dodge.width = 1) ```  ] .footnote[Artwork by [@allison_horst](https://twitter.com/allison_horst/status/1316784741987749891?s=20)] .pull-right[ <img src="lecture06_plotting_files/figure-html/unnamed-chunk-42-1.png" width="504" /> ] --- class: slide-practical # Coding mistake .pull-left[ #### What is wrong with the above code? (**Hint**: think about inherited aesthetics) ```r penguins %>% ggplot() + geom_point(aes(x = bill_length_mm, y = body_mass_g)) + geom_smooth(method = "lm") ``` ``` `geom_smooth()` using formula 'y ~ x' ``` ``` Error: stat_smooth requires the following missing aesthetics: x and y ``` <img src="lecture06_plotting_files/figure-html/wrong_aes-1.png" width="504" /> ] -- .pull-right[ #### Inheritance of `aesthetics` in main `ggplot()` ```r penguins %>% ggplot(aes(x = bill_length_mm, y = body_mass_g)) + geom_point() + geom_smooth(method = "lm", se = FALSE) ``` ``` `geom_smooth()` using formula 'y ~ x' ``` <img src="lecture06_plotting_files/figure-html/unnamed-chunk-43-1.png" width="504" /> ] --- # Control the dots plotting order .Large[`ggplot2`] outputs dots .bold[as they appear] in the input data .pull-left[ ```r tibble(x = LETTERS[1:3], y = x) %>% ggplot(aes(x, y)) + geom_point(aes(colour = x), show.legend = FALSE, size = 100, alpha = 0.9) + scale_color_brewer(palette = "Dark2") + theme_classic(20) ``` <img src="lecture06_plotting_files/figure-html/unnamed-chunk-44-1.png" width="504" /> ] .pull-right[ ```r tibble(x = LETTERS[1:3], y = x) %>% * arrange(desc(x)) %>% ggplot(aes(x, y)) + geom_point(aes(colour = x), show.legend = FALSE, size = 100, alpha = 0.9) + scale_color_brewer(palette = "Dark2") + theme_classic(20) ``` <img src="lecture06_plotting_files/figure-html/unnamed-chunk-45-1.png" width="504" /> ] --- class: inverse, center, middle # Scales catalogue ### 62 functions available!  --- # Scales for all .pull-left[ Functions are based on this .bold[scheme]: ``` scale_{aes}_{type}() ``` #### arguments to change default - `breaks`, choose where are labels - `labels`, usually with package [`scales`](https://scales.r-lib.org/) - `trans`, to change to _i.e_ log #### tidyr `crossing` + glue `glue_data` trick to generate combinations ] -- .pull-right-nvs[ ```r tidyr::crossing(aes = c("fill", "colour", "alpha", "x", "y"), type = c("continuous", "discrete", "date")) %>% glue::glue_data("scale_{aes}_{type}()") ``` ``` scale_alpha_continuous() scale_alpha_date() scale_alpha_discrete() scale_colour_continuous() scale_colour_date() scale_colour_discrete() scale_fill_continuous() scale_fill_date() scale_fill_discrete() scale_x_continuous() scale_x_date() scale_x_discrete() scale_y_continuous() scale_y_date() scale_y_discrete() ``` ```r scales::label_percent()(c(0.4, 0.6)) ``` ``` [1] "40%" "60%" ``` ```r scales::label_comma()(20^(1:3)) ``` ``` [1] "20" "400" "8,000" ``` ```r scales::breaks_log()(20^(1:3)) ``` ``` [1] 10 30 100 300 1000 3000 10000 ``` ] --- # Scales transformation .pull-left[ #### Starwars (`dplyr` dataset): who is the massive guy? ```r starwars %>% ggplot(aes(x = height, y = mass)) + geom_point(size = 2) ``` <img src="lecture06_plotting_files/figure-html/unnamed-chunk-48-1.png" width="504" /> ] -- .pull-right[ #### Log scaling the y axis ```r starwars %>% ggplot(aes(x = height, y = mass)) + geom_point(alpha = 0.6, size = 2) + # all data arg can take either a df or a function geom_text(data = \(x) filter(x, mass > 1000), aes(label = name), nudge_y = -0.1) + annotation_logticks(sides = "l") + scale_y_log10() # same as trans = "log10" ``` <img src="lecture06_plotting_files/figure-html/unnamed-chunk-49-1.png" width="504" /> ] .footnote[using the new **lambda** for anonymous functions,
**<** 4.1 would be `function(x) filter(x, mass > 1000)`] --- class: center, middle # Custom colors  Better: see [Emil Hvitfeldt repo](https://github.com/EmilHvitfeldt/r-color-palettes/blob/master/type-sorted-palettes.md) --- # Changing colours for categories .pull-left[ #### Default is `scale_fill_hue()` ```r filter(starwars, !is.na(gender)) %>% ggplot(aes(y = gender, fill = fct_lump_n(species, 8) %>% fct_infreq())) + geom_bar(position = "fill") + scale_fill_hue() + labs(fill = "top 8 Species\n(ranked)") ``` <img src="lecture06_plotting_files/figure-html/unnamed-chunk-50-1.png" width="504" /> ] -- .pull-right[ #### Rbrewer is a safe alternative ```r filter(starwars, !is.na(gender)) %>% ggplot(aes(y = gender, fill = fct_lump_n(species, 8) %>% fct_infreq())) + geom_bar(position = "fill") + scale_fill_brewer(palette = "Set1") + labs(fill = "top 8 Species\n(ranked)") ``` <img src="lecture06_plotting_files/figure-html/unnamed-chunk-51-1.png" width="504" /> ] --- # Predefined colour palettes .left-column[ ```r library(RColorBrewer) par(mar = c(0, 4, 0, 0)) display.brewer.all() ``` ] .right-column[ <img src="lecture06_plotting_files/figure-html/unnamed-chunk-52-1.png" width="504" /> ] --- # Colour gradient, for continuous variables The default gradient generated by `ggplot2` is not very good... Better off using `viridis` (`scale_color_viridis_c()` `c` for continuous) .pull-left[ ```r penguins %>% ggplot(aes(x = bill_length_mm, y = bill_depth_mm, colour = body_mass_g)) + geom_point(alpha = 0.6, size = 5) ``` <img src="lecture06_plotting_files/figure-html/grad_default-1.png" width="504" /> ] -- .pull-right[ ```r penguins %>% ggplot(aes(x = bill_length_mm, y = bill_depth_mm, colour = body_mass_g)) + geom_point(alpha = 0.6, size = 5) + scale_color_viridis_c() ``` <img src="lecture06_plotting_files/figure-html/unnamed-chunk-53-1.png" width="504" /> ] -- .plot-callout[  ] --- # Viridis palettes
.pull-left[ - 5 different scales - Also for discrete variables - [viridis](https://sjmgarnier.github.io/viridis/articles/intro-to-viridis.html) is colour blind friendly and nice in b&w - In `ggplot2` since v3.0 but no the default  ] -- .pull-right[ ```r penguins %>% ggplot(aes(x = bill_length_mm, y = bill_depth_mm, colour = species)) + geom_point(alpha = 0.6, size = 5) + scale_color_viridis_d() ``` <img src="lecture06_plotting_files/figure-html/unnamed-chunk-55-1.png" width="504" /> ] --- # Binning instead of gradient (new v3.3.0) .pull-left[ #### Binning help grouping observations .large[ - Default blue gradient, `viridis` option - Number of bins, limits can be changed ] ] ```r penguins %>% ggplot(aes(x = bill_length_mm, y = bill_depth_mm, colour = body_mass_g)) + geom_point(alpha = 0.6, size = 5) + scale_color_binned(type = "viridis") ``` .pull-right[ <img src="lecture06_plotting_files/figure-html/unnamed-chunk-56-1.png" width="504" /> ] --- # Merge similar guides (new v3.3.0) .pull-left[ #### Size & colour on same variable ➡️ 2 guides ```r penguins %>% ggplot(aes(x = bill_length_mm, y = bill_depth_mm, colour = body_mass_g, size = body_mass_g)) + geom_point(alpha = 0.6) + scale_color_viridis_c() ``` <img src="lecture06_plotting_files/figure-html/unnamed-chunk-57-1.png" width="504" /> ] .pull-right[ .large[`guides()` merge both aesthetics] ```r penguins %>% ggplot(aes(x = bill_length_mm, y = bill_depth_mm, colour = body_mass_g, size = body_mass_g)) + geom_point(alpha = 0.6) + scale_color_viridis_c() + * guides(colour = "legend") ``` <img src="lecture06_plotting_files/figure-html/unnamed-chunk-58-1.png" width="504" /> ] --- class: inverse, center, middle # Facets <img src="lecture06_plotting_files/figure-html/unnamed-chunk-59-1.png" width="432" /> --- # Facets: `facet_wrap()` .pull-left[ #### Creating facets .large[ - Easiest way: `facet_wrap()` - Use a formula (in R .Large[`~`]) - `facet_wrap()` is for one var - Or the `vars()` function ] ```r ggplot(penguins, aes(bill_depth_mm, bill_length_mm)) + geom_point() + facet_wrap(~ species) ``` ] .pull-right[ <img src="lecture06_plotting_files/figure-html/unnamed-chunk-60-1.png" width="504" /> ] --- # Facets layout .pull-left[ #### Specify the number of rows/columns: .large[ - `ncol = integer` - `nrow = integer` ] ```r fc <- ggplot(penguins, aes(bill_depth_mm, bill_length_mm)) + geom_point() fc + facet_wrap(~ species, ncol = 2) ``` ] .pull-right[ <img src="lecture06_plotting_files/figure-html/facet_2-1.png" width="504" /> ] --- # Facets, free scales #### ⚠️ Make comparison harder .pull-left[ .large[ - `x` or `y` (`free_x` / `free_y`) ] ```r fc + facet_wrap(~ species, scales = "free_y") ``` <img src="lecture06_plotting_files/figure-html/unnamed-chunk-61-1.png" width="504" /> ] -- .pull-right[ .large[ - Both axis ] ```r fc + facet_wrap(~ species, scales = "free") ``` <img src="lecture06_plotting_files/figure-html/unnamed-chunk-62-1.png" width="504" /> ] --- # `facet_grid()` to lay out panels in a grid .pull-left[ #### Specify a 2 sides **formula** .bold[rows] on the left, .bold[columns] on the right separated by a tilde .Large[`~`] ```r ggplot(penguins, aes(bill_depth_mm, bill_length_mm)) + geom_point() + facet_grid(island ~ species) ``` ] .pull-right[ <img src="lecture06_plotting_files/figure-html/unnamed-chunk-63-1.png" width="504" /> ] --- # Barplots in facets `facet_grid()` can also be used with .bold[one] variable, complemented by a placeholder: .huge[.] .pull-left[ #### Waste of space ```r ggplot(starwars) + geom_bar(aes(y = gender, fill = sex)) + facet_grid(fct_lump_min(species, 4) ~ .) + labs(y = NULL) ``` <img src="lecture06_plotting_files/figure-html/unnamed-chunk-64-1.png" width="504" /> ] -- .pull-right[ #### Optimize the space by removing empty slots ```r ggplot(starwars) + geom_bar(aes(y = gender, fill = sex)) + facet_grid(fct_lump_min(species, 4) ~ ., space = "free", scales = "free_y") + labs(y = NULL) ``` <img src="lecture06_plotting_files/figure-html/unnamed-chunk-65-1.png" width="504" /> ] --- class: inverse, center, middle # Cosmetic 💅 ### and helpers --- # Black theme .pull-left[ #### Using Bob Rudis [`hrbrthemes`](https://github.com/hrbrmstr/hrbrthemes) package ```r library(hrbrthemes) ggplot(penguins, aes(x = bill_length_mm, y = bill_depth_mm, colour = species)) + geom_point() + geom_smooth(method = "lm", formula = 'y ~ x', # no standard error ribbon se = FALSE) + facet_grid(island ~ .) + labs(x = "length (mm)", y = "depth (mm)", title = "Palmer penguins", subtitle = "bill dimensions over location and species", caption = "source: Horst AM, Hill AP, Gorman KB (2020)") + # hrbrthemes specifications scale_fill_ipsum() + theme_ft_rc(14) + # tweak the theme theme(panel.grid.major.y = element_blank(), panel.grid.major.x = element_line(size = 0.5), plot.caption = element_text(face = "italic"), strip.text = element_text(face = "bold"), plot.caption.position = "plot") ``` ] -- .pull-right[ <img src="img/plot_theme_fc.png" width="100%" /> ] --- # Exporting .bold[Interactive or passive mode] .pull-left[ #### Right panel - using the Export button in the _Plots_ panel  #### ggsave - save the `ggplot` **object**, 2nd argument, here `p` or `last_plot()` - guesses the type of desired output by the extension (jpg, png, pdf etc.) ```r ggsave("my_name.png", p, width = 60, height = 30, units = "mm") ggsave("my_name.pdf", last_plot(), width = 50, height = 50, units = "mm") ``` ] .pull-right[ #### Rmarkdown docs - if needed, adjust the chunk options: + size: `fig.height`, `fig.width` + ratio: `fig.asp`... + [others](https://yihui.name/knitr/options/?version=1.1.214&mode=desktop)  ] --- # Extensions `ggplot2` introduced the possibility for the community to contribute and [create **extensions**](http://ggplot2.tidyverse.org/articles/extending-ggplot2.html). They are referenced on a [dedicated site](https://exts.ggplot2.tidyverse.org/gallery/) .center[] --- # Compose plots with `patchwork`
#### [Patchwork](https://patchwork.data-imaginist.com/) is developed by [Thomas Lin Pedersen](https://github.com/thomasp85), main maintainer of `ggplot2`. .pull-left[ .large[Define 3 plots and assign them names] ```r p1 <- ggplot(penguins, aes(x = species)) + geom_bar() + labs(title = "Species distribution") p2 <- ggplot(penguins, aes(y = island)) + geom_bar() + labs(title = "Island but flipped") p3 <- ggplot(penguins, aes(x = body_mass_g, y = bill_depth_mm, colour = sex)) + geom_point() p1 ``` <img src="lecture06_plotting_files/figure-html/unnamed-chunk-69-1.png" width="252" /> ] .pull-right[ ```r p2 ``` <img src="lecture06_plotting_files/figure-html/unnamed-chunk-70-1.png" width="252" /> ```r p3 ``` <img src="lecture06_plotting_files/figure-html/unnamed-chunk-70-2.png" width="252" /> .Large[Now, compose them!] ] --- # Compose plots with `patchwork`
#### `patchwork` provides an API using the classic arithmetic operators .pull-left[ ```r library(patchwork) (( p1 | p2 ) / p3) + # add tags and main title plot_annotation(tag_levels = 'A', title = 'Plots about penguins') & # modify all plots recursively theme_minimal() + theme(text = element_text('Roboto')) ``` ] .pull-right[ <img src="lecture06_plotting_files/figure-html/unnamed-chunk-72-1.png" width="504" /> ] .footnote[If you need to perfectly align axes, have a look at [`cowplot`](https://wilkelab.org/cowplot/) by .bold[Claus O. Wilke]] --- # Polished example by Cédric Scherer
.Large[Using [`patchwork`](https://www.data-imaginist.com/2020/insetting-a-new-patchwork-version/), [`ggforce`](https://github.com/thomasp85/ggforce)] (.bold[T. Pedersen]) and [`ggtext`](https://wilkelab.org/ggtext/) (.bold[Claus O. Wilke]) .center[<img src = "img/plot_scherer_penguins.png", style = "height:450px;"/>] .footnote[Source: [OutlierConf](https://www.youtube.com/watch?v=7UjA_5gNvdw&list=PLAm5TIX-yz7IkKOUcStM_vl8AD0S9v0co&index=34) by [Cédric Scherer](https://github.com/Z3tt), see also [code](https://github.com/Z3tt/OutlierConf2021/blob/main/R/OutlierConf2021_ggplotWizardry_HandsOn.Rmd)] --- --- count: false .panel1-scherer-auto[ ```r *culmen <- png::readPNG(here::here("site/lectures/img/plot_culmen_depth.png"), native = TRUE) ``` ] .panel2-scherer-auto[ ] --- count: false .panel1-scherer-auto[ ```r culmen <- png::readPNG(here::here("site/lectures/img/plot_culmen_depth.png"), native = TRUE) *penguins ``` ] .panel2-scherer-auto[ ``` # A tibble: 344 × 8 species island bill_length_mm bill_depth_mm flipper_length_mm body_mass_g <fct> <fct> <dbl> <dbl> <int> <int> 1 Adelie Torgersen 39.1 18.7 181 3750 2 Adelie Torgersen 39.5 17.4 186 3800 3 Adelie Torgersen 40.3 18 195 3250 4 Adelie Torgersen NA NA NA NA 5 Adelie Torgersen 36.7 19.3 193 3450 6 Adelie Torgersen 39.3 20.6 190 3650 7 Adelie Torgersen 38.9 17.8 181 3625 8 Adelie Torgersen 39.2 19.6 195 4675 9 Adelie Torgersen 34.1 18.1 193 3475 10 Adelie Torgersen 42 20.2 190 4250 # … with 334 more rows, and 2 more variables: sex <fct>, year <int> ``` ] --- count: false .panel1-scherer-auto[ ```r culmen <- png::readPNG(here::here("site/lectures/img/plot_culmen_depth.png"), native = TRUE) penguins %>% * filter(across(ends_with("mm"), ~!is.na(.x))) ``` ] .panel2-scherer-auto[ ``` # A tibble: 342 × 8 species island bill_length_mm bill_depth_mm flipper_length_mm body_mass_g <fct> <fct> <dbl> <dbl> <int> <int> 1 Adelie Torgersen 39.1 18.7 181 3750 2 Adelie Torgersen 39.5 17.4 186 3800 3 Adelie Torgersen 40.3 18 195 3250 4 Adelie Torgersen 36.7 19.3 193 3450 5 Adelie Torgersen 39.3 20.6 190 3650 6 Adelie Torgersen 38.9 17.8 181 3625 7 Adelie Torgersen 39.2 19.6 195 4675 8 Adelie Torgersen 34.1 18.1 193 3475 9 Adelie Torgersen 42 20.2 190 4250 10 Adelie Torgersen 37.8 17.1 186 3300 # … with 332 more rows, and 2 more variables: sex <fct>, year <int> ``` ] --- count: false .panel1-scherer-auto[ ```r culmen <- png::readPNG(here::here("site/lectures/img/plot_culmen_depth.png"), native = TRUE) penguins %>% filter(across(ends_with("mm"), ~!is.na(.x))) %>% * ggplot(aes(x = bill_length_mm, y = bill_depth_mm)) ``` ] .panel2-scherer-auto[ <img src="lecture06_plotting_files/figure-html/scherer_auto_04_output-1.png" width="504" /> ] --- count: false .panel1-scherer-auto[ ```r culmen <- png::readPNG(here::here("site/lectures/img/plot_culmen_depth.png"), native = TRUE) penguins %>% filter(across(ends_with("mm"), ~!is.na(.x))) %>% ggplot(aes(x = bill_length_mm, y = bill_depth_mm)) + * ggforce::geom_mark_ellipse( * aes(fill = species, label = species), alpha = 0, * show.legend = FALSE * ) ``` ] .panel2-scherer-auto[ <img src="lecture06_plotting_files/figure-html/scherer_auto_05_output-1.png" width="504" /> ] --- count: false .panel1-scherer-auto[ ```r culmen <- png::readPNG(here::here("site/lectures/img/plot_culmen_depth.png"), native = TRUE) penguins %>% filter(across(ends_with("mm"), ~!is.na(.x))) %>% ggplot(aes(x = bill_length_mm, y = bill_depth_mm)) + ggforce::geom_mark_ellipse( aes(fill = species, label = species), alpha = 0, show.legend = FALSE ) + * geom_point(aes(color = body_mass_g), alpha = .6, size = 3.5) ``` ] .panel2-scherer-auto[ <img src="lecture06_plotting_files/figure-html/scherer_auto_06_output-1.png" width="504" /> ] --- count: false .panel1-scherer-auto[ ```r culmen <- png::readPNG(here::here("site/lectures/img/plot_culmen_depth.png"), native = TRUE) penguins %>% filter(across(ends_with("mm"), ~!is.na(.x))) %>% ggplot(aes(x = bill_length_mm, y = bill_depth_mm)) + ggforce::geom_mark_ellipse( aes(fill = species, label = species), alpha = 0, show.legend = FALSE ) + geom_point(aes(color = body_mass_g), alpha = .6, size = 3.5) + * scale_x_continuous(breaks = seq(25, 65, by = 5), limits = c(25, 65)) ``` ] .panel2-scherer-auto[ <img src="lecture06_plotting_files/figure-html/scherer_auto_07_output-1.png" width="504" /> ] --- count: false .panel1-scherer-auto[ ```r culmen <- png::readPNG(here::here("site/lectures/img/plot_culmen_depth.png"), native = TRUE) penguins %>% filter(across(ends_with("mm"), ~!is.na(.x))) %>% ggplot(aes(x = bill_length_mm, y = bill_depth_mm)) + ggforce::geom_mark_ellipse( aes(fill = species, label = species), alpha = 0, show.legend = FALSE ) + geom_point(aes(color = body_mass_g), alpha = .6, size = 3.5) + scale_x_continuous(breaks = seq(25, 65, by = 5), limits = c(25, 65)) + * scale_y_continuous(breaks = seq(12, 24, by = 2), limits = c(12, 24)) ``` ] .panel2-scherer-auto[ <img src="lecture06_plotting_files/figure-html/scherer_auto_08_output-1.png" width="504" /> ] --- count: false .panel1-scherer-auto[ ```r culmen <- png::readPNG(here::here("site/lectures/img/plot_culmen_depth.png"), native = TRUE) penguins %>% filter(across(ends_with("mm"), ~!is.na(.x))) %>% ggplot(aes(x = bill_length_mm, y = bill_depth_mm)) + ggforce::geom_mark_ellipse( aes(fill = species, label = species), alpha = 0, show.legend = FALSE ) + geom_point(aes(color = body_mass_g), alpha = .6, size = 3.5) + scale_x_continuous(breaks = seq(25, 65, by = 5), limits = c(25, 65)) + scale_y_continuous(breaks = seq(12, 24, by = 2), limits = c(12, 24)) + * scale_color_viridis_c(option = "turbo", labels = scales::comma) ``` ] .panel2-scherer-auto[ <img src="lecture06_plotting_files/figure-html/scherer_auto_09_output-1.png" width="504" /> ] --- count: false .panel1-scherer-auto[ ```r culmen <- png::readPNG(here::here("site/lectures/img/plot_culmen_depth.png"), native = TRUE) penguins %>% filter(across(ends_with("mm"), ~!is.na(.x))) %>% ggplot(aes(x = bill_length_mm, y = bill_depth_mm)) + ggforce::geom_mark_ellipse( aes(fill = species, label = species), alpha = 0, show.legend = FALSE ) + geom_point(aes(color = body_mass_g), alpha = .6, size = 3.5) + scale_x_continuous(breaks = seq(25, 65, by = 5), limits = c(25, 65)) + scale_y_continuous(breaks = seq(12, 24, by = 2), limits = c(12, 24)) + scale_color_viridis_c(option = "turbo", labels = scales::comma) + * labs( * title = "Bill Dimensions of Brush-Tailed Penguins (<i style='color:#28A87D;'>*Pygoscelis*</i>)", * subtitle = 'A scatter plot of bill depth *versus* bill length.', * caption = "Data: Gorman, Williams & Fraser (2014) *PLoS ONE*", * x = "Bill Length (mm)", * y = "Bill Depth (mm)", * color = "Body mass (g)") ``` ] .panel2-scherer-auto[ <img src="lecture06_plotting_files/figure-html/scherer_auto_10_output-1.png" width="504" /> ] --- count: false .panel1-scherer-auto[ ```r culmen <- png::readPNG(here::here("site/lectures/img/plot_culmen_depth.png"), native = TRUE) penguins %>% filter(across(ends_with("mm"), ~!is.na(.x))) %>% ggplot(aes(x = bill_length_mm, y = bill_depth_mm)) + ggforce::geom_mark_ellipse( aes(fill = species, label = species), alpha = 0, show.legend = FALSE ) + geom_point(aes(color = body_mass_g), alpha = .6, size = 3.5) + scale_x_continuous(breaks = seq(25, 65, by = 5), limits = c(25, 65)) + scale_y_continuous(breaks = seq(12, 24, by = 2), limits = c(12, 24)) + scale_color_viridis_c(option = "turbo", labels = scales::comma) + labs( title = "Bill Dimensions of Brush-Tailed Penguins (<i style='color:#28A87D;'>*Pygoscelis*</i>)", subtitle = 'A scatter plot of bill depth *versus* bill length.', caption = "Data: Gorman, Williams & Fraser (2014) *PLoS ONE*", x = "Bill Length (mm)", y = "Bill Depth (mm)", color = "Body mass (g)") + * theme_minimal(base_family = "RobotoCondensed", base_size = 12) ``` ] .panel2-scherer-auto[ <img src="lecture06_plotting_files/figure-html/scherer_auto_11_output-1.png" width="504" /> ] --- count: false .panel1-scherer-auto[ ```r culmen <- png::readPNG(here::here("site/lectures/img/plot_culmen_depth.png"), native = TRUE) penguins %>% filter(across(ends_with("mm"), ~!is.na(.x))) %>% ggplot(aes(x = bill_length_mm, y = bill_depth_mm)) + ggforce::geom_mark_ellipse( aes(fill = species, label = species), alpha = 0, show.legend = FALSE ) + geom_point(aes(color = body_mass_g), alpha = .6, size = 3.5) + scale_x_continuous(breaks = seq(25, 65, by = 5), limits = c(25, 65)) + scale_y_continuous(breaks = seq(12, 24, by = 2), limits = c(12, 24)) + scale_color_viridis_c(option = "turbo", labels = scales::comma) + labs( title = "Bill Dimensions of Brush-Tailed Penguins (<i style='color:#28A87D;'>*Pygoscelis*</i>)", subtitle = 'A scatter plot of bill depth *versus* bill length.', caption = "Data: Gorman, Williams & Fraser (2014) *PLoS ONE*", x = "Bill Length (mm)", y = "Bill Depth (mm)", color = "Body mass (g)") + theme_minimal(base_family = "RobotoCondensed", base_size = 12) + * theme(plot.title = element_markdown(face = "bold"), * plot.subtitle = element_markdown(), * plot.caption = element_markdown(margin = margin(t = 15)), * axis.title.x = element_markdown(), * axis.title.y = element_markdown()) ``` ] .panel2-scherer-auto[ <img src="lecture06_plotting_files/figure-html/scherer_auto_12_output-1.png" width="504" /> ] --- count: false .panel1-scherer-auto[ ```r culmen <- png::readPNG(here::here("site/lectures/img/plot_culmen_depth.png"), native = TRUE) penguins %>% filter(across(ends_with("mm"), ~!is.na(.x))) %>% ggplot(aes(x = bill_length_mm, y = bill_depth_mm)) + ggforce::geom_mark_ellipse( aes(fill = species, label = species), alpha = 0, show.legend = FALSE ) + geom_point(aes(color = body_mass_g), alpha = .6, size = 3.5) + scale_x_continuous(breaks = seq(25, 65, by = 5), limits = c(25, 65)) + scale_y_continuous(breaks = seq(12, 24, by = 2), limits = c(12, 24)) + scale_color_viridis_c(option = "turbo", labels = scales::comma) + labs( title = "Bill Dimensions of Brush-Tailed Penguins (<i style='color:#28A87D;'>*Pygoscelis*</i>)", subtitle = 'A scatter plot of bill depth *versus* bill length.', caption = "Data: Gorman, Williams & Fraser (2014) *PLoS ONE*", x = "Bill Length (mm)", y = "Bill Depth (mm)", color = "Body mass (g)") + theme_minimal(base_family = "RobotoCondensed", base_size = 12) + theme(plot.title = element_markdown(face = "bold"), plot.subtitle = element_markdown(), plot.caption = element_markdown(margin = margin(t = 15)), axis.title.x = element_markdown(), axis.title.y = element_markdown()) + * theme(plot.title.position = "plot") ``` ] .panel2-scherer-auto[ <img src="lecture06_plotting_files/figure-html/scherer_auto_13_output-1.png" width="504" /> ] --- count: false .panel1-scherer-auto[ ```r culmen <- png::readPNG(here::here("site/lectures/img/plot_culmen_depth.png"), native = TRUE) penguins %>% filter(across(ends_with("mm"), ~!is.na(.x))) %>% ggplot(aes(x = bill_length_mm, y = bill_depth_mm)) + ggforce::geom_mark_ellipse( aes(fill = species, label = species), alpha = 0, show.legend = FALSE ) + geom_point(aes(color = body_mass_g), alpha = .6, size = 3.5) + scale_x_continuous(breaks = seq(25, 65, by = 5), limits = c(25, 65)) + scale_y_continuous(breaks = seq(12, 24, by = 2), limits = c(12, 24)) + scale_color_viridis_c(option = "turbo", labels = scales::comma) + labs( title = "Bill Dimensions of Brush-Tailed Penguins (<i style='color:#28A87D;'>*Pygoscelis*</i>)", subtitle = 'A scatter plot of bill depth *versus* bill length.', caption = "Data: Gorman, Williams & Fraser (2014) *PLoS ONE*", x = "Bill Length (mm)", y = "Bill Depth (mm)", color = "Body mass (g)") + theme_minimal(base_family = "RobotoCondensed", base_size = 12) + theme(plot.title = element_markdown(face = "bold"), plot.subtitle = element_markdown(), plot.caption = element_markdown(margin = margin(t = 15)), axis.title.x = element_markdown(), axis.title.y = element_markdown()) + theme(plot.title.position = "plot") + * theme(plot.caption.position = "plot") ``` ] .panel2-scherer-auto[ <img src="lecture06_plotting_files/figure-html/scherer_auto_14_output-1.png" width="504" /> ] --- count: false .panel1-scherer-auto[ ```r culmen <- png::readPNG(here::here("site/lectures/img/plot_culmen_depth.png"), native = TRUE) penguins %>% filter(across(ends_with("mm"), ~!is.na(.x))) %>% ggplot(aes(x = bill_length_mm, y = bill_depth_mm)) + ggforce::geom_mark_ellipse( aes(fill = species, label = species), alpha = 0, show.legend = FALSE ) + geom_point(aes(color = body_mass_g), alpha = .6, size = 3.5) + scale_x_continuous(breaks = seq(25, 65, by = 5), limits = c(25, 65)) + scale_y_continuous(breaks = seq(12, 24, by = 2), limits = c(12, 24)) + scale_color_viridis_c(option = "turbo", labels = scales::comma) + labs( title = "Bill Dimensions of Brush-Tailed Penguins (<i style='color:#28A87D;'>*Pygoscelis*</i>)", subtitle = 'A scatter plot of bill depth *versus* bill length.', caption = "Data: Gorman, Williams & Fraser (2014) *PLoS ONE*", x = "Bill Length (mm)", y = "Bill Depth (mm)", color = "Body mass (g)") + theme_minimal(base_family = "RobotoCondensed", base_size = 12) + theme(plot.title = element_markdown(face = "bold"), plot.subtitle = element_markdown(), plot.caption = element_markdown(margin = margin(t = 15)), axis.title.x = element_markdown(), axis.title.y = element_markdown()) + theme(plot.title.position = "plot") + theme(plot.caption.position = "plot") + * theme(legend.position = "top") ``` ] .panel2-scherer-auto[ <img src="lecture06_plotting_files/figure-html/scherer_auto_15_output-1.png" width="504" /> ] --- count: false .panel1-scherer-auto[ ```r culmen <- png::readPNG(here::here("site/lectures/img/plot_culmen_depth.png"), native = TRUE) penguins %>% filter(across(ends_with("mm"), ~!is.na(.x))) %>% ggplot(aes(x = bill_length_mm, y = bill_depth_mm)) + ggforce::geom_mark_ellipse( aes(fill = species, label = species), alpha = 0, show.legend = FALSE ) + geom_point(aes(color = body_mass_g), alpha = .6, size = 3.5) + scale_x_continuous(breaks = seq(25, 65, by = 5), limits = c(25, 65)) + scale_y_continuous(breaks = seq(12, 24, by = 2), limits = c(12, 24)) + scale_color_viridis_c(option = "turbo", labels = scales::comma) + labs( title = "Bill Dimensions of Brush-Tailed Penguins (<i style='color:#28A87D;'>*Pygoscelis*</i>)", subtitle = 'A scatter plot of bill depth *versus* bill length.', caption = "Data: Gorman, Williams & Fraser (2014) *PLoS ONE*", x = "Bill Length (mm)", y = "Bill Depth (mm)", color = "Body mass (g)") + theme_minimal(base_family = "RobotoCondensed", base_size = 12) + theme(plot.title = element_markdown(face = "bold"), plot.subtitle = element_markdown(), plot.caption = element_markdown(margin = margin(t = 15)), axis.title.x = element_markdown(), axis.title.y = element_markdown()) + theme(plot.title.position = "plot") + theme(plot.caption.position = "plot") + theme(legend.position = "top") + * guides(color = guide_colorbar(title.position = "top", * title.hjust = .5, * barwidth = unit(20, "lines"), * barheight = unit(.5, "lines"))) ``` ] .panel2-scherer-auto[ <img src="lecture06_plotting_files/figure-html/scherer_auto_16_output-1.png" width="504" /> ] --- count: false .panel1-scherer-auto[ ```r culmen <- png::readPNG(here::here("site/lectures/img/plot_culmen_depth.png"), native = TRUE) penguins %>% filter(across(ends_with("mm"), ~!is.na(.x))) %>% ggplot(aes(x = bill_length_mm, y = bill_depth_mm)) + ggforce::geom_mark_ellipse( aes(fill = species, label = species), alpha = 0, show.legend = FALSE ) + geom_point(aes(color = body_mass_g), alpha = .6, size = 3.5) + scale_x_continuous(breaks = seq(25, 65, by = 5), limits = c(25, 65)) + scale_y_continuous(breaks = seq(12, 24, by = 2), limits = c(12, 24)) + scale_color_viridis_c(option = "turbo", labels = scales::comma) + labs( title = "Bill Dimensions of Brush-Tailed Penguins (<i style='color:#28A87D;'>*Pygoscelis*</i>)", subtitle = 'A scatter plot of bill depth *versus* bill length.', caption = "Data: Gorman, Williams & Fraser (2014) *PLoS ONE*", x = "Bill Length (mm)", y = "Bill Depth (mm)", color = "Body mass (g)") + theme_minimal(base_family = "RobotoCondensed", base_size = 12) + theme(plot.title = element_markdown(face = "bold"), plot.subtitle = element_markdown(), plot.caption = element_markdown(margin = margin(t = 15)), axis.title.x = element_markdown(), axis.title.y = element_markdown()) + theme(plot.title.position = "plot") + theme(plot.caption.position = "plot") + theme(legend.position = "top") + guides(color = guide_colorbar(title.position = "top", title.hjust = .5, barwidth = unit(20, "lines"), barheight = unit(.5, "lines"))) + * coord_cartesian(expand = FALSE, clip = "off") ``` ] .panel2-scherer-auto[ <img src="lecture06_plotting_files/figure-html/scherer_auto_17_output-1.png" width="504" /> ] --- count: false .panel1-scherer-auto[ ```r culmen <- png::readPNG(here::here("site/lectures/img/plot_culmen_depth.png"), native = TRUE) penguins %>% filter(across(ends_with("mm"), ~!is.na(.x))) %>% ggplot(aes(x = bill_length_mm, y = bill_depth_mm)) + ggforce::geom_mark_ellipse( aes(fill = species, label = species), alpha = 0, show.legend = FALSE ) + geom_point(aes(color = body_mass_g), alpha = .6, size = 3.5) + scale_x_continuous(breaks = seq(25, 65, by = 5), limits = c(25, 65)) + scale_y_continuous(breaks = seq(12, 24, by = 2), limits = c(12, 24)) + scale_color_viridis_c(option = "turbo", labels = scales::comma) + labs( title = "Bill Dimensions of Brush-Tailed Penguins (<i style='color:#28A87D;'>*Pygoscelis*</i>)", subtitle = 'A scatter plot of bill depth *versus* bill length.', caption = "Data: Gorman, Williams & Fraser (2014) *PLoS ONE*", x = "Bill Length (mm)", y = "Bill Depth (mm)", color = "Body mass (g)") + theme_minimal(base_family = "RobotoCondensed", base_size = 12) + theme(plot.title = element_markdown(face = "bold"), plot.subtitle = element_markdown(), plot.caption = element_markdown(margin = margin(t = 15)), axis.title.x = element_markdown(), axis.title.y = element_markdown()) + theme(plot.title.position = "plot") + theme(plot.caption.position = "plot") + theme(legend.position = "top") + guides(color = guide_colorbar(title.position = "top", title.hjust = .5, barwidth = unit(20, "lines"), barheight = unit(.5, "lines"))) + coord_cartesian(expand = FALSE, clip = "off") + * theme(plot.margin = margin(t = 25, r = 25, b = 10, l = 25)) ``` ] .panel2-scherer-auto[ <img src="lecture06_plotting_files/figure-html/scherer_auto_18_output-1.png" width="504" /> ] --- count: false .panel1-scherer-auto[ ```r culmen <- png::readPNG(here::here("site/lectures/img/plot_culmen_depth.png"), native = TRUE) penguins %>% filter(across(ends_with("mm"), ~!is.na(.x))) %>% ggplot(aes(x = bill_length_mm, y = bill_depth_mm)) + ggforce::geom_mark_ellipse( aes(fill = species, label = species), alpha = 0, show.legend = FALSE ) + geom_point(aes(color = body_mass_g), alpha = .6, size = 3.5) + scale_x_continuous(breaks = seq(25, 65, by = 5), limits = c(25, 65)) + scale_y_continuous(breaks = seq(12, 24, by = 2), limits = c(12, 24)) + scale_color_viridis_c(option = "turbo", labels = scales::comma) + labs( title = "Bill Dimensions of Brush-Tailed Penguins (<i style='color:#28A87D;'>*Pygoscelis*</i>)", subtitle = 'A scatter plot of bill depth *versus* bill length.', caption = "Data: Gorman, Williams & Fraser (2014) *PLoS ONE*", x = "Bill Length (mm)", y = "Bill Depth (mm)", color = "Body mass (g)") + theme_minimal(base_family = "RobotoCondensed", base_size = 12) + theme(plot.title = element_markdown(face = "bold"), plot.subtitle = element_markdown(), plot.caption = element_markdown(margin = margin(t = 15)), axis.title.x = element_markdown(), axis.title.y = element_markdown()) + theme(plot.title.position = "plot") + theme(plot.caption.position = "plot") + theme(legend.position = "top") + guides(color = guide_colorbar(title.position = "top", title.hjust = .5, barwidth = unit(20, "lines"), barheight = unit(.5, "lines"))) + coord_cartesian(expand = FALSE, clip = "off") + theme(plot.margin = margin(t = 25, r = 25, b = 10, l = 25)) + * labs(caption = "Data: Gorman, Williams & Fraser (2014) *PLoS ONE* • Illustration: Allison Horst") ``` ] .panel2-scherer-auto[ <img src="lecture06_plotting_files/figure-html/scherer_auto_19_output-1.png" width="504" /> ] --- count: false .panel1-scherer-auto[ ```r culmen <- png::readPNG(here::here("site/lectures/img/plot_culmen_depth.png"), native = TRUE) penguins %>% filter(across(ends_with("mm"), ~!is.na(.x))) %>% ggplot(aes(x = bill_length_mm, y = bill_depth_mm)) + ggforce::geom_mark_ellipse( aes(fill = species, label = species), alpha = 0, show.legend = FALSE ) + geom_point(aes(color = body_mass_g), alpha = .6, size = 3.5) + scale_x_continuous(breaks = seq(25, 65, by = 5), limits = c(25, 65)) + scale_y_continuous(breaks = seq(12, 24, by = 2), limits = c(12, 24)) + scale_color_viridis_c(option = "turbo", labels = scales::comma) + labs( title = "Bill Dimensions of Brush-Tailed Penguins (<i style='color:#28A87D;'>*Pygoscelis*</i>)", subtitle = 'A scatter plot of bill depth *versus* bill length.', caption = "Data: Gorman, Williams & Fraser (2014) *PLoS ONE*", x = "Bill Length (mm)", y = "Bill Depth (mm)", color = "Body mass (g)") + theme_minimal(base_family = "RobotoCondensed", base_size = 12) + theme(plot.title = element_markdown(face = "bold"), plot.subtitle = element_markdown(), plot.caption = element_markdown(margin = margin(t = 15)), axis.title.x = element_markdown(), axis.title.y = element_markdown()) + theme(plot.title.position = "plot") + theme(plot.caption.position = "plot") + theme(legend.position = "top") + guides(color = guide_colorbar(title.position = "top", title.hjust = .5, barwidth = unit(20, "lines"), barheight = unit(.5, "lines"))) + coord_cartesian(expand = FALSE, clip = "off") + theme(plot.margin = margin(t = 25, r = 25, b = 10, l = 25)) + labs(caption = "Data: Gorman, Williams & Fraser (2014) *PLoS ONE* • Illustration: Allison Horst") + * patchwork::inset_element(culmen, left = 0.82, bottom = 0.83, right = 1, top = 1, align_to = 'full') ``` ] .panel2-scherer-auto[ <img src="lecture06_plotting_files/figure-html/scherer_auto_20_output-1.png" width="504" /> ] <style> .panel1-scherer-auto { color: black; width: 38.6060606060606%; hight: 32%; float: left; padding-left: 1%; font-size: 80% } .panel2-scherer-auto { color: black; width: 59.3939393939394%; hight: 32%; float: left; padding-left: 1%; font-size: 80% } .panel3-scherer-auto { color: black; width: NA%; hight: 33%; float: left; padding-left: 1%; font-size: 80% } </style> --- # Plot your data! .flex[ .w-60.bg-washed-yellow.b--red.ba.bw2.br3.shadow-5.ph3.mt0.ml6[ .Large[ > Never trust summary statistics alone; always visualize your data .tr[ — .bold[_Alberto Cairo_]] ] ] ] .center[ ] .footnote[source: Justin Matejka, George Fitzmaurice [Same Stats, Different Graphs...](https://www.autodeskresearch.com/publications/samestats)] --- # Missing features .pull-left[ ### geoms list [here](http://ggplot2.tidyverse.org/reference/index.html#section-layer-geoms) - `geom_tile()` heatmap - `geom_bind2d()` 2D binning - `geom_abline()` slope ### stats list [here](http://ggplot2.tidyverse.org/reference/index.html#section-layer-stats) - `stat_ellipse()` (`ggforge` seen) - `stat_summary()` easy mean, 95CI etc. ### plot on multi-pages - `ggforce::facet_grid_paginate()` facets - `gridExtra::marrangeGrob()` plots ] .pull-right[ ### coordinate / transform - `coord_cartesian()` for zooming in ### customise [_theme_](http://ggplot2.tidyverse.org/reference/index.html#section-themes) elements - legend & guide tweaks - major/minor grids - font, faces - margins - labels & ticks - strip positions - see [live examples](https://www.r-graph-gallery.com/ggplot2-package.html) of pre-built themes ] --- # Build your plot with point and click #### Using `esquisse` Rstudio addin by [dreamRs](https://github.com/dreamRs/esquisse)
.center[<img src = "https://raw.githubusercontent.com/dreamRs/esquisse/master/man/figures/esquisse.png", style = "height:450px">] --- class: hide_logo # Before we stop .flex[ .w-50.bg-washed-green.b--green.ba.bw2.br3.shadow-5.ph3.mt2.ml1[ .large[.gbox[You learned to:] - Apprehend Graphics as a language - Embrace the layer system - Link data columns to aesthetics - Discover geometries and scales - The endless potential of cosmetic improvements ]] .w-50.bg-washed-green.b--green.ba.bw2.br3.shadow-5.ph3.mt2.ml2[ .large[.bbox[Acknowledgments 🙏 👏]] * [Thomas Lin Pedersen](https://github.com/thomasp85), great webinar _Plotting everything with ggplot2_: + [part 1, ggplot2 API](https://www.youtube.com/watch?v=h29g21z0a68) + [part 2, extending ggplot2](https://www.youtube.com/watch?v=0m4yywqNPVY) * [Thinkr](https://thinkr.fr/) (Diane Beldame, Vincent Guyader, Colin Fay) * [Allison M. Horst, Alison P. Hill and Kristen B. Gorman](https://github.com/allisonhorst/palmerpenguins) `*` * [DreamRs](https://www.dreamrs.fr/) (Victor Perrier, Fanny Meyer * [Romain Lesur](https://github.com/RLesur) (`pagedown`), [Christophe Dervieux](https://github.com/cderv) * [Hadley Wickham](https://github.com/hadley) * [Cédric Scherer](https://cedricscherer.netlify.app) ]] .flex[ .w-50.bg-washed-green.b--green.ba.bw2.br3.shadow-5.ph3.mt2.ml1[ .large[.ybox[Further reading 📚]] - [ggplot2 book](https://ggplot2-book.org/) by H. Wickham (free access) - [**NEW** official FAQ](https://ggplot2.tidyverse.org/articles/articles/faq-axes.html), axes, facets, custom, annot, reorder, bars - [R for Data Science](https://r4ds.had.co.nz/) by H. Wickham / G. Gromelund (free access) - [TidyTuesday challenges](https://www.tidytuesday.com/) - [Vizualisation gallery](https://cedricscherer.netlify.app/top/dataviz/) by Cédric Scherer - [plotting tutorial](https://cedricscherer.netlify.app/2019/08/05/a-ggplot2-tutorial-for-beautiful-plotting-in-r) by Cédric Scherer ] .w-50.pv2.ph3.mt2.ml1[ .huge[.bbox[Thank you for your attention!]] ]] .center[.footnote[`*`: Palmer penguins, data are available by CC-0 license and `Artwork` by Allison Horst]]