diff --git a/_freeze/materials/00-welcome/execute-results/html.json b/_freeze/materials/00-welcome/execute-results/html.json
index 64eaf0d..4997f52 100644
--- a/_freeze/materials/00-welcome/execute-results/html.json
+++ b/_freeze/materials/00-welcome/execute-results/html.json
@@ -1,7 +1,7 @@
{
- "hash": "4c2a284f2b9347b0491952f959acb465",
+ "hash": "30e2dc92d571d0b4a5cf7552814831d3",
"result": {
- "markdown": "---\ntitle: \"Engaging and Beautiful Data Visualizations with ggplot2\"\nsubtitle: \"Welcome!\"\nauthor: \"Cédric Scherer // posit::conf // September 2023\"\nformat:\n revealjs:\n theme: slides.scss\n logo: img/logo.png\n footer: '**[Cédric Scherer](https://cedricscherer.com)** // posit::conf(2023)'\n transition: fade\n progress: true\n multiplex: false\n preview-links: true\n scrollable: false\n hide-inactive-cursor: true\n highlight-style: printing\n chalkboard:\n theme: whiteboard\n boardmarker-width: 4\n buttons: true\n pause: true\neditor: source\nknitr:\n opts_chunk:\n dev: \"ragg_png\"\n retina: 3\n dpi: 200\nexecute:\n freeze: auto\n cache: true\n echo: true\n fig-width: 5\n fig-height: 6\n---\n\n\n\n# Welcome
{background-image=\"img/logo-welcome.png\" background-position=\"center\" background-size=\"40%\"}\n\n\n\n## {#hello-blank data-menu-title=\"Hello\" background-image=\"img/intro/hello-blank.png\" background-position=\"center\" background-size=\"62%\"}\n\n\n\n## {#hello-team data-menu-title=\"Hello Team\" background-image=\"img/intro/hello-team.png\" background-position=\"center\" background-size=\"62%\"}\n\n\n\n## {#teaching-team data-menu-title=\"Teaching Team\" background-image=\"img/intro/team-hex-grid.png\" background-position=\"center\" background-size=\"105%\"}\n\n\n\n## {#hello-cedric data-menu-title=\"Hello Cédric\" background-image=\"img/intro/hello-cedric.png\" background-position=\"center\" background-size=\"62%\"}\n\n\n\n## {#cedric-avatars data-menu-title=\"Cédric Avatars\" background-image=\"img/intro/avatars-logo.png\" background-position=\"center\" background-size=\"80%\"}\n\n\n\n## {#cedric-dataviz-science data-menu-title=\"Cédric Projects Science\" background-image=\"img/intro/projects-science.png\" background-position=\"center\" background-size=\"82%\" background-color=\"#ABABAB\"}\n\n::: footer\n:::\n\n\n\n## {#cedric-dataviz-clients data-menu-title=\"Cédric Projects Clients\" background-image=\"img/intro/projects-clients.png\" background-position=\"center\" background-size=\"77%\" background-color=\"#ABABAB\"}\n\n::: footer\n:::\n\n\n\n## {#cedric-dataviz-personal data-menu-title=\"Cédric Projects Personal\"background-image=\"img/intro/projects-personal.png\" background-position=\"center\" background-size=\"85%\" background-color=\"#ABABAB\"}\n\n::: footer\n:::\n\n\n\n## {#cedric-blog data-menu-title=\"Cédric Blog\"background-image=\"img/intro/blog.png\" background-position=\"center\" background-size=\"56%\"}\n\n::: footer\n:::\n\n\n\n## {#cedric-ggplot-tutorial data-menu-title=\"Cédric Blog Tutorial\" background-image=\"img/intro/blog-tutorial.png\" background-position=\"center\" background-size=\"56%\"}\n\n::: footer\n:::\n\n\n\n## {#cedric-ggplot-tutorial-overview data-menu-title=\"Cédric Blog Tutorial Overview\"}\n\n![[cedricscherer.com/2019/08/05/a-ggplot2-tutorial-for-beautiful-plotting-in-r](https://www.cedricscherer.com/2019/08/05/a-ggplot2-tutorial-for-beautiful-plotting-in-r/)](img/intro/ggplot-tutorial-overview.png){fig-align=\"center\" fig-alt=\"Overview of some exemplary plots included in my ggplot2 tutorial.\"}\n\n\n\n## {#cedric-ggplot-evol data-menu-title=\"Cédric Blog ggplot Evolution\" background-image=\"img/intro/blog-evol.png\" background-position=\"center\" background-size=\"56%\"}\n\n::: footer\n:::\n\n\n\n## {#cedric-ggplot-evol-gif data-menu-title=\"Cédric Blog ggplot Evolution GIF\"}\n\n![[cedricscherer.com/2019/05/17/the-evolution-of-a-ggplot](https://www.cedricscherer.com/2019/05/17/the-evolution-of-a-ggplot)](img/intro/evol-ggplot-1.gif){fig-align=\"center\" fig-alt=\"Animated evolution of a jitter-pop plot showing student-teacher ratios per continent. The animation shows iteration through different geometries, theme adjustments, combinations of layers, and additional annotations such as text labels with arrows and an inset tile grid map with colors by region mathing those of the main graphic.\"}\n\n\n\n## {#cedric-rstudio-conf data-menu-title=\"Cédric Blog rstudio::conf\" background-image=\"img/intro/blog-rstudioconf.png\" background-position=\"center\" background-size=\"56%\"}\n\n::: footer\n:::\n\n\n\n## {#hello-thomas data-menu-title=\"Hello Thomas\" background-image=\"img/intro/hello-thomas.png\" background-position=\"center\" background-size=\"62%\"}\n\n\n\n## {#thomas-artwork data-menu-title=\"Thomas Artwork\"}\n\n![Artwork by Thomas Linn Pedersen](img/intro/thomas_artwork.png)\n\n\n\n## {#hello-jasmin data-menu-title=\"Hello Jasmin\" background-image=\"img/intro/hello-jasmin.png\" background-position=\"center\" background-size=\"62%\"}\n\n\n\n## {#jasmin-dataviz data-menu-title=\"Jasmin Data Visualization\"}\n\n![Graphic by Jasmin Sarah König](img/intro/jasmin-overview.png)\n\n\n\n## {#jasmin-dataviz-observable data-menu-title=\"Jasmin Data Visualization\"}\n\n\n\n\n\n## {#hello-jonathan data-menu-title=\"Hello Jonathan\" background-image=\"img/intro/hello-jonathan.png\" background-position=\"center\" background-size=\"62%\"}\n\n\n\n## {#jonathan-photography-japan data-menu-title=\"Jonathan Photography\"}\n\n![Photo by Jonathan Keane](img/intro/jonathan-japan.jpg)\n\n\n\n## {#hello-course data-menu-title=\"Hello Course\" background-image=\"img/intro/hello-course.png\" background-position=\"center\" background-size=\"62%\"}\n\n\n\n## Conversation Starters\n\n- What's your name?\n- Where do you feel home?\n- When did you use R for the first time?\n- What's your favorite animal / plant / color / typeface?\n- Where did you spend your summer?\n- Whom would you like to meet during the posit::conf?\n- Which R package are you looking forward to try?\n- What are things you want to learn about ggplot2?\n\n\n\n## Announcements\n\n
\n\n#### WiFi\n- Username: Posit Conf 2023\n- Password: conf2023
\n\n#### Course Materials\n- Webpage: [posit-conf-2023.github.io/dataviz-ggplot2](https://posit-conf-2023.github.io/dataviz-ggplot2/)\n- Posit Cloud: [posit.cloud/spaces/397253](https://posit.cloud/spaces/397253/content/all?sort=name_asc)\n\n\n\n## {#course-webpage data-menu-title=\"Course Webpage\" .center}\n\n
\n\n\n\n## {#posit-cloud data-menu-title=\"Posit Cloud\" .center}\n\n\n\n\n\n## Announcements\n\n::: incremental\n- **Gender-neutral bathrooms** are located among the Grand Suite Bathrooms.\n- The two **meditation/prayer rooms** (Grand Suite 2A and Grand Suite 2B) are open Sunday-Tuesday 7:30 am-7:00 pm and Wednesday 8:00 am-6:00 pm\n- The **lactation room** is located in Grand Suite 1 and open Sunday-Tuesday 7:30 am-7:00 pm and Wednesday 8:00 am-6:00 pm.\n- Participants who do not wish to be photographed have **red lanyards**; please note everyone's lanyard colors before taking a photo and respect their choices.\n- The **Code of Conduct** and **COVID** policies can be found at [posit.co/code-of-conduct](https://posit.co/code-of-conduct). Please review them carefully. You can report Code of Conduct violations in person, by email, or by phone. Please see the policy linked above for contact information.\n:::\n\n\n\n## Communication Strategy\n\n
\n\n::: incremental\n- Green sticky note --- I am done with the exercise
\n- Pink sticky note --- I need help or support
\n- You can ask questions / comment at any time during the course.\n- Please avoid questions during the breaks to give us a chance to recover.\n- We will be using Discord as our main digital communication method.\n- Team up with your neighbors for exercises --- and lunch!\n- We will collect feedback twice during the day (more later).\n:::\n\n\n\n# Preparation\n\n\n\n## Required Packages\n\n\n::: {.cell hash='00-welcome_cache/revealjs/packages-install-tidyverse_88585319b84dbef92a58fccba66b637e'}\n\n```{.r .cell-code}\ninstall.packages(\"ggplot2\")\ninstall.packages(\"dplyr\")\ninstall.packages(\"readr\")\ninstall.packages(\"forcats\")\ninstall.packages(\"stringr\")\ninstall.packages(\"lubridate\")\ninstall.packages(\"purrr\")\n```\n:::\n\n\n::: fragment\n\n::: {.cell hash='00-welcome_cache/revealjs/packages-install-other_057c75c7a29cffb13735c8f36543a25c'}\n\n```{.r .cell-code}\ninstall.packages(\"here\")\ninstall.packages(\"scales\")\ninstall.packages(\"ragg\")\ninstall.packages(\"systemfonts\")\ninstall.packages(\"rcartocolor\")\ninstall.packages(\"scico\")\ninstall.packages(\"prismatic\")\ninstall.packages(\"patchwork\")\ninstall.packages(\"ggtext\")\ninstall.packages(\"ggforce\")\ninstall.packages(\"ggrepel\")\ninstall.packages(\"colorspace\")\ninstall.packages(\"gapminder\")\nremotes::install_github(\"clauswilke/colorblindr\")\n```\n:::\n\n:::\n\n\n\n## Optional Packages\n\n\n::: {.cell hash='00-welcome_cache/revealjs/packages-install-optional_6f3a9d7feebf705a88edbc23d7bb3537'}\n\n```{.r .cell-code}\ninstall.packages(\"camcorder\")\ninstall.packages(\"viridis\")\ninstall.packages(\"RColorBrewer\")\ninstall.packages(\"MetBrewer\")\ninstall.packages(\"ggthemes\")\ninstall.packages(\"ggsci\")\ninstall.packages(\"hrbrthemes\")\ninstall.packages(\"tvthemes\")\ninstall.packages(\"ggannotate\")\nremotes::install_github(\"AllanCameron/geomtextpath\")\n```\n:::\n\n\n\n\n## Required Typefaces\n\nDownload and install the following typefaces:\n\n* Asap: [fonts.google.com/specimen/Asap](https://fonts.google.com/specimen/Asap)\n* Spline Sans: [fonts.google.com/specimen/Spline+Sans](https://fonts.google.com/specimen/Spline+Sans)\n* Spline Sans Mono: [fonts.google.com/specimen/Spline+Sans+Mono](https://fonts.google.com/specimen/Spline+Sans+Mono)\n* Hepta Slab: [fonts.google.com/specimen/Hepta+Slab](https://fonts.google.com/specimen/Hepta+Slab)\n\n. . . \n\nAll files are also available via
[cedricscherer.com/files/positconf-dataviz-ggplot2-fonts.zip](https://cedricscherer.com/files/positconf-dataviz-ggplot2-fonts.zip)\n\n. . . \n\n→ Install the font files. \n\n. . . \n \n→ Restart Rstudio.\n\n\n\n# Let's get started!\n",
+ "markdown": "---\ntitle: \"Engaging and Beautiful Data Visualizations with ggplot2\"\nsubtitle: \"Welcome!\"\nauthor: \"Cédric Scherer // posit::conf // September 2023\"\nformat:\n revealjs:\n theme: slides.scss\n logo: img/logo.png\n footer: '**[Cédric Scherer](https://cedricscherer.com)** // posit::conf(2023)'\n transition: fade\n progress: true\n multiplex: false\n preview-links: true\n scrollable: false\n hide-inactive-cursor: true\n highlight-style: printing\n chalkboard:\n theme: whiteboard\n boardmarker-width: 4\n buttons: true\n pause: true\neditor: source\nknitr:\n opts_chunk:\n dev: \"ragg_png\"\n retina: 3\n dpi: 200\nexecute:\n freeze: auto\n cache: true\n echo: true\n fig-width: 5\n fig-height: 6\n---\n\n\n\n# Welcome
{background-image=\"img/logo-welcome.png\" background-position=\"center\" background-size=\"40%\"}\n\n\n\n## {#hello-blank data-menu-title=\"Hello\" background-image=\"img/intro/hello-blank.png\" background-position=\"center\" background-size=\"62%\"}\n\n\n\n## {#hello-team data-menu-title=\"Hello Team\" background-image=\"img/intro/hello-team.png\" background-position=\"center\" background-size=\"62%\"}\n\n\n\n## {#teaching-team data-menu-title=\"Teaching Team\" background-image=\"img/intro/team-hex-grid.png\" background-position=\"center\" background-size=\"105%\"}\n\n\n\n## {#hello-cedric data-menu-title=\"Hello Cédric\" background-image=\"img/intro/hello-cedric.png\" background-position=\"center\" background-size=\"62%\"}\n\n\n\n## {#cedric-avatars data-menu-title=\"Cédric Avatars\" background-image=\"img/intro/avatars-logo.png\" background-position=\"center\" background-size=\"80%\"}\n\n\n\n## {#cedric-dataviz-science data-menu-title=\"Cédric Projects Science\" background-image=\"img/intro/projects-science.png\" background-position=\"center\" background-size=\"82%\" background-color=\"#ABABAB\"}\n\n::: footer\n:::\n\n\n\n## {#cedric-dataviz-clients data-menu-title=\"Cédric Projects Clients\" background-image=\"img/intro/projects-clients.png\" background-position=\"center\" background-size=\"77%\" background-color=\"#ABABAB\"}\n\n::: footer\n:::\n\n\n\n## {#cedric-dataviz-personal data-menu-title=\"Cédric Projects Personal\"background-image=\"img/intro/projects-personal.png\" background-position=\"center\" background-size=\"85%\" background-color=\"#ABABAB\"}\n\n::: footer\n:::\n\n\n\n## {#cedric-blog data-menu-title=\"Cédric Blog \"background-image=\"img/intro/blog.png\" background-position=\"center\" background-size=\"56%\"}\n\n::: footer\n:::\n\n\n\n## {#cedric-ggplot-tutorial data-menu-title=\"Cédric Blog Tutorial\" background-image=\"img/intro/blog-tutorial.png\" background-position=\"center\" background-size=\"56%\"}\n\n::: footer\n:::\n\n\n\n## {#cedric-ggplot-tutorial-overview data-menu-title=\"Cédric Blog Tutorial Overview\"}\n\n![[cedricscherer.com/2019/08/05/a-ggplot2-tutorial-for-beautiful-plotting-in-r](https://www.cedricscherer.com/2019/08/05/a-ggplot2-tutorial-for-beautiful-plotting-in-r/)](img/intro/ggplot-tutorial-overview.png){fig-align=\"center\" fig-alt=\"Overview of some exemplary plots included in my ggplot2 tutorial.\"}\n\n\n\n## {#cedric-ggplot-evol data-menu-title=\"Cédric Blog ggplot Evolution\" background-image=\"img/intro/blog-evol.png\" background-position=\"center\" background-size=\"56%\"}\n\n::: footer\n:::\n\n\n\n## {#cedric-ggplot-evol-gif data-menu-title=\"Cédric Blog ggplot Evolution GIF\"}\n\n![[cedricscherer.com/2019/05/17/the-evolution-of-a-ggplot](https://www.cedricscherer.com/2019/05/17/the-evolution-of-a-ggplot)](img/intro/evol-ggplot-1.gif){fig-align=\"center\" fig-alt=\"Animated evolution of a jitter-pop plot showing student-teacher ratios per continent. The animation shows iteration through different geometries, theme adjustments, combinations of layers, and additional annotations such as text labels with arrows and an inset tile grid map with colors by region mathing those of the main graphic.\"}\n\n\n\n## {#cedric-rstudio-conf data-menu-title=\"Cédric Blog rstudio::conf\" background-image=\"img/intro/blog-rstudioconf.png\" background-position=\"center\" background-size=\"56%\"}\n\n::: footer\n:::\n\n\n\n## {#hello-thomas data-menu-title=\"Hello Thomas\" background-image=\"img/intro/hello-thomas.png\" background-position=\"center\" background-size=\"62%\"}\n\n\n\n## {#thomas-artwork data-menu-title=\"Thomas Artwork\"}\n\n![Artwork by Thomas Linn Pedersen](img/intro/thomas_artwork.png)\n\n\n\n## {#hello-jasmin data-menu-title=\"Hello Jasmin\" background-image=\"img/intro/hello-jasmin.png\" background-position=\"center\" background-size=\"62%\"}\n\n\n\n## {#jasmin-dataviz data-menu-title=\"Jasmin Data Visualization\"}\n\n![Graphic by Jasmin Sarah König](img/intro/jasmin-overview.png)\n\n\n\n## {#jasmin-dataviz-observable data-menu-title=\"Jasmin Data Visualization\"}\n\n\n\n\n\n## {#hello-jonathan data-menu-title=\"Hello Jonathan\" background-image=\"img/intro/hello-jonathan.png\" background-position=\"center\" background-size=\"62%\"}\n\n\n\n## {#jonathan-photography-japan data-menu-title=\"Jonathan Photography\"}\n\n![Photo by Jonathan Keane](img/intro/jonathan-japan.jpg)\n\n\n\n## {#hello-course data-menu-title=\"Hello Course\" background-image=\"img/intro/hello-course.png\" background-position=\"center\" background-size=\"62%\"}\n\n\n\n## Conversation Starters\n\n- What's your name?\n- Where do you feel home?\n- When did you use R for the first time?\n- What's your favorite animal / plant / color / typeface?\n- Where did you spend your summer?\n- Whom would you like to meet during the posit::conf?\n- Which R package are you looking forward to try?\n- What are things you want to learn about ggplot2?\n\n\n\n## Announcements\n\n
\n\n#### WiFi\n- Username: Posit Conf 2023\n- Password: conf2023
\n\n#### Course Materials\n- Webpage: [posit-conf-2023.github.io/dataviz-ggplot2](https://posit-conf-2023.github.io/dataviz-ggplot2/)\n- Posit Cloud: [posit.cloud/spaces/397253](https://posit.cloud/spaces/397253/content/all?sort=name_asc)\n\n\n\n## {#course-webpage data-menu-title=\"Course Webpage\" .center}\n\n\n\n\n\n## {#posit-cloud data-menu-title=\"Posit Cloud\" .center}\n\n\n\n\n\n## Announcements\n\n::: incremental\n- **Gender-neutral bathrooms** are located among the Grand Suite Bathrooms.\n- The two **meditation/prayer rooms** (Grand Suite 2A and Grand Suite 2B) are open Sunday-Tuesday 7:30 am-7:00 pm and Wednesday 8:00 am-6:00 pm\n- The **lactation room** is located in Grand Suite 1 and open Sunday-Tuesday 7:30 am-7:00 pm and Wednesday 8:00 am-6:00 pm.\n- Participants who do not wish to be photographed have **red lanyards**; please note everyone's lanyard colors before taking a photo and respect their choices.\n- The **Code of Conduct** and **COVID** policies can be found at [posit.co/code-of-conduct](https://posit.co/code-of-conduct). Please review them carefully. You can report Code of Conduct violations in person, by email, or by phone. Please see the policy linked above for contact information.\n:::\n\n\n\n## Communication Strategy\n\n
\n\n::: incremental\n- Green sticky note --- I am done with the exercise
\n- Pink sticky note --- I need help or support
\n- You can ask questions / comment at any time during the course.\n- Please avoid questions during the breaks to give us a chance to recover.\n- We will be using Discord as our main digital communication method.\n- Team up with your neighbors for exercises --- and lunch!\n- We will collect feedback twice during the day (more later).\n:::\n\n\n\n# Preparation\n\n\n\n## Required Packages\n\n\n::: {.cell hash='00-welcome_cache/revealjs/packages-install-tidyverse_88585319b84dbef92a58fccba66b637e'}\n\n```{.r .cell-code}\ninstall.packages(\"ggplot2\")\ninstall.packages(\"dplyr\")\ninstall.packages(\"readr\")\ninstall.packages(\"forcats\")\ninstall.packages(\"stringr\")\ninstall.packages(\"lubridate\")\ninstall.packages(\"purrr\")\n```\n:::\n\n\n::: fragment\n\n::: {.cell hash='00-welcome_cache/revealjs/packages-install-other_057c75c7a29cffb13735c8f36543a25c'}\n\n```{.r .cell-code}\ninstall.packages(\"here\")\ninstall.packages(\"scales\")\ninstall.packages(\"ragg\")\ninstall.packages(\"systemfonts\")\ninstall.packages(\"rcartocolor\")\ninstall.packages(\"scico\")\ninstall.packages(\"prismatic\")\ninstall.packages(\"patchwork\")\ninstall.packages(\"ggtext\")\ninstall.packages(\"ggforce\")\ninstall.packages(\"ggrepel\")\ninstall.packages(\"colorspace\")\ninstall.packages(\"gapminder\")\nremotes::install_github(\"clauswilke/colorblindr\")\n```\n:::\n\n:::\n\n\n\n## Optional Packages\n\n\n::: {.cell hash='00-welcome_cache/revealjs/packages-install-optional_6f3a9d7feebf705a88edbc23d7bb3537'}\n\n```{.r .cell-code}\ninstall.packages(\"camcorder\")\ninstall.packages(\"viridis\")\ninstall.packages(\"RColorBrewer\")\ninstall.packages(\"MetBrewer\")\ninstall.packages(\"ggthemes\")\ninstall.packages(\"ggsci\")\ninstall.packages(\"hrbrthemes\")\ninstall.packages(\"tvthemes\")\ninstall.packages(\"ggannotate\")\nremotes::install_github(\"AllanCameron/geomtextpath\")\n```\n:::\n\n\n\n\n## Required Typefaces\n\nDownload and install the following typefaces:\n\n* Asap: [fonts.google.com/specimen/Asap](https://fonts.google.com/specimen/Asap)\n* Spline Sans: [fonts.google.com/specimen/Spline+Sans](https://fonts.google.com/specimen/Spline+Sans)\n* Spline Sans Mono: [fonts.google.com/specimen/Spline+Sans+Mono](https://fonts.google.com/specimen/Spline+Sans+Mono)\n* Hepta Slab: [fonts.google.com/specimen/Hepta+Slab](https://fonts.google.com/specimen/Hepta+Slab)\n\n. . . \n\nAll files are also available via
[cedricscherer.com/files/positconf-dataviz-ggplot2-fonts.zip](https://cedricscherer.com/files/positconf-dataviz-ggplot2-fonts.zip)\n\n. . . \n\n→ Install the font files. \n\n. . . \n \n→ Restart Rstudio.\n\n\n\n# Let's get started!\n",
"supporting": [],
"filters": [
"rmarkdown/pagebreak.lua"
diff --git a/_freeze/materials/01-fundamentals/execute-results/html.json b/_freeze/materials/01-fundamentals/execute-results/html.json
index af02a85..d1300f8 100644
--- a/_freeze/materials/01-fundamentals/execute-results/html.json
+++ b/_freeze/materials/01-fundamentals/execute-results/html.json
@@ -1,7 +1,7 @@
{
- "hash": "a7040cf60680b842b8f94cd9aa262af8",
+ "hash": "e6e1ffe660743a0103dd963a55d94927",
"result": {
- "markdown": "---\ntitle: \"Engaging and Beautiful Data Visualizations with ggplot2\"\nsubtitle: \"Fundamentals & Workflows\"\nauthor: \"Cédric Scherer // posit::conf // September 2023\"\nformat:\n revealjs:\n theme: slides.scss\n logo: img/logo.png\n footer: '[Cédric Scherer](https://cedricscherer.com) // posit::conf(2023)'\n transition: fade\n progress: true\n multiplex: false\n preview-links: true\n scrollable: false\n hide-inactive-cursor: true\n highlight-style: printing\n chalkboard:\n theme: whiteboard\n boardmarker-width: 4\n buttons: true\n pause: true\neditor: source\nknitr:\n opts_chunk:\n dev: \"ragg_png\"\n retina: 3\n dpi: 200\nexecute:\n freeze: auto\n cache: true\n echo: true\n fig-width: 10.1\n fig-height: 6.3\n fig-align: center\n---\n\n\n\n\n\n# {ggplot2}\n\n\n##\n\n::: footer\n[{ggplot2} package description](https://ggplot2.tidyverse.org/)\n:::\n\n![](img/intro/ggplot2.png){fig-align=\"center\" fig-alt=\"The ggplot2 hex logo.\"}\n\n
\n\n{ggplot2}
is a system for declaratively creating graphics,
based on \"The Grammar of Graphics\" (Wilkinson 2005).\n\n::: fragment\n[You provide the data, tell {ggplot2}
how to]{style=\"font-size:24pt;\"} [map variables to aesthetics,]{.circle-highlight}
what graphical primitives to use, and it takes care of the details.\n:::\n\n## Advantages of {ggplot2}\n\n::: incremental\n- consistent underlying \"grammar of graphics\" (Wilkinson 2005)\\\n- very flexible, layered plot specification\\\n- theme system for polishing plot appearance\\\n- lots of additional functionality thanks to extensions\\\n- active and helpful community\n:::\n\n\n## The Components of a ggplot\n\n
\n\n \n Component | \n Function | \n Explanation | \n
\n \n Data | \n ggplot(data) | \n *The raw data that you want to visualize.* | \n
\n \n Aesthetics | \n aes() | \n *The mapping between variables and visual properties* | \n
\n Geometries | \n geom_*() | \n *The geometric shapes representing the data.* | \n
\n
\n\n--------------------------------------------------------------------------------\n\n![ggplot2 examples featured on [ggplot2.tidyverse.org](https://ggplot2.tidyverse.org/)](img/basic-ggplots.png){fig-align=\"center\" fig-alt=\"A collection of the versatility of ggplot2 to create basic graphs. All of them use only data, aesthetics, and layers with the defaults of ggplot2.\"}\n\n\n## The Components of a ggplot\n\n\n
\n\n \n Component | \n Function | \n Explanation | \n
\n \n Data | \n ggplot(data) | \n *The raw data that you want to visualize.* | \n
\n \n Aesthetics | \n aes() | \n *The mapping between variables and visual properties.* | \n
\n Geometries | \n geom_*() | \n *The geometric shapes representing the data.* | \n
\n \n Statistics | \n stat_*() | \n *The statistical transformations applied to the data.* | \n
\n \n Scales | \n scale_*() | \n *The representation of mapped aesthetic attributes.* | \n
\n \n Coordinate System | \n coord_*() | \n *The transformation to map data coordinates into the plot plane.* | \n
\n \n Facets | \n facet_*() | \n *The arrangement of the data into a grid of small multiples.* | \n
\n \n Visual Themes | \n theme() | theme_*() | \n *The overall visual defaults of non-data elements of the graphic.* | \n
\n
\n\n--------------------------------------------------------------------------------\n\n![Illustration by [Allison Horst](https://github.com/allisonhorst/stats-illustrations)](img/ah-ggplot2-exploratory.png){fig-align=\"center\" fig-alt=\"Allison Horsts monster illustration of explorative plotting with ggplot2.\"}\n\n--------------------------------------------------------------------------------\n\n![Illustration by [Allison Horst](https://github.com/allisonhorst/stats-illustrations)](img/ah-ggplot2-masterpiece.png){fig-align=\"center\" fig-alt=\"Allison Horsts monster illustration of building data masterpiece ith ggplot2 featuring a little Picasso monster :)\"}\n\n\n# The {ggplot2} Showcase\n\n--------------------------------------------------------------------------------\n\n
\n\n![Collection of Graphics from the [BBC R Cookbook](https://bbc.github.io/rcookbook/)](img/showcase/bbc-gallery.png){fig-align=\"center\" fig-alt=\"A multi-plot panel of various data visualizations created by the BBC teams.\"}\n\n--------------------------------------------------------------------------------\n\n
\n\n![Collection of Graphics from the [BBC R Cookbook](https://bbc.github.io/rcookbook/)](img/showcase/bbc-gallery-quote.png){fig-align=\"center\" fig-alt=\"A multi-plot panel of various data visualizations created by the BBC teams.\"}\n\n--------------------------------------------------------------------------------\n\n![[\"Bill Dimensions of Brush-Tailed Penguins\"](https://github.com/Z3tt/TidyTuesday/tree/main/plots/2020_31)](img/showcase/palmer-penguins.png){fig-align=\"center\" fig-size=\"80%\" fig-alt=\"Distribution of coffee bean ratings by the Coffee Quality Institute for countries with 25 or more reviews (up to 2018). Distributions are shown as dot plots and multiple interval stripes.\"}\n\n--------------------------------------------------------------------------------\n\n![[\"Netflix Content Explosion\"](https://twitter.com/tanya_shapiro/status/1610419176333627393) by Tanya Shapiro](img/showcase/netflix-originals-tanya-shapiro.jpeg){fig-align=\"center\" fig-size=\"50%\" fig-alt=\"rea graph of number of Netflix original series over time, annotated with images and labels.\"}\n\n--------------------------------------------------------------------------------\n\n![My reinterpreted [The Economist graphic](https://www.economist.com/graphic-detail/2019/09/28/why-are-some-languages-spoken-faster-than-others)](img/showcase/speech-speed.png){fig-align=\"center\" fig-alt=\"The raincloud chart showing the distributions of normalized speech rates (dark pink) and information rates (dark lime green) across language families.\"}\n\n--------------------------------------------------------------------------------\n\n![[\"Not My Cup of Coffee\"](https://www.behance.net/gallery/100638417/Not-My-Cup-of-Coffee)](img/showcase/coffee-ratings.png){fig-align=\"center\" fig-alt=\"The raincloud chart showing the distributions of normalized speech rates (dark pink) and information rates (dark lime green) across language families.\"}\n\n--------------------------------------------------------------------------------\n\n![[\"Food Carbon Footprint Index 2018\"](https://github.com/Z3tt/TidyTuesday/tree/main/plots/2020_08)](img/showcase/20200307_TT_2020_08_CarbonFoodprint_alt.png){fig-align=\"center\" fig-alt=\"Two circular hierarchical bar plots showing the carbon footprint 2018 for food consumption and CO2 per continent and country.\"}\n\n--------------------------------------------------------------------------------\n\n![[\"Popular Programming Languages in CRAN Packages\"](https://twitter.com/spren9er/status/1195826547724374018) by Torsten Sprenger](img/showcase/cran-packages-torsten-sprenger.png){fig-align=\"center\" fig-alt=\"A circular tree showing the programing languages used in CRAN packages, with nodes being grouped by languages and package names, sized by number of lines.\"}\n\n--------------------------------------------------------------------------------\n\n![[\"Appearance of X-Men Characters\"](https://www.behance.net/gallery/100640345/Appearance-of-Popular-X-Men-Characters)](img/showcase/xmen-comics.png){fig-align=\"center\" fig-size=\"45%\" fig-alt=\"Streamgraphs showing the appearance of the most common X-Men characters (Wovlerine, Magneto, Nightcrawler, Storm & Gambit) during the so-called Claremont Run. Chris Claremont is a famous American comic book writer who was in charge of the Uncanny X-Men comic book series from 1975–1991. During that time he developed complex literary themes and strong female characters into superhero comics, and turning the X-Men into one of Marvel's most popular series.\"}\n\n--------------------------------------------------------------------------------\n\n![[\"Artists in the US\"](https://twitter.com/leeolney3/status/1574656040599265280) by Lee Olney](img/showcase/artists-usa-lee-olney.png){fig-align=\"center\" fig-alt=\"A facet of barcodes showing location quotients from artists in the US by type and race.\"}\n\n--------------------------------------------------------------------------------\n\n
\n\n![My Contribution to the [SWDchallenge \"Small Multiples\"](https://www.storytellingwithdata.com/blog/2020/1/6/swdchallenge-small-multiples)](img/showcase/SWD_2020_01_SmallMultiples_grey.png){fig-align=\"center\" fig-alt=\"A facet of shots and goals of the Bundesliga football clubs in the season 2019/20.\"}\n\n--------------------------------------------------------------------------------\n\n![[\"European Energy Generation\"](github.com/jack-davison/tidytuesday) by Jack Davison](img/showcase/jack_davison.png){fig-align=\"center\" fig-alt=\"A gridded map of Europe showing horizontal stacked bars of energy production per country over time (each bar represents share among one year from 2016 to 2018).\"}\n\n--------------------------------------------------------------------------------\n\n![[Moon Charts as a Tile Grid Map](https://github.com/z3tt/grid-btw-wahlkreise-constituencies) showing the 2nd Vote Results from the German Election 2021](img/showcase/btw21_tile_grid_moon_second_de.png){fig-align=\"center\" fig-alt=\"A grid map using moon charts for all 297 electoral districts which show the share of the wnning party in second votesc during the German election in 2021.\"}\n\n--------------------------------------------------------------------------------\n\n![Our Winning Contribution to the [BES MoveMap Contest](https://besmovesig.wordpress.com/2021/02/25/mapping-movements-the-art-and-the-science-we-have-the-winners/)](img/showcase/20210131_BES_CheetahMap_rcarto.png){fig-align=\"center\" fig-alt=\"A spatial map of cheetah movement and their hotspot behaviour in Namibia.\"}\n\n--------------------------------------------------------------------------------\n\n![[Bivariate Choropleth x Hillshade Map](timogrossenbacher.ch/2019/04/bivariate-maps-with-ggplot2-and-sf) by Timo Gossenbacher](img/showcase/swiss_map.png){fig-align=\"center\" fig-alt=\"A spatial map of income and inequality shown with a bivariate color palette; alpine regions have a hillshading effect.\"}\n\n--------------------------------------------------------------------------------\n\n![Pixel Art by [Georgios Karamanis](https://karaman.is/)](img/showcase/bob-ross-pixel-art-georgios.png){fig-align=\"center\" fig-alt=\"A set of small multiples using pixelated encodings of certain elements in Bob Ross' paintings.\"}\n\n--------------------------------------------------------------------------------\n\n![Generative Art by [Thomas Lin Pedersen](https://www.data-imaginist.com/art)](img/showcase/genart.png){fig-align=\"center\" fig-alt=\"Two artworks by Thomas Pedersen, completely generated in R with ggplot2 (and pure magic).\"}\n\n\n# A Walk-Through Example\n\n\n## The Data Set\n\nBike sharing counts in London, UK, powered by [TfL Open Data](https://tfl.gov.uk/modes/cycling/santander-cycles)\n\n::: incremental\n- covers the years 2015 and 2016\n- incl. weather data acquired from [freemeteo.com](https://freemeteo.com)\n- prepared by Hristo Mavrodiev for [Kaggle](https://www.kaggle.com/hmavrodiev/london-bike-sharing-dataset)\n- further modification by myself\n:::\n\n\n## The Data Set\n\n\n::: {.cell}\n\n```{.r .cell-code}\nlibrary(readr)\nlibrary(ggplot2)\n\nbikes <-\n read_csv(\n here::here(\"data\", \"london-bikes.csv\"),\n col_types = \"Dcfffilllddddc\"\n )\n```\n:::\n\n\n\n## The Data Set\n\n\n::: {.cell hash='01-fundamentals_cache/revealjs/view-data_08b7b3be3eee0339e21d78d3715ee833'}\n\n```{.r .cell-code}\nbikes\n```\n\n::: {.cell-output .cell-output-stdout}\n```{.hscroll}\n# A tibble: 1,454 × 14\n date day_night year month season count is_workday is_weekend is_holiday temp temp_feel humidity wind_speed weather_type \n \n 1 2015-01-04 day 2015 1 3 6830 FALSE TRUE FALSE 2.17 -0.75 95.2 10.4 broken clouds \n 2 2015-01-04 night 2015 1 3 2404 FALSE TRUE FALSE 2.79 2.04 93.4 4.58 clear \n 3 2015-01-05 day 2015 1 3 14763 TRUE FALSE FALSE 8.96 7.71 81.1 8.67 broken clouds \n 4 2015-01-05 night 2015 1 3 5609 TRUE FALSE FALSE 7.12 5.71 79.5 9.04 cloudy \n 5 2015-01-06 day 2015 1 3 14501 TRUE FALSE FALSE 9 6.46 80.2 19.2 broken clouds \n 6 2015-01-06 night 2015 1 3 6112 TRUE FALSE FALSE 6.71 4.21 77.6 12.8 clear \n 7 2015-01-07 day 2015 1 3 16358 TRUE FALSE FALSE 8.17 5.08 75.2 21.2 scattered clouds\n 8 2015-01-07 night 2015 1 3 4706 TRUE FALSE FALSE 6.68 3.86 81.3 18.1 clear \n 9 2015-01-08 day 2015 1 3 9971 TRUE FALSE FALSE 9.46 7.12 79.4 18.8 scattered clouds\n10 2015-01-08 night 2015 1 3 5630 TRUE FALSE FALSE 10.0 8.46 79.2 22.2 clear \n# ℹ 1,444 more rows\n```\n:::\n:::\n\n\n\n\n## The Data Set\n\n\n::: {.cell hash='01-fundamentals_cache/revealjs/data-table_78b1267b2d8c1d92c639963f8ed64a4f'}\n::: {.cell-output-display}\n`````{=html}\n\n \n \n Variable | \n Description | \n Class | \n
\n \n\n \n date | \n Date encoded as `YYYY-MM-DD` | \n date | \n
\n \n day_night | \n `day` (6:00am–5:59pm) or `night` (6:00pm–5:59am) | \n character | \n
\n \n year | \n `2015` or `2016` | \n factor | \n
\n \n month | \n `1` (January) to `12` (December) | \n factor | \n
\n \n season | \n `0` (spring), `1` (summer), `2` (autumn), or `3` (winter) | \n factor | \n
\n \n count | \n Sum of reported bikes rented | \n integer | \n
\n \n is_workday | \n `TRUE` being Monday to Friday and no bank holiday | \n logical | \n
\n \n is_weekend | \n `TRUE` being Saturday or Sunday | \n logical | \n
\n \n is_holiday | \n `TRUE` being a bank holiday in the UK | \n logical | \n
\n \n temp | \n Average air temperature (°C) | \n double | \n
\n \n temp_feel | \n Average feels like temperature (°C) | \n double | \n
\n \n humidity | \n Average air humidity (%) | \n double | \n
\n \n wind_speed | \n Average wind speed (km/h) | \n double | \n
\n \n weather_type | \n Most common weather type | \n character | \n
\n\n
\n\n`````\n:::\n:::\n\n\n\n--------------------------------------------------------------------------------\n\n\n::: {.cell}\n::: {.cell-output-display}\n![](01-fundamentals_files/figure-revealjs/walkthrough-full-1.png){width=2020}\n:::\n:::\n\n\n\n## A Default ggplot\n\n\n::: {.cell hash='01-fundamentals_cache/revealjs/walkthrough-0_54e69338bfad3e48c3cfc463ef22e77b'}\n\n```{.r .cell-code}\n# scatter plot of plot bikes$count versus bikes$temp_feel\nggplot(data = bikes) + # initial call + data\n aes(x = temp_feel, y = count) + # aesthetics\n geom_point() # geometric layer\n```\n:::\n\n\n\n## A Default ggplot\n\n\n::: {.cell hash='01-fundamentals_cache/revealjs/walkthrough-1_0e54cdfa411c3d3b234fefff974ba242'}\n\n```{.r .cell-code}\n# scatter plot of plot bikes$count versus bikes$temp_feel\nggplot(bikes, aes(x = temp_feel, y = count)) +\n geom_point()\n```\n:::\n\n\n--------------------------------------------------------------------------------\n\n\n::: {.cell hash='01-fundamentals_cache/revealjs/walkthrough-1_ef3f65b32793ec6d371133f6f7038b29'}\n::: {.cell-output-display}\n![](01-fundamentals_files/figure-revealjs/walkthrough-1-1.png){width=2020}\n:::\n:::\n\n\n\n## Combine Layers\n\n\n::: {.cell hash='01-fundamentals_cache/revealjs/walkthrough-2_f184aaeaa11b8515b6b82b001609e579'}\n\n```{.r .cell-code code-line-numbers=\"3,4\"}\nggplot(bikes, aes(x = temp_feel, y = count)) +\n geom_point() + \n # add a GAM smoothing\n stat_smooth() # also: geom_smooth()\n```\n:::\n\n\n--------------------------------------------------------------------------------\n\n\n::: {.cell hash='01-fundamentals_cache/revealjs/walkthrough-2_91b3b1905cf1268438b7f56b0d731a6f'}\n::: {.cell-output-display}\n![](01-fundamentals_files/figure-revealjs/walkthrough-2-1.png){width=2020}\n:::\n:::\n\n\n\n## Mapping Aesthetics\n\n\n::: {.cell hash='01-fundamentals_cache/revealjs/walkthrough-3_293593d0c1a51009ba5eb8a59f7728ea'}\n\n```{.r .cell-code code-line-numbers=\"1\"}\nggplot(bikes, aes(x = temp_feel, y = count, color = day_night)) + \n geom_point() + \n stat_smooth()\n```\n:::\n\n\n--------------------------------------------------------------------------------\n\n\n::: {.cell hash='01-fundamentals_cache/revealjs/walkthrough-3_88f47cdcb755f82a106c3104e6f61c8a'}\n::: {.cell-output-display}\n![](01-fundamentals_files/figure-revealjs/walkthrough-3-1.png){width=2020}\n:::\n:::\n\n\n\n## Mapping Aesthetics\n\n\n::: {.cell hash='01-fundamentals_cache/revealjs/walkthrough-4_bc36b6670c28f6d74336be8eea1dc2f0'}\n\n```{.r .cell-code code-line-numbers=\"2,3|4,5\"}\nggplot(bikes, aes(x = temp_feel, y = count)) + \n # color mapping only applied to points\n geom_point(aes(color = day_night)) + \n # invisible grouping to create two trend lines\n stat_smooth(aes(group = day_night))\n```\n:::\n\n\n--------------------------------------------------------------------------------\n\n\n::: {.cell hash='01-fundamentals_cache/revealjs/walkthrough-4_78c4aadf451b272dde9b6f8b9f90d1dd'}\n::: {.cell-output-display}\n![](01-fundamentals_files/figure-revealjs/walkthrough-4-1.png){width=2020}\n:::\n:::\n\n\n\n## Setting Properties\n\n\n::: {.cell hash='01-fundamentals_cache/revealjs/walkthrough-5_34ed96698fc797de07f96bd938e6c867'}\n\n```{.r .cell-code code-line-numbers=\"2,4,5|7,9,10\"}\nggplot(bikes, aes(x = temp_feel, y = count)) + \n geom_point(\n aes(color = day_night), \n # setting larger points with 50% opacity\n alpha = .5, size = 1.5\n ) + \n stat_smooth(\n aes(group = day_night), \n # use linear fitting + draw black smoothing lines\n method = \"lm\", color = \"black\"\n )\n```\n:::\n\n\n--------------------------------------------------------------------------------\n\n\n::: {.cell hash='01-fundamentals_cache/revealjs/walkthrough-5_8fb70a2442398fd47b6e93b823111860'}\n::: {.cell-output-display}\n![](01-fundamentals_files/figure-revealjs/walkthrough-5-1.png){width=2020}\n:::\n:::\n\n\n\n## Split into Facets\n\n\n::: {.cell hash='01-fundamentals_cache/revealjs/walkthrough-6_e529afc4ea35d449fb64c893507c694f'}\n\n```{.r .cell-code code-line-numbers=\"9,10|10|6,7,8\"}\nggplot(bikes, aes(x = temp_feel, y = count)) + \n geom_point(\n aes(color = day_night), \n alpha = .5, size = 1.5\n ) + \n stat_smooth(\n method = \"lm\", color = \"black\"\n ) +\n # small multiples\n facet_wrap(facets = vars(day_night)) # also: ~ day_night\n```\n:::\n\n\n--------------------------------------------------------------------------------\n\n\n::: {.cell hash='01-fundamentals_cache/revealjs/walkthrough-6_27afd61089e430c690a7804868b50766'}\n::: {.cell-output-display}\n![](01-fundamentals_files/figure-revealjs/walkthrough-6-1.png){width=2020}\n:::\n:::\n\n\n\n## Split into Facets\n\n\n::: {.cell hash='01-fundamentals_cache/revealjs/walkthrough-7_95545d6c6b8eb53f8fb668d6bf3087d3'}\n\n```{.r .cell-code code-line-numbers=\"9,10,11,12|3\"}\nggplot(bikes, aes(x = temp_feel, y = count)) + \n geom_point(\n aes(color = season), \n alpha = .5, size = 1.5\n ) + \n stat_smooth(\n method = \"lm\", color = \"black\"\n ) +\n # small multiples\n facet_grid(\n rows = vars(day_night), cols = vars(year) # also: day_night ~ year\n )\n```\n:::\n\n\n--------------------------------------------------------------------------------\n\n\n::: {.cell hash='01-fundamentals_cache/revealjs/walkthrough-7_69b48889365752e9cd23674008e0f2a6'}\n::: {.cell-output-display}\n![](01-fundamentals_files/figure-revealjs/walkthrough-7-1.png){width=2020}\n:::\n:::\n\n\n\n## Free Facets Axes\n\n\n::: {.cell hash='01-fundamentals_cache/revealjs/walkthrough-8_fd9eff017a9fba3dbc48953c23b59afb'}\n\n```{.r .cell-code code-line-numbers=\"11,12|13,14\"}\nggplot(bikes, aes(x = temp_feel, y = count)) + \n geom_point(\n aes(color = season), \n alpha = .5, size = 1.5\n ) + \n stat_smooth(\n method = \"lm\", color = \"black\"\n ) +\n facet_grid(\n day_night ~ year, \n # free y axis range\n scales = \"free_y\", \n # scale heights proportionally\n space = \"free_y\"\n )\n```\n:::\n\n\n--------------------------------------------------------------------------------\n\n\n::: {.cell hash='01-fundamentals_cache/revealjs/walkthrough-8_4245878b8777d05fe555922e5a7de0f1'}\n::: {.cell-output-display}\n![](01-fundamentals_files/figure-revealjs/walkthrough-8-1.png){width=2020}\n:::\n:::\n\n\n\n## Store ggplot\n\n\n::: {.cell}\n\n```{.r .cell-code code-line-numbers=\"1\"}\ng1 <- \n ggplot(bikes, aes(x = temp_feel, y = count)) + \n geom_point(\n aes(color = season), \n alpha = .5, size = 1.5\n ) + \n stat_smooth(\n method = \"lm\", color = \"black\"\n ) +\n facet_grid(\n day_night ~ year, \n scales = \"free_y\", \n space = \"free_y\"\n )\n```\n:::\n\n\n\n## Change the Axis Scaling\n\n\n::: {.cell hash='01-fundamentals_cache/revealjs/walkthrough-9a_71ca58800723ac3067ba987f2a91ea75'}\n\n```{.r .cell-code code-line-numbers=\"1|2,3,8|4,5|6,7\"}\ng1 +\n # x axis\n scale_x_continuous(\n # add °C symbol\n labels = function(x) paste0(x, \"°C\"), \n # use 5°C spacing\n breaks = -1:6*5 # also: seq(-5, 30, by = 5)\n )\n```\n:::\n\n\n--------------------------------------------------------------------------------\n\n\n::: {.cell hash='01-fundamentals_cache/revealjs/walkthrough-9a_94c213b3e3298aee7aa24c2a76b7b869'}\n::: {.cell-output-display}\n![](01-fundamentals_files/figure-revealjs/walkthrough-9a-1.png){width=2020}\n:::\n:::\n\n\n\n## Change the Axis Scaling\n\n\n::: {.cell}\n\n```{.r .cell-code code-line-numbers=\"9,10,15|11,12|13,14|1\"}\ng2 <- g1 +\n # x axis\n scale_x_continuous(\n # add °C symbol\n labels = function(x) paste0(x, \"°C\"), \n # use 5°C spacing\n breaks = -1:6*5 # also: seq(-5, 30, by = 5)\n ) +\n # y axis\n scale_y_continuous(\n # add a thousand separator\n labels = scales::label_comma(), \n # use consistent spacing across rows\n breaks = 0:5*10000\n )\n```\n:::\n\n\n--------------------------------------------------------------------------------\n\n\n::: {.cell hash='01-fundamentals_cache/revealjs/walkthrough-9b_a1f16b4bb9b70474a341331ddfd6cf88'}\n::: {.cell-output-display}\n![](01-fundamentals_files/figure-revealjs/walkthrough-9b-1.png){width=2020}\n:::\n:::\n\n\n\n## Use a Custom Color Palette\n\n\n::: {.cell hash='01-fundamentals_cache/revealjs/walkthrough-10a_a2b62e2d5909c2c1666aa1d893b05151'}\n\n```{.r .cell-code code-line-numbers=\"2,3,4,5\"}\ng2 +\n # use a custom color palette for season colors\n scale_color_manual(\n values = c(\"#6681FE\", \"#1EC98D\", \"#F7B01B\", \"#A26E7C\")\n )\n```\n:::\n\n\n\n## Use a Custom Color Palette\n\n\n::: {.cell}\n\n```{.r .cell-code code-line-numbers=\"1,2,3,4,5,6,7|10,11,12\"}\n# use a named vector for explicit matching\ncolors <- c(\n `0` = \"#1EC98D\",\n `1` = \"#F7B01B\",\n `2` = \"#A26E7C\",\n `3` = \"#6681FE\"\n)\n\ng2 +\n scale_color_manual(\n values = colors\n )\n```\n:::\n\n\n--------------------------------------------------------------------------------\n\n\n::: {.cell hash='01-fundamentals_cache/revealjs/walkthrough-10_ce693f946c70482edbf1e765ddb060e1'}\n::: {.cell-output-display}\n![](01-fundamentals_files/figure-revealjs/walkthrough-10-1.png){width=2020}\n:::\n:::\n\n\n\n## Adjust Labels and Titles\n\n\n::: {.cell hash='01-fundamentals_cache/revealjs/walkthrough-11_2d7e0b13bceb12c6758e86b13d745705'}\n\n```{.r .cell-code code-line-numbers=\"11,12\"}\n# use a named vector for explicit matching\ncolors <- c(\n `0` = \"#1EC98D\",\n `1` = \"#F7B01B\",\n `2` = \"#A26E7C\",\n `3` = \"#6681FE\"\n)\n\ng2 +\n scale_color_manual(\n values = colors,\n # overwrite legend keys\n labels = c(\"Winter\", \"Spring\", \"Summer\", \"Autumn\")\n )\n```\n:::\n\n\n--------------------------------------------------------------------------------\n\n\n::: {.cell hash='01-fundamentals_cache/revealjs/walkthrough-11_9545eeba757f1a80bcb64ae741df7cec'}\n::: {.cell-output-display}\n![](01-fundamentals_files/figure-revealjs/walkthrough-11-1.png){width=2020}\n:::\n:::\n\n\n\n## Adjust Labels and Titles\n\n\n::: {.cell}\n\n```{.r .cell-code code-line-numbers=\"6,12|7,8|9,10,11\"}\ng3 <- g2 +\n scale_color_manual(\n values = colors,\n labels = c(\"Winter\", \"Spring\", \"Summer\", \"Autumn\")\n ) +\n labs(\n # overwrite axis and legend titles\n x = \"Average feels-like temperature\", y = NULL, color = NULL,\n # add plot title and caption\n title = \"Trends of Reported Bike Rents versus Feels-Like Temperature in London\",\n caption = \"Data: TfL (Transport for London), Jan 2015–Dec 2016\"\n )\n```\n:::\n\n\n--------------------------------------------------------------------------------\n\n\n::: {.cell hash='01-fundamentals_cache/revealjs/walkthrough-12_fa8618f2346558525d91984fc7c63410'}\n::: {.cell-output-display}\n![](01-fundamentals_files/figure-revealjs/walkthrough-12-1.png){width=2020}\n:::\n:::\n\n\n\n## Apply a Complete Theme\n\n\n::: {.cell hash='01-fundamentals_cache/revealjs/walkthrough-13_8ce6babacc4b7bf8b34abbd3a8f15fc1'}\n\n```{.r .cell-code code-line-numbers=\"2,3,4,5\"}\ng3 +\n # add theme with a custom font + larger element sizes\n theme_light(\n base_size = 15, base_family = \"Spline Sans\"\n )\n```\n:::\n\n\n--------------------------------------------------------------------------------\n\n\n::: {.cell hash='01-fundamentals_cache/revealjs/walkthrough-13_7b4505b1ca4b548fdd479f0a368e2306'}\n::: {.cell-output-display}\n![](01-fundamentals_files/figure-revealjs/walkthrough-13-1.png){width=2020}\n:::\n:::\n\n\n\n## Apply a Complete Theme\n\n\n::: {.cell}\n\n```{.r .cell-code code-line-numbers=\"3,4,20|5,6,7|8,9,10,11,12,13,14|15,16|17,18|19\"}\ng4 <- g3 +\n theme_light(base_size = 15, base_family = \"Spline Sans\") +\n # theme adjustments\n theme(\n plot.title.position = \"plot\", # left-align title \n plot.caption.position = \"plot\", # right-align caption\n legend.position = \"top\", # place legend above plot\n plot.title = element_text(face = \"bold\", size = rel(1.4)), # larger, bold title\n axis.text = element_text(family = \"Spline Sans Mono\"), # monospaced font for axes\n axis.title.x = element_text( # left-aligned, grey x axis label\n hjust = 0, color = \"grey20\", margin = margin(t = 12)\n ),\n legend.text = element_text(size = rel(1)), # larger legend labels\n strip.text = element_text(face = \"bold\", size = rel(1.15)), # larger, bold facet labels\n panel.grid.major.x = element_blank(), # no vertical major lines\n panel.grid.minor = element_blank(), # no minor grid lines\n panel.spacing.x = unit(20, \"pt\"), # increase white space between panels\n panel.spacing.y = unit(10, \"pt\"), # increase white space between panels\n plot.margin = margin(rep(15, 4)) # adjust white space around plot\n )\n```\n:::\n\n\n--------------------------------------------------------------------------------\n\n\n::: {.cell hash='01-fundamentals_cache/revealjs/walkthrough-14_579d1a1dfaf0480650568783386a63ce'}\n::: {.cell-output-display}\n![](01-fundamentals_files/figure-revealjs/walkthrough-14-1.png){width=2020}\n:::\n:::\n\n\n\n## Adjust Legend\n\n\n::: {.cell hash='01-fundamentals_cache/revealjs/walkthrough-15_d3d277f36ff972c767f850750799d004'}\n\n```{.r .cell-code code-line-numbers=\"2,3,4,5|4\"}\ng4 +\n # adjust symbol size in legend\n guides(\n color = guide_legend(override.aes = list(size = 4))\n )\n```\n:::\n\n\n\n## Adjust Legend\n\n\n::: {.cell hash='01-fundamentals_cache/revealjs/walkthrough-15b_6458e18188c6b9f6ebd8138a1213bb5f'}\n\n```{.r .cell-code code-line-numbers=\"2,5,6,7|5,6\"}\ng4 +\n scale_color_manual(\n values = colors,\n labels = c(\"Winter\", \"Spring\", \"Summer\", \"Autumn\"),\n # adjust symbol size in legend size\n guide = guide_legend(override.aes = list(size = 4))\n )\n```\n:::\n\n\n--------------------------------------------------------------------------------\n\n\n::: {.cell hash='01-fundamentals_cache/revealjs/walkthrough-15_c1f1277ad82b6cd039e09702caad009f'}\n::: {.cell-output-display}\n![](01-fundamentals_files/figure-revealjs/walkthrough-15-1.png){width=2020}\n:::\n:::\n\n\n\n--------------------------------------------------------------------------------\n\n## Full Code\n\n\n::: {.cell hash='01-fundamentals_cache/revealjs/walkthrough-full_8c95ed35a394e76e96f956adb5272781'}\n\n```{.r .cell-code}\n# create named color vector\ncolors <- c(\n `0` = \"#1EC98D\",\n `1` = \"#F7B01B\",\n `2` = \"#A26E7C\",\n `3` = \"#6681FE\"\n)\n\n# scatter plot of plot bikes$count versus bikes$temp_feel\nggplot(bikes, aes(x = temp_feel, y = count)) + \n # add points\n geom_point(\n # color mapping only applied to points\n aes(color = season), \n # setting larger points with 50% opacity\n alpha = .5, size = 1.5\n ) + \n # add a smoothing\n stat_smooth( # also: geom_smooth()\n # use linear fitting + draw black smoothing lines\n method = \"lm\", color = \"black\"\n ) +\n # small multiples\n facet_grid(\n day_night ~ year, # also: vars(day_night), vars(year)\n # free y axis range\n scales = \"free_y\", \n # scale heights proportionally \n space = \"free_y\"\n ) +\n # x axis\n scale_x_continuous(\n # add °C symbol\n labels = function(x) paste0(x, \"°C\"), \n # use 5°C spacing\n breaks = -1:6*5 # also: seq(-5, 30, by = 5)\n ) +\n # y axis\n scale_y_continuous(\n # add a thousand separator\n labels = scales::label_comma(), \n # use consistent spacing across rows\n breaks = 0:5*10000\n ) +\n # colors\n scale_color_manual(\n # use a custom color palette\n values = colors,\n # overwrite legend keys\n labels = c(\"Winter\", \"Spring\", \"Summer\", \"Autumn\"),\n # adjust symbol size in legend size\n guide = guide_legend(override.aes = list(size = 4))\n ) +\n labs(\n # overwrite axis and legend titles\n x = \"Average feels-like temperature\", y = NULL, color = NULL,\n # add plot title and caption\n title = \"Trends of Reported Bike Rents versus Feels-Like Temperature in London\",\n caption = \"Data: TfL (Transport for London), Jan 2015–Dec 2016\"\n ) +\n # add theme with a custom font + larger element sizes\n theme_light(\n base_size = 15, base_family = \"Spline Sans\"\n ) +\n # theme adjustments\n theme(\n plot.title.position = \"plot\", # left-align title \n plot.caption.position = \"plot\", # right-align caption\n legend.position = \"top\", # place legend above plot\n plot.title = element_text(face = \"bold\", size = rel(1.4)), # larger, bold title\n axis.text = element_text(family = \"Spline Sans Mono\"), # monospaced font for axes\n axis.title.x = element_text( # left-aligned, grey x axis label\n hjust = 0, color = \"grey20\", margin = margin(t = 12)\n ),\n legend.text = element_text(size = rel(1)), # larger legend labels\n strip.text = element_text(face = \"bold\", size = rel(1.15)), # larger, bold facet labels\n panel.grid.major.x = element_blank(), # no vertical major lines\n panel.grid.minor = element_blank(), # no minor grid lines\n panel.spacing.x = unit(20, \"pt\"), # increase white space between panels\n panel.spacing.y = unit(10, \"pt\"), # increase white space between panels\n plot.margin = margin(rep(15, 4)) # adjust white space around plot\n )\n```\n:::\n\n\n\n# Saving Plots\n\n\n## Save the Graphic\n\n
\n\n\n::: {.cell hash='01-fundamentals_cache/revealjs/ggplot-save_e5f05ce158402d7e685982556d179209'}\n\n```{.r .cell-code}\nggsave(filename = \"my_plot.png\", plot = g)\n```\n:::\n\n\n::: fragment\n\n::: {.cell hash='01-fundamentals_cache/revealjs/ggplot-save-implicit_9766c1583f2fbb00908b516d985f6453'}\n\n```{.r .cell-code}\nggsave(\"my_plot.png\")\n```\n:::\n\n:::\n\n
\n\n::: fragment\n\n::: {.cell hash='01-fundamentals_cache/revealjs/ggplot-save-aspect_c4c7d92b369109a8c63e4d3acb8b3a4a'}\n\n```{.r .cell-code}\nggsave(\"my_plot.png\", width = 6, height = 5, dpi = 600)\n```\n:::\n\n:::\n\n\n## Plot Resolution\n\n\n\n\n\n::: {layout-ncol=\"2\"}\n![](plots/resolution-dpi-100.png)\n\n![](plots/resolution-dpi-600.png)\n:::\n\n\n## Plot Resolution\n\n::: {layout-ncol=\"2\"}\n![](img/resolution-dpi-100-zoom.png)\n\n![](img/resolution-dpi-600-zoom.png)\n:::\n\n\n## Save the Graphic\n\n
\n\n\n::: {.cell hash='01-fundamentals_cache/revealjs/ggplot-save_439dcf333a92406ebd8f3987d6bf9287'}\n\n```{.r .cell-code}\nggsave(filename = \"my_plot.png\", plot = g)\n```\n:::\n\n::: {.cell hash='01-fundamentals_cache/revealjs/ggplot-save-implicit_c5fdbcc9003675c2f0008fca98c36874'}\n\n```{.r .cell-code}\nggsave(\"my_plot.png\")\n```\n:::\n\n\n
\n\n\n::: {.cell hash='01-fundamentals_cache/revealjs/ggplot-save-aspect_c7758af26f1a01644a26e5432e2f2d0c'}\n\n```{.r .cell-code}\nggsave(\"my_plot.png\", width = 6, height = 5, dpi = 600)\n```\n:::\n\n\n::: fragment\n\n::: {.cell hash='01-fundamentals_cache/revealjs/ggplot-save-unit_1cb025e0ae788e688d21927fee627091'}\n\n```{.r .cell-code}\nggsave(\"my_plot.png\", width = 6*2.54, height = 5*2.54, unit = \"cm\", dpi = 600)\n```\n:::\n\n:::\n\n
\n\n::: fragment\n\n::: {.cell hash='01-fundamentals_cache/revealjs/ggplot-save-raster-agg_7717fd36fbcc79947a3b710ba2e06004'}\n\n```{.r .cell-code}\nggsave(\"my_plot.png\", device = agg_png)\n```\n:::\n\n:::\n\n::: fragment\n\n::: {.cell hash='01-fundamentals_cache/revealjs/ggplot-save-cairo_b9eb653fefdb960c5af7f9f35c0916ab'}\n\n```{.r .cell-code}\nggsave(\"my_plot.pdf\", device = cairo_pdf)\n```\n:::\n\n:::\n\n\n--------------------------------------------------------------------------------\n\n
\n\n![Modified from canva.com](img/vector-raster-canva.png){fig-alt=\"A comparison of vector and raster graphics.\" fig-width=\"150%\"}\n\n\n\n## The {ragg} Package\n\nprovides drop-in replacements for the default raster graphic devices\n\n::: incremental\n\n* faster\n* direct access to all system fonts\n* advanced text rendering\n * including support for right-to-left text, emojis, and font fallback\n* high quality anti-aliasing\n* high quality rotated text\n* supports 16-bit output\n* system independent rendering\n\n:::\n\n\n## The {ragg} Package\n\n
\n\n![Source: [tidyverse.org/blog/2021/02/modern-text-features](https://www.tidyverse.org/blog/2021/02/modern-text-features/)](img/ragg-left-and-right.png){fig-align=\"center\" fig-alt=\"A comparison of different graphic devices in R comparing the rendering of right-to-left text (and mixing left-to-right and right-to-left text).\"}\n\n\n## The {ragg} Package\n\n
\n\n![Source: [tidyverse.org/blog/2021/02/modern-text-features](https://www.tidyverse.org/blog/2021/02/modern-text-features/)](img/ragg-ligatures.png){fig-align=\"center\" fig-alt=\"A comparison of different graphic devices in R comparing the rendering of font ligatures.\"}\n\n\n## The {ragg} Package\n\n
\n\n![Source: [tidyverse.org/blog/2021/02/modern-text-features](https://www.tidyverse.org/blog/2021/02/modern-text-features/)](img/ragg-emojis.png){fig-align=\"center\" fig-alt=\"A comparison of different graphic devices in R comparing the rendering of emojis.\"}\n\n\n## The {ragg} Package\n\n
\n\n![Source: [tidyverse.org/blog/2021/02/modern-text-features](https://www.tidyverse.org/blog/2021/02/modern-text-features/)](img/ragg-fallback.png){fig-align=\"center\" fig-alt=\"A comparison of different graphic devices in R comparing the rendering missing glyphs, partly making use of fallback fonts.\"}\n\n\n## The {ragg} Package\n\n::: incremental\n* use {ragg} when saving ggplots by passing agg device function: `ggsave(device = agg_png))` ([used by default if installed](https://github.com/tidyverse/ggplot2/pull/4388))\n* use {ragg} in the *Rstudio Plots* pane be setting the backend to AGG: ![](img/ragg-rstudio.png){fig-alt=\"How to set the AGG device as the default in RStudio via Global Options > > General > Graphics > Backend.\"}\n* use {ragg} when knitting Rmarkdown files by setting `dev=\"ragg_png\"` in the code chunk options.\n\n:::\n\n\n## Save the Graphic\n\n
\n\n\n::: {.cell hash='01-fundamentals_cache/revealjs/ggplot-save_439dcf333a92406ebd8f3987d6bf9287'}\n\n```{.r .cell-code}\nggsave(filename = \"my_plot.png\", plot = g)\n```\n:::\n\n::: {.cell hash='01-fundamentals_cache/revealjs/ggplot-save-implicit_c5fdbcc9003675c2f0008fca98c36874'}\n\n```{.r .cell-code}\nggsave(\"my_plot.png\")\n```\n:::\n\n\n
\n\n\n::: {.cell hash='01-fundamentals_cache/revealjs/ggplot-save-aspect_c7758af26f1a01644a26e5432e2f2d0c'}\n\n```{.r .cell-code}\nggsave(\"my_plot.png\", width = 6, height = 5, dpi = 600)\n```\n:::\n\n::: {.cell hash='01-fundamentals_cache/revealjs/ggplot-save-unit_7b4c6b278330b6c7959419e4fe66e57e'}\n\n```{.r .cell-code}\nggsave(\"my_plot.png\", width = 6*2.54, height = 5*2.54, unit = \"cm\", dpi = 600)\n```\n:::\n\n
\n\n\n::: {.cell hash='01-fundamentals_cache/revealjs/ggplot-save-raster-agg_ee35fa72950cb04d7a1ba33120bd2923'}\n\n```{.r .cell-code}\nggsave(\"my_plot.png\", device = agg_png)\n```\n:::\n\n::: {.cell hash='01-fundamentals_cache/revealjs/ggplot-save-cairo_a437ddfca531433a3be58b3e32c0b6cf'}\n\n```{.r .cell-code}\nggsave(\"my_plot.pdf\", device = cairo_pdf)\n```\n:::\n\n\n::: fragment\n\n::: {.cell hash='01-fundamentals_cache/revealjs/ggplot-save-svg_04c01878d73ecdfe86e9bb01ec2cecfb'}\n\n```{.r .cell-code}\nggsave(\"my_plot.svg\")\n```\n:::\n\n:::\n\n\n--------------------------------------------------------------------------------\n\n![](img/figma-svg.png){fig-align=\"center\"}\n\n\n## How to Work with Aspect Ratios\n\n::: incremental\n- don't rely on the Rstudio viewer pane!\n- once you have a *\"it's getting close\"* prototype, settle on a plot size
\n- **Approach 1:** save the file and inspect it—go back to your IDE—repeat\n - tedious and time-consuming...
\n- **Approach 2:** use a qmd or rmd with inline output and chunk settings\n - set `fig-width` / `fig.width` and `fig-height` / `fig.height`
per chunk or globally
\n:::\n\n\n## Setting Plot Sizes in Quarto and Rmarkdown\n\n![](img/plot-size-chunk-yaml.png){fig-alt=\"A screenshot of an exemplary Qmd file with two chunks with different settings of fig-width and fig-height as YAML-styled options using the hashpipe. Unfortunately, these are not respected when the chunk output is printed inline.\" fig-width=\"60%\"}\n\n\n## Setting Plot Sizes in Quarto and Rmarkdown\n\n![](img/plot-size-chunk-inline.png){fig-alt=\"A screenshot of an exemplary Qmd file with two chunks with different settings of fig.width and fig.height set as inline chunk options.\" fig-width=\"60%\"}\n\n\n## How to Work with Aspect Ratios\n\n- don't rely on the Rstudio viewer pane!\n- once you have a *\"it's getting close\"* prototype, settle on a plot size
\n- **Approach 1:** save the file and inspect it—go back to your IDE—repeat\n - tedious and time-consuming...
\n- **Approach 2:** use a qmd or rmd with inline output and chunk settings\n - set `fig-width` / `fig.width` and `fig-height` / `fig.height`
per chunk or globally
\n- **Approach 3:** use our [{camcorder} package](https://github.com/thebioengineer/camcorder)\n - saves output from all `ggplot()` calls and displays it in the viewer pane\n\n\n## Setting Plot Sizes via {camcorder}\n\n
\n\n![](img/plot-size-camcorder-a.png){fig-alt=\"A screenshot of an exemplary R script with a plot automatically saved and isplayed in correct aspect ratio thanks to the camcorder package.\" fig-width=\"120%\"}\n\n\n## Setting Plot Sizes via {camcorder}\n\n
\n\n![](img/plot-size-camcorder-b.png){fig-alt=\"A screenshot of an exemplary R script with a plot automatically saved and isplayed in correct aspect ratio thanks to the camcorder package.\" fig-width=\"120%\"}\n\n\n## Setting Plot Sizes via {camcorder}\n\n\n::: {.cell hash='01-fundamentals_cache/revealjs/camcorder-record_00dad4ac42afbc08553cc5c510c3d7ea'}\n\n```{.r .cell-code code-line-numbers=\"1,2,3,4,5,6,7|9,10,11,12,13,15\"}\ncamcorder::gg_record(\n dir = here::here(\"temp\"), # path for plot files\n device = \"png\", # device to use\n width = 10, # figure width\n height = 5, # figure height\n dpi = 600 # plot resolution\n)\n\ng <- ggplot(bikes, aes(x = temp, y = count, color = day_night)) +\n geom_point(alpha = .3, size = 2) +\n scale_color_manual(values = c(day = \"#FFA200\", night = \"#757BC7\")) +\n theme_minimal(base_size = 14, base_family = \"Asap SemiCondensed\") +\n theme(panel.grid.minor = element_blank())\n\ng\n```\n:::\n\n\n\n## Setting Plot Sizes via {camcorder}\n\n\n::: {.cell hash='01-fundamentals_cache/revealjs/camcorder-resize_8c9dabd1c4d2661597733e6d716f0424'}\n\n```{.r .cell-code code-line-numbers=\"17,19\"}\ncamcorder::gg_record(\n dir = here::here(\"temp\"), # path for plot files\n device = \"png\", # device to use\n width = 10, # figure width\n height = 5, # figure height\n dpi = 600 # plot resolution\n)\n\ng <- ggplot(bikes, aes(x = temp, y = count, color = day_night)) +\n geom_point(alpha = .3, size = 2) +\n scale_color_manual(values = c(day = \"#FFA200\", night = \"#757BC7\")) +\n theme_minimal(base_size = 14, base_family = \"Asap SemiCondensed\") +\n theme(panel.grid.minor = element_blank())\n\ng\n\ncamcorder::gg_resize_film(width = 20) # update figure width\n\ng\n```\n:::\n\n\n\n## Like a Pro: Set Theme Globally\n\n\n::: {.cell}\n\n```{.r .cell-code}\ntheme_set(theme_minimal(base_size = 14, base_family = \"Asap SemiCondensed\"))\ntheme_update(panel.grid.minor = element_blank())\n```\n:::\n\n\n\n# Programming
with ggplot2\n\n\n## Conditional Components\n\n\n::: {.cell hash='01-fundamentals_cache/revealjs/conditional-components_caef70472f777a01248d33a3f284f406'}\n\n```{.r .cell-code code-line-numbers=\"1|3,4,5|4\"}\nsmooth <- TRUE\n\nggplot(bikes, aes(x = temp, y = humidity)) +\n { if(smooth) geom_smooth(color = \"red\") } +\n geom_point(alpha = .5)\n```\n:::\n\n\n\n## Conditional Components\n\n\n::: {.cell layout-align=\"center\" hash='01-fundamentals_cache/revealjs/conditional-components-1_af3590b704ded767678e130b9bed0532'}\n\n```{.r .cell-code}\nsmooth <- TRUE\n\nggplot(bikes, aes(x = temp, y = humidity)) +\n { if(smooth) geom_smooth(color = \"red\") } +\n geom_point(alpha = .5)\n```\n\n::: {.cell-output-display}\n![](01-fundamentals_files/figure-revealjs/conditional-components-1-1.png){fig-align='center' width=1600}\n:::\n:::\n\n\n\n## Conditional Components\n\n\n::: {.cell layout-align=\"center\" hash='01-fundamentals_cache/revealjs/conditional-components-2_f29ca7457d58aeba72af8364052998e2'}\n\n```{.r .cell-code code-line-numbers=\"1\"}\nsmooth <- FALSE\n\nggplot(bikes, aes(x = temp, y = humidity)) +\n { if(smooth) geom_smooth(color = \"red\") } +\n geom_point(alpha = .5)\n```\n\n::: {.cell-output-display}\n![](01-fundamentals_files/figure-revealjs/conditional-components-2-1.png){fig-align='center' width=1600}\n:::\n:::\n\n\n\n## Wrapper Functions for Plots\n\n\n::: {.cell hash='01-fundamentals_cache/revealjs/conditional-components-function_bbcbb08aec8f13e9bfdf6dcd42f130a4'}\n\n```{.r .cell-code code-line-numbers=\"1,5|2,3,4\"}\ndraw_scatter <- function(smooth = TRUE) {\n ggplot(bikes, aes(x = temp, y = humidity)) +\n { if(smooth) geom_smooth(color = \"red\") } +\n geom_point(alpha = .5)\n}\n```\n:::\n\n\n\n## Wrapper Functions for Plots\n\n\n::: {.cell output-location='column' hash='01-fundamentals_cache/revealjs/conditional-components-function-plot-default_b88942c23d103843491ed566b4ee8391'}\n\n```{.r .cell-code}\ndraw_scatter()\n```\n\n::: {.cell-output-display}\n![](01-fundamentals_files/figure-revealjs/conditional-components-function-plot-default-1.png){width=1000}\n:::\n:::\n\n\n\n## Wrapper Functions for Plots\n\n\n::: {.cell output-location='column' hash='01-fundamentals_cache/revealjs/conditional-components-function-plot-false_9e465abdd77a1628e20f9b9194f5c781'}\n\n```{.r .cell-code}\ndraw_scatter(smooth = FALSE)\n```\n\n::: {.cell-output-display}\n![](01-fundamentals_files/figure-revealjs/conditional-components-function-plot-false-1.png){width=1000}\n:::\n:::\n\n\n\n## Components as Functions\n\n\n::: {.cell}\n\n```{.r .cell-code code-line-numbers=\"1,2,7|3,6|4,5\"}\ngeom_scatterfit <- function(pointsize = 1, pointalpha = 1, \n method = \"lm\", linecolor = \"red\", ...) {\n list(\n geom_point(size = pointsize, alpha = pointalpha, ...),\n geom_smooth(method = method, color = linecolor, ...)\n )\n}\n```\n:::\n\n\n\n## Components as Functions\n\n\n::: {.cell output-location='column' hash='01-fundamentals_cache/revealjs/function-components-defaults_b82bb4e1013de3757c454e7f445193ef'}\n\n```{.r .cell-code code-line-numbers=\"3\"}\nggplot(bikes,\n aes(x = humidity, y = count)) +\n geom_scatterfit()\n```\n\n::: {.cell-output-display}\n![](01-fundamentals_files/figure-revealjs/function-components-defaults-1.png){width=1000}\n:::\n:::\n\n\n\n## Components as Functions\n\n\n::: {.cell output-location='column' hash='01-fundamentals_cache/revealjs/function-components-args_166742f1bde5f609121fd38acd7a44d2'}\n\n```{.r .cell-code code-line-numbers=\"4,5\"}\nggplot(bikes,\n aes(x = humidity, y = count)) +\n geom_scatterfit(\n color = \"#28A87D\", \n linewidth = 3\n )\n```\n\n::: {.cell-output-display}\n![](01-fundamentals_files/figure-revealjs/function-components-args-1.png){width=1000}\n:::\n:::\n\n\n\n## Components as Functions\n\n\n::: {.cell output-location='column' hash='01-fundamentals_cache/revealjs/function-components-custom_0855f87dcad4c1979956d8c4ba0fb5cc'}\n\n```{.r .cell-code code-line-numbers=\"1,2|4,5,6,7\"}\nggplot(diamonds, \n aes(x = carat, y = price)) +\n geom_scatterfit(\n pointsize = .5, \n pointalpha = .1,\n method = \"gam\",\n linecolor = \"#EFAC00\"\n )\n```\n\n::: {.cell-output-display}\n![](01-fundamentals_files/figure-revealjs/function-components-custom-1.png){width=1000}\n:::\n:::\n\n\n\n## Components as Functions\n\n\n::: {.cell}\n\n```{.r .cell-code code-line-numbers=\"1,14|2,13|3,4,5,6,7|8,9,10,11,12\"}\nscales_log <- function(sides = \"xy\") {\n list(\n if(stringr::str_detect(sides, \"x\")) {\n scale_x_log10(\n breaks = c(10^(1:100)), labels = scales::label_log()\n )\n },\n if(stringr::str_detect(sides, \"y\")) {\n scale_y_log10(\n breaks = c(10^(1:100)), labels = scales::label_log()\n )\n }\n )\n}\n```\n:::\n\n\n\n## Components as Functions\n\n\n::: {.cell output-location='column' hash='01-fundamentals_cache/revealjs/function-components-scales-custom_5b6321eab679a1975d13c047c2a99c10'}\n\n```{.r .cell-code code-line-numbers=\"9\"}\nggplot(diamonds, \n aes(x = carat, y = price)) +\n geom_scatterfit(\n pointsize = .5, \n pointalpha = .1,\n method = \"gam\",\n linecolor = \"#EFAC00\"\n ) +\n scales_log(sides = \"y\")\n```\n\n::: {.cell-output-display}\n![](01-fundamentals_files/figure-revealjs/function-components-scales-custom-1.png){width=1000}\n:::\n:::\n\n\n\n## Iterative Graphics\n\n\n::: {.cell}\n\n```{.r .cell-code code-line-numbers=\"1,11|2,3,4|5,6,7,8,9|1,4,9\"}\ntrends_monthly <- function(grp = \"January\") {\n bikes |> \n dplyr::mutate(month = lubridate::month(date, label = TRUE, abbr = FALSE)) |> \n dplyr::filter(month %in% grp) |> \n ggplot(aes(x = temp, y = count, color = day_night)) +\n geom_point(alpha = .2, show.legend = FALSE) +\n geom_smooth(se = FALSE) +\n scale_color_manual(values = c(\"#FFA200\", \"#757bc7\")) +\n labs(title = grp, x = \"Temperature\", y = \"Bike shares\", color = NULL)\n}\n```\n:::\n\n\n\n## Iterative Graphics\n\n\n::: {.cell output-location='column'}\n\n```{.r .cell-code}\ntrends_monthly(\"July\")\n```\n\n::: {.cell-output-display}\n![](01-fundamentals_files/figure-revealjs/function-iterate-monthly-july-1.png){width=1000}\n:::\n:::\n\n\n\n## Iterative Graphics\n\n\n::: {.cell}\n\n```{.r .cell-code code-line-numbers=\"8,9,10\"}\ntrends_monthly <- function(grp = \"January\") {\n bikes |> \n dplyr::mutate(month = lubridate::month(date, label = TRUE, abbr = FALSE)) |> \n dplyr::filter(month %in% grp) |> \n ggplot(aes(x = temp, y = count, color = day_night)) +\n geom_point(alpha = .2, show.legend = FALSE) +\n geom_smooth(se = FALSE) +\n # keep axis ranges consistent\n scale_x_continuous(limits = range(bikes$temp)) +\n scale_y_continuous(limits = range(bikes$count)) +\n scale_color_manual(values = c(\"#FFA200\", \"#757bc7\")) +\n labs(title = grp, x = \"Temperature\", y = \"Bike shares\", color = NULL)\n}\n```\n:::\n\n\n\n## Iterative Graphics\n\n\n::: {.cell output-location='column'}\n\n```{.r .cell-code}\ntrends_monthly(\"July\")\n```\n\n::: {.cell-output-display}\n![](01-fundamentals_files/figure-revealjs/function-iterate-monthly-ranges-july-1.png){width=1000}\n:::\n:::\n\n\n\n## Iterative Graphics\n\n\n::: {.cell}\n\n```{.r .cell-code}\nplots <- purrr::map(month.name[1:12], trends_monthly) ## also: ~ trends_monthly(.x)\n```\n:::\n\n\n\n## Iterative Graphics\n\n\n::: {.cell layout-align=\"center\"}\n\n```{.r .cell-code code-line-numbers=\"2\"}\nplots <- purrr::map(month.name[1:12], trends_monthly) ## also: ~ trends_monthly(.x)\nplots[[9]]\n```\n\n::: {.cell-output-display}\n![](01-fundamentals_files/figure-revealjs/function-iterate-monthly-ranges-purrr-single-1.png){fig-align='center' width=1600}\n:::\n:::\n\n\n\n## Iterative Graphics\n\n\n::: {.cell layout-align=\"center\"}\n\n```{.r .cell-code code-line-numbers=\"2\"}\nplots <- purrr::map(month.name[1:12], trends_monthly) ## also: ~ trends_monthly(.x)\npatchwork::wrap_plots(plots)\n```\n\n::: {.cell-output-display}\n![](01-fundamentals_files/figure-revealjs/function-iterate-monthly-ranges-wrap-1.png){fig-align='center' width=3600}\n:::\n:::\n\n\n\n## Iterative Graphics\n\n\n::: {.cell}\n\n```{.r .cell-code code-line-numbers=\"1,11|2|3,4|5,6,7|8,9,10\"}\nplot_density <- function(data, var, grp = \"\") {\n ggplot(data, aes(x = !!sym(var))) +\n geom_density(aes(fill = !!sym(grp)), position = \"identity\",\n color = \"grey30\", alpha = .3) +\n coord_cartesian(expand = FALSE, clip = \"off\") +\n scale_y_continuous(labels = scales::label_number()) +\n scale_fill_brewer(palette = \"Dark2\", name = NULL) +\n theme(legend.position = \"top\")\n}\n```\n:::\n\n\n\n## Iterative Graphics\n\n\n::: {.cell output-location='column'}\n\n```{.r .cell-code}\nplot_density(\n bikes, \"count\"\n)\n```\n\n::: {.cell-output-display}\n![](01-fundamentals_files/figure-revealjs/function-density-plot-1.png){width=1000}\n:::\n:::\n\n\n\n## Iterative Graphics\n\n\n::: {.cell layout-align=\"center\"}\n\n```{.r .cell-code code-line-numbers=\"1,2,3,4|2|3|5\"}\nplots <- purrr::map(\n c(\"count\", \"temp\", \"humidity\", \"wind_speed\"), \n ~ plot_density(data = bikes, var = .x, grp = \"day_night\")\n)\npatchwork::wrap_plots(plots, nrow = 1)\n```\n\n::: {.cell-output-display}\n![](01-fundamentals_files/figure-revealjs/function-density-plot-grp-1.png){fig-align='center' width=2800}\n:::\n:::\n\n\n\n## Iterative Graphics\n\n\n::: {.cell layout-align=\"center\"}\n\n```{.r .cell-code code-line-numbers=\"2|3|5\"}\nplots <- purrr::map(\n names(dplyr::select(midwest, where(is.numeric))),\n ~plot_density(data = midwest, var = .x)\n)\npatchwork::wrap_plots(plots)\n```\n\n::: {.cell-output-display}\n![](01-fundamentals_files/figure-revealjs/function-density-plot-midwest-1.png){fig-align='center' width=4000}\n:::\n:::\n\n\n\n# Combine Plots\n\n\n## Combine Plots with {patchwork}\n\n\n::: {.cell}\n\n```{.r .cell-code code-line-numbers=\"1|3|5|7∂\"}\nlibrary(patchwork)\n\np1 <- plot_density(data = bikes, var = \"count\", grp = \"day_night\")\n\np2 <- plot_density(data = bikes, var = \"humidity\", grp = \"day_night\")\n\np3 <- ggplot(bikes, aes(x = humidity, y = count)) + geom_scatterfit(pointalpha = .3)\n```\n:::\n\n\n\n## Combine Plots with {patchwork}\n\n\n::: {.cell layout-align=\"center\"}\n\n```{.r .cell-code}\n(p1 + p2) / p3\n```\n\n::: {.cell-output-display}\n![](01-fundamentals_files/figure-revealjs/patchwork-example-1-1.png){fig-align='center' width=2400}\n:::\n:::\n\n\n\n## Combine Plots with {patchwork}\n\n\n::: {.cell layout-align=\"center\"}\n\n```{.r .cell-code}\n(p1 + p2) / p3 + plot_layout(heights = c(1, 2))\n```\n\n::: {.cell-output-display}\n![](01-fundamentals_files/figure-revealjs/patchwork-example-2-1.png){fig-align='center' width=2400}\n:::\n:::\n\n\n\n## Combine Plots with {patchwork}\n\n\n::: {.cell layout-align=\"center\"}\n\n```{.r .cell-code}\n(p1 + p2) / p3 + plot_layout(heights = c(1, 2), guides = \"collect\")\n```\n\n::: {.cell-output-display}\n![](01-fundamentals_files/figure-revealjs/patchwork-example-3-1.png){fig-align='center' width=2400}\n:::\n:::\n\n\n\n## Combine Plots with {patchwork}\n\n\n::: {.cell layout-align=\"center\"}\n\n```{.r .cell-code}\n(p1 + p2) / p3 + plot_layout(heights = c(1, 2), guides = \"collect\") +\n plot_annotation(theme = theme(legend.justification = \"top\"))\n```\n\n::: {.cell-output-display}\n![](01-fundamentals_files/figure-revealjs/patchwork-example-4-1.png){fig-align='center' width=2400}\n:::\n:::\n\n\n\n## Combine Plots with {patchwork}\n\n\n::: {.cell layout-align=\"center\"}\n\n```{.r .cell-code}\n(p1 + p2) / p3 + plot_layout(heights = c(1, 2), guides = \"collect\") +\n plot_annotation(tag_levels = \"A\", tag_suffix = \".\", theme = theme(legend.justification = \"top\"))\n```\n\n::: {.cell-output-display}\n![](01-fundamentals_files/figure-revealjs/patchwork-example-5-1.png){fig-align='center' width=2400}\n:::\n:::\n\n\n\n# Exciting Extension Packages\n\n\n## Layers\n\n+ [**`{geofacet}`**](https://hafen.github.io/geofacet/) — tile grid maps\n+ [**`{ggalluvial}`**](https://github.com/hrbrmstr/ggalt) — alluvial plots\n+ [**`{ggalt}`**](https://github.com/hrbrmstr/ggalt) — dumbbell, horizon, and lollipop charts, splines, ...\n+ [**`{ggbeeswarm}`**](https://github.com/hrbrmstr/ggalt) — beeswarm plots and variants\n+ [**`{ggbraid}`**](https://nsgrantham.github.io/ggbraid/) — ribbons for alternating groups\n+ [**`{ggbump}`**](https://github.com/davidsjoberg/ggbump) — parallel sets, pie charts, geometries, splines, voronoi, ...\n+ [**`{ggdensity}`**](https://jamesotto852.github.io/ggdensity/) — improved density plots\n+ [**`{ggdist}`**](https://github.com/davidsjoberg/ggbump) — uncertainty visualizations\n+ [**`{ggforce}`**](https://ggforce.data-imaginist.com/) — several interesting layers (and more)\n+ [**`{ggpattern}`**](https://github.com/coolbutuseless/ggpattern) — pattern fills for layers\n\n\n## Layers (continued)\n\n+ [**`{ggpointdensity}`**](https://github.com/LKremer/ggpointdensity) — density gradients for scatter plots\n+ [**`{ggraph}`**](https://github.com/thomasp85/ggraph) — networks, graphs & trees\n+ [**`{ggridges}`**](https://github.com/clauswilke/ggridges) — ridgeline plots\n+ [**`{ggsankey}`**](https://github.com/davidsjoberg/ggsankey) — sankey diagrams\n+ [**`{ggsignif}`**](https://const-ae.github.io/ggsignif/) — significance levels\n+ [**`{ggstar}`**](https://github.com/xiangpin/ggstar) — more point shapes\n+ [**`{ggstream}`**](https://github.com/davidsjoberg/ggstream) — stream graphs\n+ [**`{ggupset}`**](https://github.com/const-ae/ggupset) — upset graphs\n+ [**`{treemapify}`**](https://wilkox.org/treemapify/) — treemaps\n\n\n## Utilities\n\n+ [**`{cowplot}`**](https://cran.r-project.org/web/packages/cowplot/vignettes/introduction.html) — combine ggplots\n+ [**`{ggannotate}`**](https://github.com/MattCowgill/ggannotate) — point-n-click annotations\n+ [**`{ggblend}`**](https://mjskay.github.io/ggblend/) — blend, compose, adjust layers\n+ [**`{ggfittext}`**](https://wilkox.org/ggfittext/) — scale text according to space\n+ [**`{ggfx}`**](https://ggfx.data-imaginist.com/) — shaders and filters for layers\n+ [**`{ggh4x}`**](https://teunbrand.github.io/ggh4x/) — facets, positions, and more\n+ [**`{ggtext}`**](https://github.com/thomasp85/patchwork#patchwork) — text rendering for theme elements + text layers\n+ [**`{lemon}`**](https://github.com/stefanedwards/lemon) — axis lines (and a few layers)\n+ [**`{patchwork}`**](https://github.com/thomasp85/patchwork#patchwork) — combine ggplots\n+ [**`{scales}`**](https://scales.r-lib.org/) — control scales \n\n\n## Themes\n\n+ [**`{ggdark}`**](https://github.com/nsgrantham/ggdark)\n+ [**`{ggsci}`**](https://github.com/jrnold/ggthemes) (also color scales)\n+ [**`{ggtech}`**](https://github.com/ricardo-bion/ggtech) (also color scales)\n+ [**`{ggthemes}`**](https://github.com/jrnold/ggthemes) (also color scales)\n+ [**`{ggthemr}`**](https://github.com/Mikata-Project/ggthemr)\n+ [**`{hrbrthemes}`**](https://github.com/hrbrmstr/hrbrthemes) (also color scales)\n+ [**`{tvthemes}`**](https://ryo-n7.github.io/tvthemes/) (also color scales)\n\n\n## Color Palettes\n\n+ [**`{colorspace}`**](https://cran.r-project.org/web/packages/colorspace/vignettes/colorspace.html)\n+ [**`{jcolors}`**](https://jaredhuling.org/jcolors/)\n+ [**`{MetBrewer}`**](https://github.com/BlakeRMills/MetBrewer)\n+ [**`{nord}`**](https://cran.r-project.org/web/packages/nord/readme/README.html)\n+ [**`{rcartocolor}`**](https://jakubnowosad.com/rcartocolor/)\n+ [**`{RColorBrewer}`**](https://cran.r-project.org/web/packages/RColorBrewer/index.html)\n+ [**`{scico}`**](https://github.com/thomasp85/scico)\n+ [**`{unikn}`**](https://github.com/hneth/unikn)\n+ [**`{viridis}`**](https://cran.r-project.org/web/packages/viridis/vignettes/intro-to-viridis.html)\n+ [**`{wesanderson}`**](https://github.com/karthik/wesanderson)\n\n\n## Interactive Charts\n\n+ [**`{ggiraph}`**](https://davidgohel.github.io/ggiraph/)\n+ [**`{plotly}`**](https://plotly.com/r/)\n+ [**`{echarts4r}`**](https://echarts4r.john-coene.com/)*\n+ [**`{highcharter}`**](https://jkunst.com/highcharter/)*\n+ [**`{charter}`**](https://github.com/JohnCoene/charter)*\n+ [**`{streamgraph}`**](https://hrbrmstr.github.io/streamgraph/)*\n+ [**`{tmap}`**](https://cran.r-project.org/web/packages/tmap/vignettes/tmap-getstarted.html)*\n+ [**`{leaflet}`**](https://rstudio.github.io/leaflet/)*\n+ [**`{globe4r}`**](https://globe4r.john-coene.com/)*\n+ [**`{grapher}`**](https://grapher.network/)*\n\n* not using ggplot2
\n\n\n## Recap\n\n::: recap\n- a basic ggplot is build by specifying three components:
`data`, `aes`thetics and a `layer` (usually a `geom_*` or `stat_*`)\n- *aesthetic mappings* define how variables map to visual properties\n- the default appearance of all other components can be modified via `scale_*`, `coord_*`, `facet_*` and `theme_*` / `theme` \n- use the devices cairo (pdf) and agg (png, jpg, tiff) when saving plots\n- find a suitable plot size by setting figure chunk options in qmd/rmd files or with the help of the `{camcorder}` package\n- define conditional components, custom layers and functions to generate plots more efficiently and to iterate over multiple inputs\n- combine multiple plot outputs with `{patchwork}`\n:::\n\n\n# Exercises\n\n\n## Exercise 1\n\n::: question\n- **Discuss / investigate with your neighbor:**\n - What are the differences between `geom_line()` and `geom_path()`?\n - Why can you use `geom_smooth()` and `stat_smooth()` interchangeably?\n - What are the three ways to *remove a legend* from a ggplot?\n:::\n\n\n## Exercise 2\n\n::: question\n- **Explore the TfL bike share data visually:**\n - Create a *time series* of counts per day and night.\n - Draw *box and whisker plots* of average temperatures per month.\n - Visualize bike counts per weather type and period as *bar chart*. \n- **Combine the three plots with {patchwork}.**\n- **Export the final graphic in a format of your choice.**\n:::\n\n## {background-image=\"img/exercise-what-now.png\" background-position=\"center\" background-size=\"75%\"}\n",
+ "markdown": "---\ntitle: \"Engaging and Beautiful Data Visualizations with ggplot2\"\nsubtitle: \"Fundamentals & Workflows\"\nauthor: \"Cédric Scherer // posit::conf // September 2023\"\nformat:\n revealjs:\n theme: slides.scss\n logo: img/logo.png\n footer: '[Cédric Scherer](https://cedricscherer.com) // posit::conf(2023)'\n transition: fade\n progress: true\n multiplex: false\n preview-links: true\n scrollable: false\n hide-inactive-cursor: true\n highlight-style: printing\n chalkboard:\n theme: whiteboard\n boardmarker-width: 4\n buttons: true\n pause: true\neditor: source\nknitr:\n opts_chunk:\n dev: \"ragg_png\"\n retina: 3\n dpi: 200\nexecute:\n freeze: auto\n cache: true\n echo: true\n fig-width: 10.1\n fig-height: 6.3\n fig-align: center\n---\n\n\n\n\n\n# {ggplot2}\n\n\n##\n\n::: footer\n[{ggplot2} package description](https://ggplot2.tidyverse.org/)\n:::\n\n![](img/intro/ggplot2.png){fig-align=\"center\" fig-alt=\"The ggplot2 hex logo.\"}\n\n
\n\n{ggplot2}
is a system for declaratively creating graphics,
based on \"The Grammar of Graphics\" (Wilkinson 2005).\n\n::: fragment\n[You provide the data, tell {ggplot2}
how to]{style=\"font-size:24pt;\"} [map variables to aesthetics,]{.circle-highlight}
what graphical primitives to use, and it takes care of the details.\n:::\n\n## Advantages of {ggplot2}\n\n::: incremental\n- consistent underlying \"grammar of graphics\" (Wilkinson 2005)\\\n- very flexible, layered plot specification\\\n- theme system for polishing plot appearance\\\n- lots of additional functionality thanks to extensions\\\n- active and helpful community\n:::\n\n\n## The Components of a ggplot\n\n
\n\n \n Component | \n Function | \n Explanation | \n
\n \n Data | \n ggplot(data) | \n *The raw data that you want to visualize (initialising a plot).* | \n
\n \n Aesthetics | \n aes() | \n *The mapping between variables and visual properties.* | \n
\n Geometries | \n geom_*() | \n *The geometric shape of a layer representing the data.* | \n
\n
\n\n--------------------------------------------------------------------------------\n\n![ggplot2 examples featured on [ggplot2.tidyverse.org](https://ggplot2.tidyverse.org/)](img/basic-ggplots.png){fig-align=\"center\" fig-alt=\"A collection of the versatility of ggplot2 to create basic graphs. All of them use only data, aesthetics, and layers with the defaults of ggplot2.\"}\n\n\n## The Components of a ggplot\n\n\n
\n\n \n Component | \n Function | \n Explanation | \n
\n \n Data | \n ggplot(data) | \n *The raw data that you want to visualize (initializing a plot).* | \n
\n \n Aesthetics | \n aes() | \n *The mapping between variables and visual properties.* | \n
\n Geometries | \n geom_*() | \n *The geometric shape of a layer representing the data.* | \n
\n \n Statistics | \n stat_*() | \n *The statistical transformation of a layer applied to the data.* | \n
\n \n Scales | \n scale_*() | \n *The representation of mapped aesthetic attributes.* | \n
\n \n Coordinate System | \n coord_*() | \n *The transformation to map data coordinates into the plot plane.* | \n
\n \n Facets | \n facet_*() | \n *The arrangement of the data into a set of small multiples.* | \n
\n \n Visual Themes | \n theme() | theme_*() | \n *The overall visual defaults of non-data elements of the graphic.* | \n
\n
\n\n--------------------------------------------------------------------------------\n\n![Illustration by [Allison Horst](https://github.com/allisonhorst/stats-illustrations)](img/ah-ggplot2-exploratory.png){fig-align=\"center\" fig-alt=\"Allison Horsts monster illustration of explorative plotting with ggplot2.\"}\n\n--------------------------------------------------------------------------------\n\n![Illustration by [Allison Horst](https://github.com/allisonhorst/stats-illustrations)](img/ah-ggplot2-masterpiece.png){fig-align=\"center\" fig-alt=\"Allison Horsts monster illustration of building data masterpiece ith ggplot2 featuring a little Picasso monster :)\"}\n\n\n# The {ggplot2} Showcase\n\n--------------------------------------------------------------------------------\n\n
\n\n![Collection of Graphics from the [BBC R Cookbook](https://bbc.github.io/rcookbook/)](img/showcase/bbc-gallery.png){fig-align=\"center\" fig-alt=\"A multi-plot panel of various data visualizations created by the BBC teams.\"}\n\n--------------------------------------------------------------------------------\n\n
\n\n![Collection of Graphics from the [BBC R Cookbook](https://bbc.github.io/rcookbook/)](img/showcase/bbc-gallery-quote.png){fig-align=\"center\" fig-alt=\"A multi-plot panel of various data visualizations created by the BBC teams.\"}\n\n--------------------------------------------------------------------------------\n\n![[\"Bill Dimensions of Brush-Tailed Penguins\"](https://github.com/Z3tt/TidyTuesday/tree/main/plots/2020_31)](img/showcase/palmer-penguins.png){fig-align=\"center\" fig-size=\"80%\" fig-alt=\"Distribution of coffee bean ratings by the Coffee Quality Institute for countries with 25 or more reviews (up to 2018). Distributions are shown as dot plots and multiple interval stripes.\"}\n\n--------------------------------------------------------------------------------\n\n![[\"Netflix Content Explosion\"](https://twitter.com/tanya_shapiro/status/1610419176333627393) by Tanya Shapiro](img/showcase/netflix-originals-tanya-shapiro.jpeg){fig-align=\"center\" fig-size=\"50%\" fig-alt=\"rea graph of number of Netflix original series over time, annotated with images and labels.\"}\n\n--------------------------------------------------------------------------------\n\n![My reinterpreted [The Economist graphic](https://www.economist.com/graphic-detail/2019/09/28/why-are-some-languages-spoken-faster-than-others)](img/showcase/speech-speed.png){fig-align=\"center\" fig-alt=\"The raincloud chart showing the distributions of normalized speech rates (dark pink) and information rates (dark lime green) across language families.\"}\n\n--------------------------------------------------------------------------------\n\n![[\"Not My Cup of Coffee\"](https://www.behance.net/gallery/100638417/Not-My-Cup-of-Coffee)](img/showcase/coffee-ratings.png){fig-align=\"center\" fig-alt=\"The raincloud chart showing the distributions of normalized speech rates (dark pink) and information rates (dark lime green) across language families.\"}\n\n--------------------------------------------------------------------------------\n\n![[\"Food Carbon Footprint Index 2018\"](https://github.com/Z3tt/TidyTuesday/tree/main/plots/2020_08)](img/showcase/20200307_TT_2020_08_CarbonFoodprint_alt.png){fig-align=\"center\" fig-alt=\"Two circular hierarchical bar plots showing the carbon footprint 2018 for food consumption and CO2 per continent and country.\"}\n\n--------------------------------------------------------------------------------\n\n![[\"Popular Programming Languages in CRAN Packages\"](https://twitter.com/spren9er/status/1195826547724374018) by Torsten Sprenger](img/showcase/cran-packages-torsten-sprenger.png){fig-align=\"center\" fig-alt=\"A circular tree showing the programing languages used in CRAN packages, with nodes being grouped by languages and package names, sized by number of lines.\"}\n\n--------------------------------------------------------------------------------\n\n![[\"Appearance of X-Men Characters\"](https://www.behance.net/gallery/100640345/Appearance-of-Popular-X-Men-Characters)](img/showcase/xmen-comics.png){fig-align=\"center\" fig-size=\"45%\" fig-alt=\"Streamgraphs showing the appearance of the most common X-Men characters (Wovlerine, Magneto, Nightcrawler, Storm & Gambit) during the so-called Claremont Run. Chris Claremont is a famous American comic book writer who was in charge of the Uncanny X-Men comic book series from 1975–1991. During that time he developed complex literary themes and strong female characters into superhero comics, and turning the X-Men into one of Marvel's most popular series.\"}\n\n--------------------------------------------------------------------------------\n\n![[\"Artists in the US\"](https://twitter.com/leeolney3/status/1574656040599265280) by Lee Olney](img/showcase/artists-usa-lee-olney.png){fig-align=\"center\" fig-alt=\"A facet of barcodes showing location quotients from artists in the US by type and race.\"}\n\n--------------------------------------------------------------------------------\n\n
\n\n![My Contribution to the [SWDchallenge \"Small Multiples\"](https://www.storytellingwithdata.com/blog/2020/1/6/swdchallenge-small-multiples)](img/showcase/SWD_2020_01_SmallMultiples_grey.png){fig-align=\"center\" fig-alt=\"A facet of shots and goals of the Bundesliga football clubs in the season 2019/20.\"}\n\n--------------------------------------------------------------------------------\n\n![[\"European Energy Generation\"](github.com/jack-davison/tidytuesday) by Jack Davison](img/showcase/jack_davison.png){fig-align=\"center\" fig-alt=\"A gridded map of Europe showing horizontal stacked bars of energy production per country over time (each bar represents share among one year from 2016 to 2018).\"}\n\n--------------------------------------------------------------------------------\n\n![[Moon Charts as a Tile Grid Map](https://github.com/z3tt/grid-btw-wahlkreise-constituencies) showing the 2nd Vote Results from the German Election 2021](img/showcase/btw21_tile_grid_moon_second_de.png){fig-align=\"center\" fig-alt=\"A grid map using moon charts for all 297 electoral districts which show the share of the wnning party in second votesc during the German election in 2021.\"}\n\n--------------------------------------------------------------------------------\n\n![Our Winning Contribution to the [BES MoveMap Contest](https://besmovesig.wordpress.com/2021/02/25/mapping-movements-the-art-and-the-science-we-have-the-winners/)](img/showcase/20210131_BES_CheetahMap_rcarto.png){fig-align=\"center\" fig-alt=\"A spatial map of cheetah movement and their hotspot behaviour in Namibia.\"}\n\n--------------------------------------------------------------------------------\n\n![[Bivariate Choropleth x Hillshade Map](timogrossenbacher.ch/2019/04/bivariate-maps-with-ggplot2-and-sf) by Timo Gossenbacher](img/showcase/swiss_map.png){fig-align=\"center\" fig-alt=\"A spatial map of income and inequality shown with a bivariate color palette; alpine regions have a hillshading effect.\"}\n\n--------------------------------------------------------------------------------\n\n![Pixel Art by [Georgios Karamanis](https://karaman.is/)](img/showcase/bob-ross-pixel-art-georgios.png){fig-align=\"center\" fig-alt=\"A set of small multiples using pixelated encodings of certain elements in Bob Ross' paintings.\"}\n\n--------------------------------------------------------------------------------\n\n![Generative Art by [Thomas Lin Pedersen](https://www.data-imaginist.com/art)](img/showcase/genart.png){fig-align=\"center\" fig-alt=\"Two artworks by Thomas Pedersen, completely generated in R with ggplot2 (and pure magic).\"}\n\n\n# A Walk-Through Example\n\n\n## The Data Set\n\nBike sharing counts in London, UK, powered by [TfL Open Data](https://tfl.gov.uk/modes/cycling/santander-cycles)\n\n::: incremental\n- covers the years 2015 and 2016\n- incl. weather data acquired from [freemeteo.com](https://freemeteo.com)\n- prepared by Hristo Mavrodiev for [Kaggle](https://www.kaggle.com/hmavrodiev/london-bike-sharing-dataset)\n- further modification by myself\n:::\n\n\n## The Data Set\n\n\n::: {.cell}\n\n```{.r .cell-code}\nlibrary(readr)\nlibrary(ggplot2)\n\nbikes <-\n read_csv(\n here::here(\"data\", \"london-bikes.csv\"),\n col_types = \"Dcfffilllddddc\"\n )\n```\n:::\n\n\n\n## The Data Set\n\n\n::: {.cell hash='01-fundamentals_cache/revealjs/view-data_08b7b3be3eee0339e21d78d3715ee833'}\n\n```{.r .cell-code}\nbikes\n```\n\n::: {.cell-output .cell-output-stdout}\n```{.hscroll}\n# A tibble: 1,454 × 14\n date day_night year month season count is_workday is_weekend is_holiday temp temp_feel humidity wind_speed weather_type \n \n 1 2015-01-04 day 2015 1 3 6830 FALSE TRUE FALSE 2.17 -0.75 95.2 10.4 broken clouds \n 2 2015-01-04 night 2015 1 3 2404 FALSE TRUE FALSE 2.79 2.04 93.4 4.58 clear \n 3 2015-01-05 day 2015 1 3 14763 TRUE FALSE FALSE 8.96 7.71 81.1 8.67 broken clouds \n 4 2015-01-05 night 2015 1 3 5609 TRUE FALSE FALSE 7.12 5.71 79.5 9.04 cloudy \n 5 2015-01-06 day 2015 1 3 14501 TRUE FALSE FALSE 9 6.46 80.2 19.2 broken clouds \n 6 2015-01-06 night 2015 1 3 6112 TRUE FALSE FALSE 6.71 4.21 77.6 12.8 clear \n 7 2015-01-07 day 2015 1 3 16358 TRUE FALSE FALSE 8.17 5.08 75.2 21.2 scattered clouds\n 8 2015-01-07 night 2015 1 3 4706 TRUE FALSE FALSE 6.68 3.86 81.3 18.1 clear \n 9 2015-01-08 day 2015 1 3 9971 TRUE FALSE FALSE 9.46 7.12 79.4 18.8 scattered clouds\n10 2015-01-08 night 2015 1 3 5630 TRUE FALSE FALSE 10.0 8.46 79.2 22.2 clear \n# ℹ 1,444 more rows\n```\n:::\n:::\n\n\n\n\n## The Data Set\n\n\n::: {.cell hash='01-fundamentals_cache/revealjs/data-table_78b1267b2d8c1d92c639963f8ed64a4f'}\n::: {.cell-output-display}\n`````{=html}\n\n \n \n Variable | \n Description | \n Class | \n
\n \n\n \n date | \n Date encoded as `YYYY-MM-DD` | \n date | \n
\n \n day_night | \n `day` (6:00am–5:59pm) or `night` (6:00pm–5:59am) | \n character | \n
\n \n year | \n `2015` or `2016` | \n factor | \n
\n \n month | \n `1` (January) to `12` (December) | \n factor | \n
\n \n season | \n `0` (spring), `1` (summer), `2` (autumn), or `3` (winter) | \n factor | \n
\n \n count | \n Sum of reported bikes rented | \n integer | \n
\n \n is_workday | \n `TRUE` being Monday to Friday and no bank holiday | \n logical | \n
\n \n is_weekend | \n `TRUE` being Saturday or Sunday | \n logical | \n
\n \n is_holiday | \n `TRUE` being a bank holiday in the UK | \n logical | \n
\n \n temp | \n Average air temperature (°C) | \n double | \n
\n \n temp_feel | \n Average feels like temperature (°C) | \n double | \n
\n \n humidity | \n Average air humidity (%) | \n double | \n
\n \n wind_speed | \n Average wind speed (km/h) | \n double | \n
\n \n weather_type | \n Most common weather type | \n character | \n
\n\n
\n\n`````\n:::\n:::\n\n\n\n--------------------------------------------------------------------------------\n\n\n::: {.cell}\n::: {.cell-output-display}\n![](01-fundamentals_files/figure-revealjs/walkthrough-full-1.png){width=2020}\n:::\n:::\n\n\n\n## A Default ggplot\n\n\n::: {.cell hash='01-fundamentals_cache/revealjs/walkthrough-0_54e69338bfad3e48c3cfc463ef22e77b'}\n\n```{.r .cell-code}\n# scatter plot of plot bikes$count versus bikes$temp_feel\nggplot(data = bikes) + # initial call + data\n aes(x = temp_feel, y = count) + # aesthetics\n geom_point() # geometric layer\n```\n:::\n\n\n\n## A Default ggplot\n\n\n::: {.cell hash='01-fundamentals_cache/revealjs/walkthrough-1_0e54cdfa411c3d3b234fefff974ba242'}\n\n```{.r .cell-code}\n# scatter plot of plot bikes$count versus bikes$temp_feel\nggplot(bikes, aes(x = temp_feel, y = count)) +\n geom_point()\n```\n:::\n\n\n--------------------------------------------------------------------------------\n\n\n::: {.cell hash='01-fundamentals_cache/revealjs/walkthrough-1_ef3f65b32793ec6d371133f6f7038b29'}\n::: {.cell-output-display}\n![](01-fundamentals_files/figure-revealjs/walkthrough-1-1.png){width=2020}\n:::\n:::\n\n\n\n## Combine Layers\n\n\n::: {.cell hash='01-fundamentals_cache/revealjs/walkthrough-2_f184aaeaa11b8515b6b82b001609e579'}\n\n```{.r .cell-code code-line-numbers=\"3,4\"}\nggplot(bikes, aes(x = temp_feel, y = count)) +\n geom_point() + \n # add a GAM smoothing\n stat_smooth() # also: geom_smooth()\n```\n:::\n\n\n--------------------------------------------------------------------------------\n\n\n::: {.cell hash='01-fundamentals_cache/revealjs/walkthrough-2_91b3b1905cf1268438b7f56b0d731a6f'}\n::: {.cell-output-display}\n![](01-fundamentals_files/figure-revealjs/walkthrough-2-1.png){width=2020}\n:::\n:::\n\n\n\n## Mapping Aesthetics\n\n\n::: {.cell hash='01-fundamentals_cache/revealjs/walkthrough-3_293593d0c1a51009ba5eb8a59f7728ea'}\n\n```{.r .cell-code code-line-numbers=\"1\"}\nggplot(bikes, aes(x = temp_feel, y = count, color = day_night)) + \n geom_point() + \n stat_smooth()\n```\n:::\n\n\n--------------------------------------------------------------------------------\n\n\n::: {.cell hash='01-fundamentals_cache/revealjs/walkthrough-3_88f47cdcb755f82a106c3104e6f61c8a'}\n::: {.cell-output-display}\n![](01-fundamentals_files/figure-revealjs/walkthrough-3-1.png){width=2020}\n:::\n:::\n\n\n\n## Mapping Aesthetics\n\n\n::: {.cell hash='01-fundamentals_cache/revealjs/walkthrough-4_bc36b6670c28f6d74336be8eea1dc2f0'}\n\n```{.r .cell-code code-line-numbers=\"2,3|4,5\"}\nggplot(bikes, aes(x = temp_feel, y = count)) + \n # color mapping only applied to points\n geom_point(aes(color = day_night)) + \n # invisible grouping to create two trend lines\n stat_smooth(aes(group = day_night))\n```\n:::\n\n\n--------------------------------------------------------------------------------\n\n\n::: {.cell hash='01-fundamentals_cache/revealjs/walkthrough-4_78c4aadf451b272dde9b6f8b9f90d1dd'}\n::: {.cell-output-display}\n![](01-fundamentals_files/figure-revealjs/walkthrough-4-1.png){width=2020}\n:::\n:::\n\n\n\n## Setting Properties\n\n\n::: {.cell hash='01-fundamentals_cache/revealjs/walkthrough-5_34ed96698fc797de07f96bd938e6c867'}\n\n```{.r .cell-code code-line-numbers=\"2,4,5|7,9,10\"}\nggplot(bikes, aes(x = temp_feel, y = count)) + \n geom_point(\n aes(color = day_night), \n # setting larger points with 50% opacity\n alpha = .5, size = 1.5\n ) + \n stat_smooth(\n aes(group = day_night), \n # use linear fitting + draw black smoothing lines\n method = \"lm\", color = \"black\"\n )\n```\n:::\n\n\n--------------------------------------------------------------------------------\n\n\n::: {.cell hash='01-fundamentals_cache/revealjs/walkthrough-5_8fb70a2442398fd47b6e93b823111860'}\n::: {.cell-output-display}\n![](01-fundamentals_files/figure-revealjs/walkthrough-5-1.png){width=2020}\n:::\n:::\n\n\n\n## Split into Facets\n\n\n::: {.cell hash='01-fundamentals_cache/revealjs/walkthrough-6_e529afc4ea35d449fb64c893507c694f'}\n\n```{.r .cell-code code-line-numbers=\"9,10|10|6,7,8\"}\nggplot(bikes, aes(x = temp_feel, y = count)) + \n geom_point(\n aes(color = day_night), \n alpha = .5, size = 1.5\n ) + \n stat_smooth(\n method = \"lm\", color = \"black\"\n ) +\n # small multiples\n facet_wrap(facets = vars(day_night)) # also: ~ day_night\n```\n:::\n\n\n--------------------------------------------------------------------------------\n\n\n::: {.cell hash='01-fundamentals_cache/revealjs/walkthrough-6_27afd61089e430c690a7804868b50766'}\n::: {.cell-output-display}\n![](01-fundamentals_files/figure-revealjs/walkthrough-6-1.png){width=2020}\n:::\n:::\n\n\n\n## Split into Facets\n\n\n::: {.cell hash='01-fundamentals_cache/revealjs/walkthrough-7_95545d6c6b8eb53f8fb668d6bf3087d3'}\n\n```{.r .cell-code code-line-numbers=\"9,10,11,12|3\"}\nggplot(bikes, aes(x = temp_feel, y = count)) + \n geom_point(\n aes(color = season), \n alpha = .5, size = 1.5\n ) + \n stat_smooth(\n method = \"lm\", color = \"black\"\n ) +\n # small multiples\n facet_grid(\n rows = vars(day_night), cols = vars(year) # also: day_night ~ year\n )\n```\n:::\n\n\n--------------------------------------------------------------------------------\n\n\n::: {.cell hash='01-fundamentals_cache/revealjs/walkthrough-7_69b48889365752e9cd23674008e0f2a6'}\n::: {.cell-output-display}\n![](01-fundamentals_files/figure-revealjs/walkthrough-7-1.png){width=2020}\n:::\n:::\n\n\n\n## Free Facets Axes\n\n\n::: {.cell hash='01-fundamentals_cache/revealjs/walkthrough-8_fd9eff017a9fba3dbc48953c23b59afb'}\n\n```{.r .cell-code code-line-numbers=\"11,12|13,14\"}\nggplot(bikes, aes(x = temp_feel, y = count)) + \n geom_point(\n aes(color = season), \n alpha = .5, size = 1.5\n ) + \n stat_smooth(\n method = \"lm\", color = \"black\"\n ) +\n facet_grid(\n day_night ~ year, \n # free y axis range\n scales = \"free_y\", \n # scale heights proportionally\n space = \"free_y\"\n )\n```\n:::\n\n\n--------------------------------------------------------------------------------\n\n\n::: {.cell hash='01-fundamentals_cache/revealjs/walkthrough-8_4245878b8777d05fe555922e5a7de0f1'}\n::: {.cell-output-display}\n![](01-fundamentals_files/figure-revealjs/walkthrough-8-1.png){width=2020}\n:::\n:::\n\n\n\n## Store ggplot\n\n\n::: {.cell}\n\n```{.r .cell-code code-line-numbers=\"1\"}\ng1 <- \n ggplot(bikes, aes(x = temp_feel, y = count)) + \n geom_point(\n aes(color = season), \n alpha = .5, size = 1.5\n ) + \n stat_smooth(\n method = \"lm\", color = \"black\"\n ) +\n facet_grid(\n day_night ~ year, \n scales = \"free_y\", \n space = \"free_y\"\n )\n```\n:::\n\n\n\n## Change the Axis Scaling\n\n\n::: {.cell hash='01-fundamentals_cache/revealjs/walkthrough-9a_71ca58800723ac3067ba987f2a91ea75'}\n\n```{.r .cell-code code-line-numbers=\"1|2,3,8|4,5|6,7\"}\ng1 +\n # x axis\n scale_x_continuous(\n # add °C symbol\n labels = function(x) paste0(x, \"°C\"), \n # use 5°C spacing\n breaks = -1:6*5 # also: seq(-5, 30, by = 5)\n )\n```\n:::\n\n\n--------------------------------------------------------------------------------\n\n\n::: {.cell hash='01-fundamentals_cache/revealjs/walkthrough-9a_94c213b3e3298aee7aa24c2a76b7b869'}\n::: {.cell-output-display}\n![](01-fundamentals_files/figure-revealjs/walkthrough-9a-1.png){width=2020}\n:::\n:::\n\n\n\n## Change the Axis Scaling\n\n\n::: {.cell}\n\n```{.r .cell-code code-line-numbers=\"9,10,15|11,12|13,14|1\"}\ng2 <- g1 +\n # x axis\n scale_x_continuous(\n # add °C symbol\n labels = function(x) paste0(x, \"°C\"), \n # use 5°C spacing\n breaks = -1:6*5 # also: seq(-5, 30, by = 5)\n ) +\n # y axis\n scale_y_continuous(\n # add a thousand separator\n labels = scales::label_comma(), \n # use consistent spacing across rows\n breaks = 0:5*10000\n )\n```\n:::\n\n\n--------------------------------------------------------------------------------\n\n\n::: {.cell hash='01-fundamentals_cache/revealjs/walkthrough-9b_a1f16b4bb9b70474a341331ddfd6cf88'}\n::: {.cell-output-display}\n![](01-fundamentals_files/figure-revealjs/walkthrough-9b-1.png){width=2020}\n:::\n:::\n\n\n\n## Use a Custom Color Palette\n\n\n::: {.cell hash='01-fundamentals_cache/revealjs/walkthrough-10a_a2b62e2d5909c2c1666aa1d893b05151'}\n\n```{.r .cell-code code-line-numbers=\"2,3,4,5\"}\ng2 +\n # use a custom color palette for season colors\n scale_color_manual(\n values = c(\"#6681FE\", \"#1EC98D\", \"#F7B01B\", \"#A26E7C\")\n )\n```\n:::\n\n\n\n## Use a Custom Color Palette\n\n\n::: {.cell}\n\n```{.r .cell-code code-line-numbers=\"1,2,3,4,5,6,7|10,11,12\"}\n# use a named vector for explicit matching\ncolors <- c(\n `0` = \"#1EC98D\",\n `1` = \"#F7B01B\",\n `2` = \"#A26E7C\",\n `3` = \"#6681FE\"\n)\n\ng2 +\n scale_color_manual(\n values = colors\n )\n```\n:::\n\n\n--------------------------------------------------------------------------------\n\n\n::: {.cell hash='01-fundamentals_cache/revealjs/walkthrough-10_ce693f946c70482edbf1e765ddb060e1'}\n::: {.cell-output-display}\n![](01-fundamentals_files/figure-revealjs/walkthrough-10-1.png){width=2020}\n:::\n:::\n\n\n\n## Adjust Labels and Titles\n\n\n::: {.cell hash='01-fundamentals_cache/revealjs/walkthrough-11_2d7e0b13bceb12c6758e86b13d745705'}\n\n```{.r .cell-code code-line-numbers=\"11,12\"}\n# use a named vector for explicit matching\ncolors <- c(\n `0` = \"#1EC98D\",\n `1` = \"#F7B01B\",\n `2` = \"#A26E7C\",\n `3` = \"#6681FE\"\n)\n\ng2 +\n scale_color_manual(\n values = colors,\n # overwrite legend keys\n labels = c(\"Winter\", \"Spring\", \"Summer\", \"Autumn\")\n )\n```\n:::\n\n\n--------------------------------------------------------------------------------\n\n\n::: {.cell hash='01-fundamentals_cache/revealjs/walkthrough-11_9545eeba757f1a80bcb64ae741df7cec'}\n::: {.cell-output-display}\n![](01-fundamentals_files/figure-revealjs/walkthrough-11-1.png){width=2020}\n:::\n:::\n\n\n\n## Adjust Labels and Titles\n\n\n::: {.cell}\n\n```{.r .cell-code code-line-numbers=\"6,12|7,8|9,10,11\"}\ng3 <- g2 +\n scale_color_manual(\n values = colors,\n labels = c(\"Winter\", \"Spring\", \"Summer\", \"Autumn\")\n ) +\n labs(\n # overwrite axis and legend titles\n x = \"Average feels-like temperature\", y = NULL, color = NULL,\n # add plot title and caption\n title = \"Trends of Reported Bike Rents versus Feels-Like Temperature in London\",\n caption = \"Data: TfL (Transport for London), Jan 2015–Dec 2016\"\n )\n```\n:::\n\n\n--------------------------------------------------------------------------------\n\n\n::: {.cell hash='01-fundamentals_cache/revealjs/walkthrough-12_fa8618f2346558525d91984fc7c63410'}\n::: {.cell-output-display}\n![](01-fundamentals_files/figure-revealjs/walkthrough-12-1.png){width=2020}\n:::\n:::\n\n\n\n## Apply a Complete Theme\n\n\n::: {.cell hash='01-fundamentals_cache/revealjs/walkthrough-13_8ce6babacc4b7bf8b34abbd3a8f15fc1'}\n\n```{.r .cell-code code-line-numbers=\"2,3,4,5\"}\ng3 +\n # add theme with a custom font + larger element sizes\n theme_light(\n base_size = 15, base_family = \"Spline Sans\"\n )\n```\n:::\n\n\n--------------------------------------------------------------------------------\n\n\n::: {.cell hash='01-fundamentals_cache/revealjs/walkthrough-13_7b4505b1ca4b548fdd479f0a368e2306'}\n::: {.cell-output-display}\n![](01-fundamentals_files/figure-revealjs/walkthrough-13-1.png){width=2020}\n:::\n:::\n\n\n\n## Apply a Complete Theme\n\n\n::: {.cell}\n\n```{.r .cell-code code-line-numbers=\"3,4,20|5,6,7|8,9,10,11,12,13,14|15,16|17,18|19\"}\ng4 <- g3 +\n theme_light(base_size = 15, base_family = \"Spline Sans\") +\n # theme adjustments\n theme(\n plot.title.position = \"plot\", # left-align title \n plot.caption.position = \"plot\", # right-align caption\n legend.position = \"top\", # place legend above plot\n plot.title = element_text(face = \"bold\", size = rel(1.4)), # larger, bold title\n axis.text = element_text(family = \"Spline Sans Mono\"), # monospaced font for axes\n axis.title.x = element_text( # left-aligned, grey x axis label\n hjust = 0, color = \"grey20\", margin = margin(t = 12)\n ),\n legend.text = element_text(size = rel(1)), # larger legend labels\n strip.text = element_text(face = \"bold\", size = rel(1.15)), # larger, bold facet labels\n panel.grid.major.x = element_blank(), # no vertical major lines\n panel.grid.minor = element_blank(), # no minor grid lines\n panel.spacing.x = unit(20, \"pt\"), # increase white space between panels\n panel.spacing.y = unit(10, \"pt\"), # increase white space between panels\n plot.margin = margin(rep(15, 4)) # adjust white space around plot\n )\n```\n:::\n\n\n--------------------------------------------------------------------------------\n\n\n::: {.cell hash='01-fundamentals_cache/revealjs/walkthrough-14_579d1a1dfaf0480650568783386a63ce'}\n::: {.cell-output-display}\n![](01-fundamentals_files/figure-revealjs/walkthrough-14-1.png){width=2020}\n:::\n:::\n\n\n\n## Adjust Legend\n\n\n::: {.cell hash='01-fundamentals_cache/revealjs/walkthrough-15_d3d277f36ff972c767f850750799d004'}\n\n```{.r .cell-code code-line-numbers=\"2,3,4,5|4\"}\ng4 +\n # adjust symbol size in legend\n guides(\n color = guide_legend(override.aes = list(size = 4))\n )\n```\n:::\n\n\n\n## Adjust Legend\n\n\n::: {.cell hash='01-fundamentals_cache/revealjs/walkthrough-15b_6458e18188c6b9f6ebd8138a1213bb5f'}\n\n```{.r .cell-code code-line-numbers=\"2,5,6,7|5,6\"}\ng4 +\n scale_color_manual(\n values = colors,\n labels = c(\"Winter\", \"Spring\", \"Summer\", \"Autumn\"),\n # adjust symbol size in legend size\n guide = guide_legend(override.aes = list(size = 4))\n )\n```\n:::\n\n\n--------------------------------------------------------------------------------\n\n\n::: {.cell hash='01-fundamentals_cache/revealjs/walkthrough-15_c1f1277ad82b6cd039e09702caad009f'}\n::: {.cell-output-display}\n![](01-fundamentals_files/figure-revealjs/walkthrough-15-1.png){width=2020}\n:::\n:::\n\n\n\n--------------------------------------------------------------------------------\n\n## Full Code\n\n\n::: {.cell hash='01-fundamentals_cache/revealjs/walkthrough-full_8c95ed35a394e76e96f956adb5272781'}\n\n```{.r .cell-code}\n# create named color vector\ncolors <- c(\n `0` = \"#1EC98D\",\n `1` = \"#F7B01B\",\n `2` = \"#A26E7C\",\n `3` = \"#6681FE\"\n)\n\n# scatter plot of plot bikes$count versus bikes$temp_feel\nggplot(bikes, aes(x = temp_feel, y = count)) + \n # add points\n geom_point(\n # color mapping only applied to points\n aes(color = season), \n # setting larger points with 50% opacity\n alpha = .5, size = 1.5\n ) + \n # add a smoothing\n stat_smooth( # also: geom_smooth()\n # use linear fitting + draw black smoothing lines\n method = \"lm\", color = \"black\"\n ) +\n # small multiples\n facet_grid(\n day_night ~ year, # also: vars(day_night), vars(year)\n # free y axis range\n scales = \"free_y\", \n # scale heights proportionally \n space = \"free_y\"\n ) +\n # x axis\n scale_x_continuous(\n # add °C symbol\n labels = function(x) paste0(x, \"°C\"), \n # use 5°C spacing\n breaks = -1:6*5 # also: seq(-5, 30, by = 5)\n ) +\n # y axis\n scale_y_continuous(\n # add a thousand separator\n labels = scales::label_comma(), \n # use consistent spacing across rows\n breaks = 0:5*10000\n ) +\n # colors\n scale_color_manual(\n # use a custom color palette\n values = colors,\n # overwrite legend keys\n labels = c(\"Winter\", \"Spring\", \"Summer\", \"Autumn\"),\n # adjust symbol size in legend size\n guide = guide_legend(override.aes = list(size = 4))\n ) +\n labs(\n # overwrite axis and legend titles\n x = \"Average feels-like temperature\", y = NULL, color = NULL,\n # add plot title and caption\n title = \"Trends of Reported Bike Rents versus Feels-Like Temperature in London\",\n caption = \"Data: TfL (Transport for London), Jan 2015–Dec 2016\"\n ) +\n # add theme with a custom font + larger element sizes\n theme_light(\n base_size = 15, base_family = \"Spline Sans\"\n ) +\n # theme adjustments\n theme(\n plot.title.position = \"plot\", # left-align title \n plot.caption.position = \"plot\", # right-align caption\n legend.position = \"top\", # place legend above plot\n plot.title = element_text(face = \"bold\", size = rel(1.4)), # larger, bold title\n axis.text = element_text(family = \"Spline Sans Mono\"), # monospaced font for axes\n axis.title.x = element_text( # left-aligned, grey x axis label\n hjust = 0, color = \"grey20\", margin = margin(t = 12)\n ),\n legend.text = element_text(size = rel(1)), # larger legend labels\n strip.text = element_text(face = \"bold\", size = rel(1.15)), # larger, bold facet labels\n panel.grid.major.x = element_blank(), # no vertical major lines\n panel.grid.minor = element_blank(), # no minor grid lines\n panel.spacing.x = unit(20, \"pt\"), # increase white space between panels\n panel.spacing.y = unit(10, \"pt\"), # increase white space between panels\n plot.margin = margin(rep(15, 4)) # adjust white space around plot\n )\n```\n:::\n\n\n\n# Saving Plots\n\n\n## Save the Graphic\n\n
\n\n\n::: {.cell hash='01-fundamentals_cache/revealjs/ggplot-save_e5f05ce158402d7e685982556d179209'}\n\n```{.r .cell-code}\nggsave(filename = \"my_plot.png\", plot = g)\n```\n:::\n\n\n::: fragment\n\n::: {.cell hash='01-fundamentals_cache/revealjs/ggplot-save-implicit_9766c1583f2fbb00908b516d985f6453'}\n\n```{.r .cell-code}\nggsave(\"my_plot.png\")\n```\n:::\n\n:::\n\n
\n\n::: fragment\n\n::: {.cell hash='01-fundamentals_cache/revealjs/ggplot-save-aspect_c4c7d92b369109a8c63e4d3acb8b3a4a'}\n\n```{.r .cell-code}\nggsave(\"my_plot.png\", width = 6, height = 5, dpi = 600)\n```\n:::\n\n:::\n\n\n## Plot Resolution\n\n\n\n\n\n::: {layout-ncol=\"2\"}\n![](plots/resolution-dpi-100.png)\n\n![](plots/resolution-dpi-600.png)\n:::\n\n\n## Plot Resolution\n\n::: {layout-ncol=\"2\"}\n![](img/resolution-dpi-100-zoom.png)\n\n![](img/resolution-dpi-600-zoom.png)\n:::\n\n\n## Save the Graphic\n\n
\n\n\n::: {.cell hash='01-fundamentals_cache/revealjs/ggplot-save_439dcf333a92406ebd8f3987d6bf9287'}\n\n```{.r .cell-code}\nggsave(filename = \"my_plot.png\", plot = g)\n```\n:::\n\n::: {.cell hash='01-fundamentals_cache/revealjs/ggplot-save-implicit_c5fdbcc9003675c2f0008fca98c36874'}\n\n```{.r .cell-code}\nggsave(\"my_plot.png\")\n```\n:::\n\n\n
\n\n\n::: {.cell hash='01-fundamentals_cache/revealjs/ggplot-save-aspect_c7758af26f1a01644a26e5432e2f2d0c'}\n\n```{.r .cell-code}\nggsave(\"my_plot.png\", width = 6, height = 5, dpi = 600)\n```\n:::\n\n\n::: fragment\n\n::: {.cell hash='01-fundamentals_cache/revealjs/ggplot-save-unit_1cb025e0ae788e688d21927fee627091'}\n\n```{.r .cell-code}\nggsave(\"my_plot.png\", width = 6*2.54, height = 5*2.54, unit = \"cm\", dpi = 600)\n```\n:::\n\n:::\n\n
\n\n::: fragment\n\n::: {.cell hash='01-fundamentals_cache/revealjs/ggplot-save-raster-agg_7717fd36fbcc79947a3b710ba2e06004'}\n\n```{.r .cell-code}\nggsave(\"my_plot.png\", device = agg_png)\n```\n:::\n\n:::\n\n::: fragment\n\n::: {.cell hash='01-fundamentals_cache/revealjs/ggplot-save-cairo_b9eb653fefdb960c5af7f9f35c0916ab'}\n\n```{.r .cell-code}\nggsave(\"my_plot.pdf\", device = cairo_pdf)\n```\n:::\n\n:::\n\n\n--------------------------------------------------------------------------------\n\n
\n\n![Modified from canva.com](img/vector-raster-canva.png){fig-alt=\"A comparison of vector and raster graphics.\" fig-width=\"150%\"}\n\n\n\n## The {ragg} Package\n\nprovides drop-in replacements for the default raster graphic devices\n\n::: incremental\n\n* faster\n* direct access to all system fonts\n* advanced text rendering\n * including support for right-to-left text, emojis, and font fallback\n* high quality anti-aliasing\n* high quality rotated text\n* supports 16-bit output\n* system independent rendering\n\n:::\n\n\n## The {ragg} Package\n\n
\n\n![Source: [tidyverse.org/blog/2021/02/modern-text-features](https://www.tidyverse.org/blog/2021/02/modern-text-features/)](img/ragg-left-and-right.png){fig-align=\"center\" fig-alt=\"A comparison of different graphic devices in R comparing the rendering of right-to-left text (and mixing left-to-right and right-to-left text).\"}\n\n\n## The {ragg} Package\n\n
\n\n![Source: [tidyverse.org/blog/2021/02/modern-text-features](https://www.tidyverse.org/blog/2021/02/modern-text-features/)](img/ragg-ligatures.png){fig-align=\"center\" fig-alt=\"A comparison of different graphic devices in R comparing the rendering of font ligatures.\"}\n\n\n## The {ragg} Package\n\n
\n\n![Source: [tidyverse.org/blog/2021/02/modern-text-features](https://www.tidyverse.org/blog/2021/02/modern-text-features/)](img/ragg-emojis.png){fig-align=\"center\" fig-alt=\"A comparison of different graphic devices in R comparing the rendering of emojis.\"}\n\n\n## The {ragg} Package\n\n
\n\n![Source: [tidyverse.org/blog/2021/02/modern-text-features](https://www.tidyverse.org/blog/2021/02/modern-text-features/)](img/ragg-fallback.png){fig-align=\"center\" fig-alt=\"A comparison of different graphic devices in R comparing the rendering missing glyphs, partly making use of fallback fonts.\"}\n\n\n## The {ragg} Package\n\n::: incremental\n* use {ragg} when saving ggplots by passing agg device function: `ggsave(device = agg_png))` ([used by default if installed](https://github.com/tidyverse/ggplot2/pull/4388))\n* use {ragg} in the *Rstudio Plots* pane be setting the backend to AGG: ![](img/ragg-rstudio.png){fig-alt=\"How to set the AGG device as the default in RStudio via Global Options > > General > Graphics > Backend.\"}\n* use {ragg} when knitting Rmarkdown files by setting `dev=\"ragg_png\"` in the code chunk options.\n\n:::\n\n\n## Save the Graphic\n\n
\n\n\n::: {.cell hash='01-fundamentals_cache/revealjs/ggplot-save_439dcf333a92406ebd8f3987d6bf9287'}\n\n```{.r .cell-code}\nggsave(filename = \"my_plot.png\", plot = g)\n```\n:::\n\n::: {.cell hash='01-fundamentals_cache/revealjs/ggplot-save-implicit_c5fdbcc9003675c2f0008fca98c36874'}\n\n```{.r .cell-code}\nggsave(\"my_plot.png\")\n```\n:::\n\n\n
\n\n\n::: {.cell hash='01-fundamentals_cache/revealjs/ggplot-save-aspect_c7758af26f1a01644a26e5432e2f2d0c'}\n\n```{.r .cell-code}\nggsave(\"my_plot.png\", width = 6, height = 5, dpi = 600)\n```\n:::\n\n::: {.cell hash='01-fundamentals_cache/revealjs/ggplot-save-unit_7b4c6b278330b6c7959419e4fe66e57e'}\n\n```{.r .cell-code}\nggsave(\"my_plot.png\", width = 6*2.54, height = 5*2.54, unit = \"cm\", dpi = 600)\n```\n:::\n\n
\n\n\n::: {.cell hash='01-fundamentals_cache/revealjs/ggplot-save-raster-agg_ee35fa72950cb04d7a1ba33120bd2923'}\n\n```{.r .cell-code}\nggsave(\"my_plot.png\", device = agg_png)\n```\n:::\n\n::: {.cell hash='01-fundamentals_cache/revealjs/ggplot-save-cairo_a437ddfca531433a3be58b3e32c0b6cf'}\n\n```{.r .cell-code}\nggsave(\"my_plot.pdf\", device = cairo_pdf)\n```\n:::\n\n\n::: fragment\n\n::: {.cell hash='01-fundamentals_cache/revealjs/ggplot-save-svg_04c01878d73ecdfe86e9bb01ec2cecfb'}\n\n```{.r .cell-code}\nggsave(\"my_plot.svg\")\n```\n:::\n\n:::\n\n\n--------------------------------------------------------------------------------\n\n![](img/figma-svg.png){fig-align=\"center\"}\n\n\n## How to Work with Aspect Ratios\n\n::: incremental\n- don't rely on the Rstudio viewer pane!\n- once you have a *\"it's getting close\"* prototype, settle on a plot size
\n- **Approach 1:** save the file and inspect it—go back to your IDE—repeat\n - tedious and time-consuming...
\n- **Approach 2:** use a qmd or rmd with inline output and chunk settings\n - set `fig-width` / `fig.width` and `fig-height` / `fig.height`
per chunk or globally
\n:::\n\n\n## Setting Plot Sizes in Quarto and Rmarkdown\n\n![](img/plot-size-chunk-yaml.png){fig-alt=\"A screenshot of an exemplary Qmd file with two chunks with different settings of fig-width and fig-height as YAML-styled options using the hashpipe. Unfortunately, these are not respected when the chunk output is printed inline.\" fig-width=\"60%\"}\n\n\n## Setting Plot Sizes in Quarto and Rmarkdown\n\n![](img/plot-size-chunk-inline.png){fig-alt=\"A screenshot of an exemplary Qmd file with two chunks with different settings of fig.width and fig.height set as inline chunk options.\" fig-width=\"60%\"}\n\n\n## How to Work with Aspect Ratios\n\n- don't rely on the Rstudio viewer pane!\n- once you have a *\"it's getting close\"* prototype, settle on a plot size
\n- **Approach 1:** save the file and inspect it—go back to your IDE—repeat\n - tedious and time-consuming...
\n- **Approach 2:** use a qmd or rmd with inline output and chunk settings\n - set `fig-width` / `fig.width` and `fig-height` / `fig.height`
per chunk or globally
\n- **Approach 3:** use our [{camcorder} package](https://github.com/thebioengineer/camcorder)\n - saves output from all `ggplot()` calls and displays it in the viewer pane\n\n\n## Setting Plot Sizes via {camcorder}\n\n
\n\n![](img/plot-size-camcorder-a.png){fig-alt=\"A screenshot of an exemplary R script with a plot automatically saved and isplayed in correct aspect ratio thanks to the camcorder package.\" fig-width=\"120%\"}\n\n\n## Setting Plot Sizes via {camcorder}\n\n
\n\n![](img/plot-size-camcorder-b.png){fig-alt=\"A screenshot of an exemplary R script with a plot automatically saved and isplayed in correct aspect ratio thanks to the camcorder package.\" fig-width=\"120%\"}\n\n\n## Setting Plot Sizes via {camcorder}\n\n\n::: {.cell hash='01-fundamentals_cache/revealjs/camcorder-record_00dad4ac42afbc08553cc5c510c3d7ea'}\n\n```{.r .cell-code code-line-numbers=\"1,2,3,4,5,6,7|9,10,11,12,13,15\"}\ncamcorder::gg_record(\n dir = here::here(\"temp\"), # path for plot files\n device = \"png\", # device to use\n width = 10, # figure width\n height = 5, # figure height\n dpi = 600 # plot resolution\n)\n\ng <- ggplot(bikes, aes(x = temp, y = count, color = day_night)) +\n geom_point(alpha = .3, size = 2) +\n scale_color_manual(values = c(day = \"#FFA200\", night = \"#757BC7\")) +\n theme_minimal(base_size = 14, base_family = \"Asap SemiCondensed\") +\n theme(panel.grid.minor = element_blank())\n\ng\n```\n:::\n\n\n\n## Setting Plot Sizes via {camcorder}\n\n\n::: {.cell hash='01-fundamentals_cache/revealjs/camcorder-resize_8c9dabd1c4d2661597733e6d716f0424'}\n\n```{.r .cell-code code-line-numbers=\"17,19\"}\ncamcorder::gg_record(\n dir = here::here(\"temp\"), # path for plot files\n device = \"png\", # device to use\n width = 10, # figure width\n height = 5, # figure height\n dpi = 600 # plot resolution\n)\n\ng <- ggplot(bikes, aes(x = temp, y = count, color = day_night)) +\n geom_point(alpha = .3, size = 2) +\n scale_color_manual(values = c(day = \"#FFA200\", night = \"#757BC7\")) +\n theme_minimal(base_size = 14, base_family = \"Asap SemiCondensed\") +\n theme(panel.grid.minor = element_blank())\n\ng\n\ncamcorder::gg_resize_film(width = 20) # update figure width\n\ng\n```\n:::\n\n\n\n## Like a Pro: Set Theme Globally\n\n\n::: {.cell}\n\n```{.r .cell-code}\ntheme_set(theme_minimal(base_size = 14, base_family = \"Asap SemiCondensed\"))\ntheme_update(panel.grid.minor = element_blank())\n```\n:::\n\n\n\n# Programming
with ggplot2\n\n\n## Conditional Components\n\n\n::: {.cell hash='01-fundamentals_cache/revealjs/conditional-components_caef70472f777a01248d33a3f284f406'}\n\n```{.r .cell-code code-line-numbers=\"1|3,4,5|4\"}\nsmooth <- TRUE\n\nggplot(bikes, aes(x = temp, y = humidity)) +\n { if(smooth) geom_smooth(color = \"red\") } +\n geom_point(alpha = .5)\n```\n:::\n\n\n\n## Conditional Components\n\n\n::: {.cell layout-align=\"center\" hash='01-fundamentals_cache/revealjs/conditional-components-1_af3590b704ded767678e130b9bed0532'}\n\n```{.r .cell-code}\nsmooth <- TRUE\n\nggplot(bikes, aes(x = temp, y = humidity)) +\n { if(smooth) geom_smooth(color = \"red\") } +\n geom_point(alpha = .5)\n```\n\n::: {.cell-output-display}\n![](01-fundamentals_files/figure-revealjs/conditional-components-1-1.png){fig-align='center' width=1600}\n:::\n:::\n\n\n\n## Conditional Components\n\n\n::: {.cell layout-align=\"center\" hash='01-fundamentals_cache/revealjs/conditional-components-2_f29ca7457d58aeba72af8364052998e2'}\n\n```{.r .cell-code code-line-numbers=\"1\"}\nsmooth <- FALSE\n\nggplot(bikes, aes(x = temp, y = humidity)) +\n { if(smooth) geom_smooth(color = \"red\") } +\n geom_point(alpha = .5)\n```\n\n::: {.cell-output-display}\n![](01-fundamentals_files/figure-revealjs/conditional-components-2-1.png){fig-align='center' width=1600}\n:::\n:::\n\n\n\n## Wrapper Functions for Plots\n\n\n::: {.cell hash='01-fundamentals_cache/revealjs/conditional-components-function_bbcbb08aec8f13e9bfdf6dcd42f130a4'}\n\n```{.r .cell-code code-line-numbers=\"1,5|2,3,4\"}\ndraw_scatter <- function(smooth = TRUE) {\n ggplot(bikes, aes(x = temp, y = humidity)) +\n { if(smooth) geom_smooth(color = \"red\") } +\n geom_point(alpha = .5)\n}\n```\n:::\n\n\n\n## Wrapper Functions for Plots\n\n\n::: {.cell output-location='column' hash='01-fundamentals_cache/revealjs/conditional-components-function-plot-default_b88942c23d103843491ed566b4ee8391'}\n\n```{.r .cell-code}\ndraw_scatter()\n```\n\n::: {.cell-output-display}\n![](01-fundamentals_files/figure-revealjs/conditional-components-function-plot-default-1.png){width=1000}\n:::\n:::\n\n\n\n## Wrapper Functions for Plots\n\n\n::: {.cell output-location='column' hash='01-fundamentals_cache/revealjs/conditional-components-function-plot-false_9e465abdd77a1628e20f9b9194f5c781'}\n\n```{.r .cell-code}\ndraw_scatter(smooth = FALSE)\n```\n\n::: {.cell-output-display}\n![](01-fundamentals_files/figure-revealjs/conditional-components-function-plot-false-1.png){width=1000}\n:::\n:::\n\n\n\n## Components as Functions\n\n\n::: {.cell}\n\n```{.r .cell-code code-line-numbers=\"1,2,7|3,6|4,5\"}\ngeom_scatterfit <- function(pointsize = 1, pointalpha = 1, \n method = \"lm\", linecolor = \"red\", ...) {\n list(\n geom_point(size = pointsize, alpha = pointalpha, ...),\n geom_smooth(method = method, color = linecolor, ...)\n )\n}\n```\n:::\n\n\n\n## Components as Functions\n\n\n::: {.cell output-location='column' hash='01-fundamentals_cache/revealjs/function-components-defaults_b82bb4e1013de3757c454e7f445193ef'}\n\n```{.r .cell-code code-line-numbers=\"3\"}\nggplot(bikes,\n aes(x = humidity, y = count)) +\n geom_scatterfit()\n```\n\n::: {.cell-output-display}\n![](01-fundamentals_files/figure-revealjs/function-components-defaults-1.png){width=1000}\n:::\n:::\n\n\n\n## Components as Functions\n\n\n::: {.cell output-location='column' hash='01-fundamentals_cache/revealjs/function-components-args_166742f1bde5f609121fd38acd7a44d2'}\n\n```{.r .cell-code code-line-numbers=\"4,5\"}\nggplot(bikes,\n aes(x = humidity, y = count)) +\n geom_scatterfit(\n color = \"#28A87D\", \n linewidth = 3\n )\n```\n\n::: {.cell-output-display}\n![](01-fundamentals_files/figure-revealjs/function-components-args-1.png){width=1000}\n:::\n:::\n\n\n\n## Components as Functions\n\n\n::: {.cell output-location='column' hash='01-fundamentals_cache/revealjs/function-components-custom_0855f87dcad4c1979956d8c4ba0fb5cc'}\n\n```{.r .cell-code code-line-numbers=\"1,2|4,5,6,7\"}\nggplot(diamonds, \n aes(x = carat, y = price)) +\n geom_scatterfit(\n pointsize = .5, \n pointalpha = .1,\n method = \"gam\",\n linecolor = \"#EFAC00\"\n )\n```\n\n::: {.cell-output-display}\n![](01-fundamentals_files/figure-revealjs/function-components-custom-1.png){width=1000}\n:::\n:::\n\n\n\n## Components as Functions\n\n\n::: {.cell}\n\n```{.r .cell-code code-line-numbers=\"1,14|2,13|3,4,5,6,7|8,9,10,11,12\"}\nscales_log <- function(sides = \"xy\") {\n list(\n if(stringr::str_detect(sides, \"x\")) {\n scale_x_log10(\n breaks = c(10^(1:100)), labels = scales::label_log()\n )\n },\n if(stringr::str_detect(sides, \"y\")) {\n scale_y_log10(\n breaks = c(10^(1:100)), labels = scales::label_log()\n )\n }\n )\n}\n```\n:::\n\n\n\n## Components as Functions\n\n\n::: {.cell output-location='column' hash='01-fundamentals_cache/revealjs/function-components-scales-custom_5b6321eab679a1975d13c047c2a99c10'}\n\n```{.r .cell-code code-line-numbers=\"9\"}\nggplot(diamonds, \n aes(x = carat, y = price)) +\n geom_scatterfit(\n pointsize = .5, \n pointalpha = .1,\n method = \"gam\",\n linecolor = \"#EFAC00\"\n ) +\n scales_log(sides = \"y\")\n```\n\n::: {.cell-output-display}\n![](01-fundamentals_files/figure-revealjs/function-components-scales-custom-1.png){width=1000}\n:::\n:::\n\n\n\n## Iterative Graphics\n\n\n::: {.cell}\n\n```{.r .cell-code code-line-numbers=\"1,11|2,3,4|5,6,7,8,9|1,4,9\"}\ntrends_monthly <- function(grp = \"January\") {\n bikes |> \n dplyr::mutate(month = lubridate::month(date, label = TRUE, abbr = FALSE)) |> \n dplyr::filter(month %in% grp) |> \n ggplot(aes(x = temp, y = count, color = day_night)) +\n geom_point(alpha = .2, show.legend = FALSE) +\n geom_smooth(se = FALSE) +\n scale_color_manual(values = c(\"#FFA200\", \"#757bc7\")) +\n labs(title = grp, x = \"Temperature\", y = \"Bike shares\", color = NULL)\n}\n```\n:::\n\n\n\n## Iterative Graphics\n\n\n::: {.cell output-location='column'}\n\n```{.r .cell-code}\ntrends_monthly(\"July\")\n```\n\n::: {.cell-output-display}\n![](01-fundamentals_files/figure-revealjs/function-iterate-monthly-july-1.png){width=1000}\n:::\n:::\n\n\n\n## Iterative Graphics\n\n\n::: {.cell}\n\n```{.r .cell-code code-line-numbers=\"8,9,10\"}\ntrends_monthly <- function(grp = \"January\") {\n bikes |> \n dplyr::mutate(month = lubridate::month(date, label = TRUE, abbr = FALSE)) |> \n dplyr::filter(month %in% grp) |> \n ggplot(aes(x = temp, y = count, color = day_night)) +\n geom_point(alpha = .2, show.legend = FALSE) +\n geom_smooth(se = FALSE) +\n # keep axis ranges consistent\n scale_x_continuous(limits = range(bikes$temp)) +\n scale_y_continuous(limits = range(bikes$count)) +\n scale_color_manual(values = c(\"#FFA200\", \"#757bc7\")) +\n labs(title = grp, x = \"Temperature\", y = \"Bike shares\", color = NULL)\n}\n```\n:::\n\n\n\n## Iterative Graphics\n\n\n::: {.cell output-location='column'}\n\n```{.r .cell-code}\ntrends_monthly(\"July\")\n```\n\n::: {.cell-output-display}\n![](01-fundamentals_files/figure-revealjs/function-iterate-monthly-ranges-july-1.png){width=1000}\n:::\n:::\n\n\n\n## Iterative Graphics\n\n\n::: {.cell}\n\n```{.r .cell-code}\nplots <- purrr::map(month.name[1:12], trends_monthly) ## also: ~ trends_monthly(.x)\n```\n:::\n\n\n\n## Iterative Graphics\n\n\n::: {.cell layout-align=\"center\"}\n\n```{.r .cell-code code-line-numbers=\"2\"}\nplots <- purrr::map(month.name[1:12], trends_monthly) ## also: ~ trends_monthly(.x)\nplots[[9]]\n```\n\n::: {.cell-output-display}\n![](01-fundamentals_files/figure-revealjs/function-iterate-monthly-ranges-purrr-single-1.png){fig-align='center' width=1600}\n:::\n:::\n\n\n\n## Iterative Graphics\n\n\n::: {.cell layout-align=\"center\"}\n\n```{.r .cell-code code-line-numbers=\"2\"}\nplots <- purrr::map(month.name[1:12], trends_monthly) ## also: ~ trends_monthly(.x)\npatchwork::wrap_plots(plots)\n```\n\n::: {.cell-output-display}\n![](01-fundamentals_files/figure-revealjs/function-iterate-monthly-ranges-wrap-1.png){fig-align='center' width=3600}\n:::\n:::\n\n\n\n## Iterative Graphics\n\n\n::: {.cell}\n\n```{.r .cell-code code-line-numbers=\"1,11|2|3,4|5,6,7|8,9,10\"}\nplot_density <- function(data, var, grp = \"\") {\n ggplot(data, aes(x = !!sym(var))) +\n geom_density(aes(fill = !!sym(grp)), position = \"identity\",\n color = \"grey30\", alpha = .3) +\n coord_cartesian(expand = FALSE, clip = \"off\") +\n scale_y_continuous(labels = scales::label_number()) +\n scale_fill_brewer(palette = \"Dark2\", name = NULL) +\n theme(legend.position = \"top\")\n}\n```\n:::\n\n\n\n## Iterative Graphics\n\n\n::: {.cell output-location='column'}\n\n```{.r .cell-code}\nplot_density(\n bikes, \"count\"\n)\n```\n\n::: {.cell-output-display}\n![](01-fundamentals_files/figure-revealjs/function-density-plot-1.png){width=1000}\n:::\n:::\n\n\n\n## Iterative Graphics\n\n\n::: {.cell layout-align=\"center\"}\n\n```{.r .cell-code code-line-numbers=\"1,2,3,4|2|3|5\"}\nplots <- purrr::map(\n c(\"count\", \"temp\", \"humidity\", \"wind_speed\"), \n ~ plot_density(data = bikes, var = .x, grp = \"day_night\")\n)\npatchwork::wrap_plots(plots, nrow = 1)\n```\n\n::: {.cell-output-display}\n![](01-fundamentals_files/figure-revealjs/function-density-plot-grp-1.png){fig-align='center' width=2800}\n:::\n:::\n\n\n\n## Iterative Graphics\n\n\n::: {.cell layout-align=\"center\"}\n\n```{.r .cell-code code-line-numbers=\"2|3|5\"}\nplots <- purrr::map(\n names(dplyr::select(midwest, where(is.numeric))),\n ~plot_density(data = midwest, var = .x)\n)\npatchwork::wrap_plots(plots)\n```\n\n::: {.cell-output-display}\n![](01-fundamentals_files/figure-revealjs/function-density-plot-midwest-1.png){fig-align='center' width=4000}\n:::\n:::\n\n\n\n# Combine Plots\n\n\n## Combine Plots with {patchwork}\n\n\n::: {.cell}\n\n```{.r .cell-code code-line-numbers=\"1|3|5|7∂\"}\nlibrary(patchwork)\n\np1 <- plot_density(data = bikes, var = \"count\", grp = \"day_night\")\n\np2 <- plot_density(data = bikes, var = \"humidity\", grp = \"day_night\")\n\np3 <- ggplot(bikes, aes(x = humidity, y = count)) + geom_scatterfit(pointalpha = .3)\n```\n:::\n\n\n\n## Combine Plots with {patchwork}\n\n\n::: {.cell layout-align=\"center\"}\n\n```{.r .cell-code}\n(p1 + p2) / p3\n```\n\n::: {.cell-output-display}\n![](01-fundamentals_files/figure-revealjs/patchwork-example-1-1.png){fig-align='center' width=2400}\n:::\n:::\n\n\n\n## Combine Plots with {patchwork}\n\n\n::: {.cell layout-align=\"center\"}\n\n```{.r .cell-code}\n(p1 + p2) / p3 + plot_layout(heights = c(1, 2))\n```\n\n::: {.cell-output-display}\n![](01-fundamentals_files/figure-revealjs/patchwork-example-2-1.png){fig-align='center' width=2400}\n:::\n:::\n\n\n\n## Combine Plots with {patchwork}\n\n\n::: {.cell layout-align=\"center\"}\n\n```{.r .cell-code}\n(p1 + p2) / p3 + plot_layout(heights = c(1, 2), guides = \"collect\")\n```\n\n::: {.cell-output-display}\n![](01-fundamentals_files/figure-revealjs/patchwork-example-3-1.png){fig-align='center' width=2400}\n:::\n:::\n\n\n\n## Combine Plots with {patchwork}\n\n\n::: {.cell layout-align=\"center\"}\n\n```{.r .cell-code}\n(p1 + p2) / p3 + plot_layout(heights = c(1, 2), guides = \"collect\") +\n plot_annotation(theme = theme(legend.justification = \"top\"))\n```\n\n::: {.cell-output-display}\n![](01-fundamentals_files/figure-revealjs/patchwork-example-4-1.png){fig-align='center' width=2400}\n:::\n:::\n\n\n\n## Combine Plots with {patchwork}\n\n\n::: {.cell layout-align=\"center\"}\n\n```{.r .cell-code}\n(p1 + p2) / p3 + plot_layout(heights = c(1, 2), guides = \"collect\") +\n plot_annotation(tag_levels = \"A\", tag_suffix = \".\", theme = theme(legend.justification = \"top\"))\n```\n\n::: {.cell-output-display}\n![](01-fundamentals_files/figure-revealjs/patchwork-example-5-1.png){fig-align='center' width=2400}\n:::\n:::\n\n\n\n# Exciting Extension Packages\n\n\n## Layers\n\n+ [**`{geofacet}`**](https://hafen.github.io/geofacet/) — tile grid maps\n+ [**`{ggalluvial}`**](https://github.com/hrbrmstr/ggalt) — alluvial plots\n+ [**`{ggalt}`**](https://github.com/hrbrmstr/ggalt) — dumbbell, horizon, and lollipop charts, splines, ...\n+ [**`{ggbeeswarm}`**](https://github.com/hrbrmstr/ggalt) — beeswarm plots and variants\n+ [**`{ggbraid}`**](https://nsgrantham.github.io/ggbraid/) — ribbons for alternating groups\n+ [**`{ggbump}`**](https://github.com/davidsjoberg/ggbump) — parallel sets, pie charts, geometries, splines, voronoi, ...\n+ [**`{ggdensity}`**](https://jamesotto852.github.io/ggdensity/) — improved density plots\n+ [**`{ggdist}`**](https://github.com/davidsjoberg/ggbump) — uncertainty visualizations\n+ [**`{ggforce}`**](https://ggforce.data-imaginist.com/) — several interesting layers (and more)\n+ [**`{ggpattern}`**](https://github.com/coolbutuseless/ggpattern) — pattern fills for layers\n\n\n## Layers (continued)\n\n+ [**`{ggpointdensity}`**](https://github.com/LKremer/ggpointdensity) — density gradients for scatter plots\n+ [**`{ggraph}`**](https://github.com/thomasp85/ggraph) — networks, graphs & trees\n+ [**`{ggridges}`**](https://github.com/clauswilke/ggridges) — ridgeline plots\n+ [**`{ggsankey}`**](https://github.com/davidsjoberg/ggsankey) — sankey diagrams\n+ [**`{ggsignif}`**](https://const-ae.github.io/ggsignif/) — significance levels\n+ [**`{ggstar}`**](https://github.com/xiangpin/ggstar) — more point shapes\n+ [**`{ggstream}`**](https://github.com/davidsjoberg/ggstream) — stream graphs\n+ [**`{ggupset}`**](https://github.com/const-ae/ggupset) — upset graphs\n+ [**`{treemapify}`**](https://wilkox.org/treemapify/) — treemaps\n\n\n## Utilities\n\n+ [**`{cowplot}`**](https://cran.r-project.org/web/packages/cowplot/vignettes/introduction.html) — combine ggplots\n+ [**`{ggannotate}`**](https://github.com/MattCowgill/ggannotate) — point-n-click annotations\n+ [**`{ggblend}`**](https://mjskay.github.io/ggblend/) — blend, compose, adjust layers\n+ [**`{ggfittext}`**](https://wilkox.org/ggfittext/) — scale text according to space\n+ [**`{ggfx}`**](https://ggfx.data-imaginist.com/) — shaders and filters for layers\n+ [**`{ggh4x}`**](https://teunbrand.github.io/ggh4x/) — facets, positions, and more\n+ [**`{ggtext}`**](https://github.com/thomasp85/patchwork#patchwork) — text rendering for theme elements + text layers\n+ [**`{lemon}`**](https://github.com/stefanedwards/lemon) — axis lines (and a few layers)\n+ [**`{patchwork}`**](https://github.com/thomasp85/patchwork#patchwork) — combine ggplots\n+ [**`{scales}`**](https://scales.r-lib.org/) — control scales \n\n\n## Themes\n\n+ [**`{ggdark}`**](https://github.com/nsgrantham/ggdark)\n+ [**`{ggsci}`**](https://github.com/jrnold/ggthemes) (also color scales)\n+ [**`{ggtech}`**](https://github.com/ricardo-bion/ggtech) (also color scales)\n+ [**`{ggthemes}`**](https://github.com/jrnold/ggthemes) (also color scales)\n+ [**`{ggthemr}`**](https://github.com/Mikata-Project/ggthemr)\n+ [**`{hrbrthemes}`**](https://github.com/hrbrmstr/hrbrthemes) (also color scales)\n+ [**`{tvthemes}`**](https://ryo-n7.github.io/tvthemes/) (also color scales)\n\n\n## Color Palettes\n\n+ [**`{colorspace}`**](https://cran.r-project.org/web/packages/colorspace/vignettes/colorspace.html)\n+ [**`{jcolors}`**](https://jaredhuling.org/jcolors/)\n+ [**`{MetBrewer}`**](https://github.com/BlakeRMills/MetBrewer)\n+ [**`{nord}`**](https://cran.r-project.org/web/packages/nord/readme/README.html)\n+ [**`{rcartocolor}`**](https://jakubnowosad.com/rcartocolor/)\n+ [**`{RColorBrewer}`**](https://cran.r-project.org/web/packages/RColorBrewer/index.html)\n+ [**`{scico}`**](https://github.com/thomasp85/scico)\n+ [**`{unikn}`**](https://github.com/hneth/unikn)\n+ [**`{viridis}`**](https://cran.r-project.org/web/packages/viridis/vignettes/intro-to-viridis.html)\n+ [**`{wesanderson}`**](https://github.com/karthik/wesanderson)\n\n\n## Interactive Charts\n\n+ [**`{ggiraph}`**](https://davidgohel.github.io/ggiraph/)\n+ [**`{plotly}`**](https://plotly.com/r/)\n+ [**`{echarts4r}`**](https://echarts4r.john-coene.com/)*\n+ [**`{highcharter}`**](https://jkunst.com/highcharter/)*\n+ [**`{charter}`**](https://github.com/JohnCoene/charter)*\n+ [**`{streamgraph}`**](https://hrbrmstr.github.io/streamgraph/)*\n+ [**`{tmap}`**](https://cran.r-project.org/web/packages/tmap/vignettes/tmap-getstarted.html)*\n+ [**`{leaflet}`**](https://rstudio.github.io/leaflet/)*\n+ [**`{globe4r}`**](https://globe4r.john-coene.com/)*\n+ [**`{grapher}`**](https://grapher.network/)*\n\n* not using ggplot2
\n\n\n## Recap\n\n::: recap\n- a basic ggplot is build by specifying three components:
`data`, `aes`thetics and a `layer` (usually a `geom_*` or `stat_*`)\n- *aesthetic mappings* define how variables map to visual properties\n- the default appearance of all other components can be modified via `scale_*`, `coord_*`, `facet_*` and `theme_*` / `theme` \n- use the devices cairo (pdf) and agg (png, jpg, tiff) when saving plots\n- find a suitable plot size by setting figure chunk options in qmd/rmd files or with the help of the `{camcorder}` package\n- define conditional components, custom layers and functions to generate plots more efficiently and to iterate over multiple inputs\n- combine multiple plot outputs with `{patchwork}`\n:::\n\n\n# Exercises\n\n\n## Exercise 1\n\n::: question\n- **Discuss / investigate with your neighbor:**\n - What are the differences between `geom_line()` and `geom_path()`?\n - Why can you use `geom_smooth()` and `stat_smooth()` interchangeably?\n - What are the three ways to *remove a legend* from a ggplot?\n:::\n\n\n## Exercise 2\n\n::: question\n- **Explore the TfL bike share data visually:**\n - Create a *time series* of counts per day and night.\n - Draw *box and whisker plots* of average temperatures per month.\n - Visualize bike counts per weather type and period as *bar chart*. \n- **Combine the three plots with {patchwork}.**\n- **Export the final graphic in a format of your choice.**\n:::\n\n## {background-image=\"img/exercise-what-now.png\" background-position=\"center\" background-size=\"75%\"}\n",
"supporting": [],
"filters": [
"rmarkdown/pagebreak.lua"
diff --git a/_freeze/materials/01-fundamentals/figure-revealjs/walkthrough-15-1.png b/_freeze/materials/01-fundamentals/figure-revealjs/walkthrough-15-1.png
index 13fc068..b6029c5 100644
Binary files a/_freeze/materials/01-fundamentals/figure-revealjs/walkthrough-15-1.png and b/_freeze/materials/01-fundamentals/figure-revealjs/walkthrough-15-1.png differ
diff --git a/_freeze/materials/01-fundamentals/figure-revealjs/walkthrough-full-1.png b/_freeze/materials/01-fundamentals/figure-revealjs/walkthrough-full-1.png
index 13fc068..b6029c5 100644
Binary files a/_freeze/materials/01-fundamentals/figure-revealjs/walkthrough-full-1.png and b/_freeze/materials/01-fundamentals/figure-revealjs/walkthrough-full-1.png differ
diff --git a/_quarto.yml b/_quarto.yml
index 3ad9b66..5b252ef 100644
--- a/_quarto.yml
+++ b/_quarto.yml
@@ -1,5 +1,6 @@
project:
type: website
+ output-dir: docs
resources:
- "images/twitter-card.png"
render:
diff --git a/docs/docs/docs/docs/images/cedric.png b/docs/docs/docs/docs/images/cedric.png
new file mode 100644
index 0000000..2db48b0
Binary files /dev/null and b/docs/docs/docs/docs/images/cedric.png differ
diff --git a/docs/docs/docs/docs/images/logo.png b/docs/docs/docs/docs/images/logo.png
new file mode 100644
index 0000000..d89034a
Binary files /dev/null and b/docs/docs/docs/docs/images/logo.png differ
diff --git a/docs/docs/docs/docs/images/team-page.png b/docs/docs/docs/docs/images/team-page.png
new file mode 100644
index 0000000..5edef7c
Binary files /dev/null and b/docs/docs/docs/docs/images/team-page.png differ
diff --git a/docs/docs/docs/docs/images/twitter-card.png b/docs/docs/docs/docs/images/twitter-card.png
new file mode 100644
index 0000000..df77ccc
Binary files /dev/null and b/docs/docs/docs/docs/images/twitter-card.png differ
diff --git a/docs/materials/00-welcome.html b/docs/materials/00-welcome.html
index 607c134..b870637 100644
--- a/docs/materials/00-welcome.html
+++ b/docs/materials/00-welcome.html
@@ -451,7 +451,7 @@
-