{ "cells": [ { "cell_type": "markdown", "metadata": { "deletable": false, "editable": false, "nbgrader": { "cell_type": "markdown", "checksum": "ede6c9c027c6e150253eb7a111cd752d", "grade": false, "grade_id": "cell-fc171c7a1fa7ad47", "locked": true, "schema_version": 3, "solution": false, "task": false } }, "source": [ "# Worksheet A-3: Graphing with the Grammar of Graphics through ggplot2\n", "\n", "By the end of this worksheet, you will be able to:\n", "\n", "+ Identify the seven components of the grammar of graphics underlying ggplot2.\n", "+ Produce plots with ggplot2 by implementing the components of the grammar of graphics.\n", "+ Customize the look of ggplot2 graphs.\n", "+ Choose an appropriate plot type for Exploratory Data Analysis, based on an understanding of what makes a graph effective. \n", "\n", "To get full marks for each participation worksheet, you must successfully answer at least 10 of the autograded questions. In this worksheet, there are a total of 21 autograded questions. \n", "\n", "\n", "## Getting Started\n", "\n", "Load the required packages for this worksheet:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "deletable": false, "editable": false, "nbgrader": { "cell_type": "code", "checksum": "3ac361dd4c2264e5a68a6999d499857d", "grade": false, "grade_id": "cell-24309ff38e46bf59", "locked": true, "schema_version": 3, "solution": false, "task": false } }, "outputs": [], "source": [ "suppressPackageStartupMessages(library(tidyverse))\n", "suppressPackageStartupMessages(library(rlang))\n", "suppressPackageStartupMessages(library(tsibble))\n", "suppressPackageStartupMessages(library(gapminder))\n", "suppressPackageStartupMessages(library(palmerpenguins))\n", "suppressPackageStartupMessages(library(ggridges))\n", "suppressPackageStartupMessages(library(scales))\n", "suppressPackageStartupMessages(library(testthat))\n", "suppressPackageStartupMessages(library(digest))" ] }, { "cell_type": "markdown", "metadata": { "deletable": false, "editable": false, "nbgrader": { "cell_type": "markdown", "checksum": "79ffd701037e8f861cb92001cacb4863", "grade": false, "grade_id": "cell-04c685cb2eb8b6f0", "locked": true, "schema_version": 3, "solution": false, "task": false } }, "source": [ "The following code chunk has been unlocked, to give you the flexibility to start this document with some of your own code. Remember, it's bad manners to keep a call to `install.packages()` in your source code, so don't forget to delete these lines if you ever need to run them." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# An unlocked code cell." ] }, { "cell_type": "markdown", "metadata": { "deletable": false, "editable": false, "nbgrader": { "cell_type": "markdown", "checksum": "2281fae73aa69f96b8ecbd309cad0d35", "grade": false, "grade_id": "cell-1d39f2e3556c89f3", "locked": true, "schema_version": 3, "solution": false, "task": false } }, "source": [ "# Part 1: The Grammar of Graphics\n", "\n", "\n", "## QUESTION 1.0\n", "\n", "Consider the following plot. Don't concern yourself with the code at this point." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "deletable": false, "editable": false, "fig.height": 2, "fig.width": 5, "nbgrader": { "cell_type": "code", "checksum": "dbfcfe3cb4d74fac9a85a71348592dcd", "grade": false, "grade_id": "cell-13ae5030ac04ea95", "locked": true, "schema_version": 3, "solution": false, "task": false } }, "outputs": [], "source": [ "gapminder %>% \n", " filter(year == 2007) %>% \n", " mutate(continent = fct_infreq(continent)) %>% \n", " ggplot(aes(continent)) +\n", " geom_bar() +\n", " theme_bw()" ] }, { "cell_type": "markdown", "metadata": { "deletable": false, "editable": false, "nbgrader": { "cell_type": "markdown", "checksum": "a4ef01d47e133b83d6a03a9efe36960e", "grade": false, "grade_id": "cell-8ac4a30c1f3fa392", "locked": true, "schema_version": 3, "solution": false, "task": false } }, "source": [ "Which table specifies the seven grammar of graphics components of this plot? Choose the best option, and place your choice in a variable named `answer1.0`\n", "\n", "A)\n", "\n", "| Grammar Component | Specification |\n", "|-----------------------|---------------|\n", "| __data__ | `gapminder` |\n", "| __aesthetic mapping__ | `continent` |\n", "| __geometric object__ | `bars` |\n", "| scale | `logarithmic` |\n", "| statistical transform | `none` |\n", "| coordinate system | `rectangular` |\n", "| facetting | `none` |\n", "\n", "B)\n", "\n", "| Grammar Component | Specification |\n", "|-----------------------|---------------|\n", "| __data__ | `gapminder` |\n", "| __aesthetic mapping__ | `continent` |\n", "| __geometric object__ | `bars` |\n", "| scale | `linear` |\n", "| statistical transform | `none` |\n", "| coordinate system | `rectangular` |\n", "| facetting | `none` |\n", "\n", "C)\n", "\n", "| Grammar Component | Specification |\n", "|-----------------------|---------------|\n", "| __data__ | `gapminder` |\n", "| __aesthetic mapping__ | `year` |\n", "| __geometric object__ | `bars` |\n", "| scale | `linear` |\n", "| statistical transform | `none` |\n", "| coordinate system | `rectangular` |\n", "| facetting | `none` |" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "deletable": false, "nbgrader": { "cell_type": "code", "checksum": "a36024ccd7e43e32c3f7dd7de73c40e3", "grade": false, "grade_id": "cell-cfc3d9e1948b5dd5", "locked": false, "schema_version": 3, "solution": true, "task": false } }, "outputs": [], "source": [ "# answer1.0 <- \"FILL_THIS_IN\"\n", "# your code here\n", "fail() # No Answer - remove if you provide an answer" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "deletable": false, "editable": false, "nbgrader": { "cell_type": "code", "checksum": "c46fd5e1897754d93b14fca817b08592", "grade": true, "grade_id": "cell-91fe67fe9b8d9b44", "locked": true, "points": 1, "schema_version": 3, "solution": false, "task": false } }, "outputs": [], "source": [ "test_that(\"Question 1.0\", {\n", " expect_equal(digest(as.character(toupper(answer1.0))), \"3a5505c06543876fe45598b5e5e5195d\")\n", "})" ] }, { "cell_type": "markdown", "metadata": { "deletable": false, "editable": false, "nbgrader": { "cell_type": "markdown", "checksum": "08143c377adee56296792784a4771391", "grade": false, "grade_id": "cell-45cc0c3aa866aa91", "locked": true, "schema_version": 3, "solution": false, "task": false } }, "source": [ "## Question 1.1\n", "\n", "Consider the following plot. Don't concern yourself with the code at this point." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "deletable": false, "editable": false, "nbgrader": { "cell_type": "code", "checksum": "35aecc6ea16a61f1d0c22b424d067702", "grade": false, "grade_id": "cell-0146fd3d421ece40", "locked": true, "schema_version": 3, "solution": false, "task": false } }, "outputs": [], "source": [ "ggplot(gapminder, aes(gdpPercap, lifeExp)) +\n", " geom_point(alpha = 0.1) +\n", " scale_x_log10(\"GDP per capita\", labels = scales::dollar_format()) +\n", " theme_bw() +\n", " ylab(\"Life Expectancy\")" ] }, { "cell_type": "markdown", "metadata": { "deletable": false, "editable": false, "nbgrader": { "cell_type": "markdown", "checksum": "e4349763d8af3f11792eb8b080f4197f", "grade": false, "grade_id": "cell-d846800cf5df5bd3", "locked": true, "schema_version": 3, "solution": false, "task": false } }, "source": [ "What is the aesthetic mapping in this plot? Place your answer in a variable named `answer1.1`\n", "\n", "A) alpha = 0.1 \n", "\n", "B) x: gdpPercap, y: lifeExp \n", "\n", "C) none \n", "\n", "D) \"Life Expectancy\"" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "deletable": false, "name": "question-2-1", "nbgrader": { "cell_type": "code", "checksum": "9d38dd8eb229a60de1904b0538414352", "grade": false, "grade_id": "cell-3dd0ed73c41c1136", "locked": false, "schema_version": 3, "solution": true, "task": false } }, "outputs": [], "source": [ "# answer1.1 <- \"FILL_THIS_IN\"\n", "# your code here\n", "fail() # No Answer - remove if you provide an answer" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "deletable": false, "editable": false, "name": "test-2-1", "nbgrader": { "cell_type": "code", "checksum": "c78fe7b14b32a8af0f50e7010656bf06", "grade": true, "grade_id": "cell-8c5e0da43802f075", "locked": true, "points": 1, "schema_version": 3, "solution": false, "task": false } }, "outputs": [], "source": [ "test_that(\"Question 1.1\", {\n", " expect_equal(digest(as.character(toupper(answer1.1))), \"3a5505c06543876fe45598b5e5e5195d\")\n", "})" ] }, { "cell_type": "markdown", "metadata": { "deletable": false, "editable": false, "nbgrader": { "cell_type": "markdown", "checksum": "5f0b97e50f3cc94c331ea745f8f5a55e", "grade": false, "grade_id": "cell-2f034a30aeb54771", "locked": true, "schema_version": 3, "solution": false, "task": false } }, "source": [ "# Part 2: `ggplot2` Syntax \n", "\n", "The following is a tsibble (a special type of tibble containing time series data), stored in the variable `mauna`, of CO$_2$ concentrations collected monthly at the Mauna Loa station.\n", "\n", "Execute this code to store the data in `mauna`:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "deletable": false, "editable": false, "nbgrader": { "cell_type": "code", "checksum": "342528eb322ac3656dd072ce711fd3d8", "grade": false, "grade_id": "cell-4cc5d4b024e3f5ef", "locked": true, "schema_version": 3, "solution": false, "task": false } }, "outputs": [], "source": [ "mauna <- tsibble::as_tsibble(co2) %>% \n", " rename(month = index, conc = value)\n", "head(mauna)" ] }, { "cell_type": "markdown", "metadata": { "deletable": false, "editable": false, "nbgrader": { "cell_type": "markdown", "checksum": "192959dadba87af2a1110221e98dfbfe", "grade": false, "grade_id": "cell-912fc1bf38a4b46f", "locked": true, "schema_version": 3, "solution": false, "task": false } }, "source": [ "## QUESTION 2.0\n", "\n", "Use ggplot2 to produce a line chart showing the concentration of CO$_2$ over time in the `mauna` dataset. Specifically, the plot should have the following grammar components:\n", "\n", "| Grammar Component | Specification |\n", "|-----------------------|---------------|\n", "| __data__ | `mauna` |\n", "| __aesthetic mapping__ | x: month, y: conc |\n", "| __geometric object__ | lines |\n", "| scale | linear |\n", "| statistical transform | none |\n", "| coordinate system | rectangular |\n", "| facetting | none |\n", "\n", "Fill in the blanks to obtain the plot, storing your plot in a variable named `answer2.0`.\n", "\n", "```\n", "answer2.0 <- ggplot(FILL_THIS_IN, aes(FILL_THIS_IN, FILL_THIS_IN)) +\n", " FILL_THIS_IN()\n", "```" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "deletable": false, "name": "question-2-2", "nbgrader": { "cell_type": "code", "checksum": "0559b11676385d14a6e6aeae20451199", "grade": false, "grade_id": "cell-dc9d534f13046219", "locked": false, "schema_version": 3, "solution": true, "task": false } }, "outputs": [], "source": [ "# Produce the plot\n", "# your code here\n", "fail() # No Answer - remove if you provide an answer\n", "print(answer2.0)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "deletable": false, "editable": false, "name": "test-2-2", "nbgrader": { "cell_type": "code", "checksum": "2e93e8ef6f9511914aa108c731c6d6a8", "grade": true, "grade_id": "cell-b008267739be5f55", "locked": true, "points": 1, "schema_version": 3, "solution": false, "task": false } }, "outputs": [], "source": [ "test_that(\"Question 2.0\", {\n", " expect_equal(as.character(rlang::get_expr(answer2.0$mapping$x)), \"month\")\n", " expect_equal(as.character(rlang::get_expr(answer2.0$mapping$y)), \"conc\")\n", " expect_true(\"GeomLine\" %in% class(answer2.0$layers[[1]]$geom))\n", "})" ] }, { "cell_type": "markdown", "metadata": { "deletable": false, "editable": false, "nbgrader": { "cell_type": "markdown", "checksum": "7757b42a5b223851f93d3c656386cc9b", "grade": false, "grade_id": "cell-fa034aa9eadc889b", "locked": true, "schema_version": 3, "solution": false, "task": false } }, "source": [ "## QUESTION 2.1\n", "\n", "You can store the output of the plot in a variable, too. The plot that you created in 2.0 is stored in the variable `answer2.0`. Add a layer to `answer2.0` that adds green points to the plot. (Not a pretty plot; just expository.)\n", "\n", "```\n", "answer2.1 <- answer2.0 +\n", " FILL_THIS_IN(colour = FILL_THIS_IN)\n", "```" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "deletable": false, "name": "question-2-4", "nbgrader": { "cell_type": "code", "checksum": "615de1e359a8919699aa7243b59e9051", "grade": false, "grade_id": "cell-d42834d6e87a400e", "locked": false, "schema_version": 3, "solution": true, "task": false } }, "outputs": [], "source": [ "# Produce your plot here. \n", "# your code here\n", "fail() # No Answer - remove if you provide an answer\n", "print(answer2.1)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "deletable": false, "editable": false, "name": "test-2-4", "nbgrader": { "cell_type": "code", "checksum": "227cbae407e53b8624becb4f4cd481d0", "grade": true, "grade_id": "cell-13c6834fe68d4a9f", "locked": true, "points": 1, "schema_version": 3, "solution": false, "task": false } }, "outputs": [], "source": [ "test_that(\"Question 2.1\", {\n", " expect_true(all(ggplot_build(answer2.1)$data[[2]]$colour == \"green\"))\n", "})" ] }, { "cell_type": "markdown", "metadata": { "deletable": false, "editable": false, "nbgrader": { "cell_type": "markdown", "checksum": "ca54cb9e0fba7a334a11aabe406b7e80", "grade": false, "grade_id": "cell-122ac8c8ab5644aa", "locked": true, "schema_version": 3, "solution": false, "task": false } }, "source": [ "## QUESTION 2.2\n", "\n", "Besides specifying the aesthetic mappings in the `ggplot()` function, you can also specify the aesthetic mappings in a `geom` layer instead of, or in addition to, in the `ggplot()` function, with the following rules:\n", "\n", "- Aesthetics appearing in a `geom` layer apply only to that layer.\n", "- If there are conflicting aesthetics in both the `ggplot()` function and the `geom` layer, the `geom` layer takes precedence.\n", "\n", "The following code mistakenly puts the month variable on the y-axis. Fill in the `FILL_THIS_IN` so that `conc` is on the y-axis (and month remains on the x-axis), but leave the rest of the code intact. Note what happens to the y-axis label, though! Store your answer in a variable named `answer2.2`\n", "\n", "```\n", "answer2.2 <- ggplot(mauna, aes(x = month, y = month)) +\n", " geom_point(FILL_THIS_IN)\n", "```" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "deletable": false, "name": "question-2-3", "nbgrader": { "cell_type": "code", "checksum": "f8409315a3a06f2438e4565fed4babb8", "grade": false, "grade_id": "cell-32eaa38bca33f44e", "locked": false, "schema_version": 3, "solution": true, "task": false } }, "outputs": [], "source": [ "# Produce the plot here.\n", "# your code here\n", "fail() # No Answer - remove if you provide an answer\n", "print(answer2.2)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "deletable": false, "editable": false, "name": "test-2-3", "nbgrader": { "cell_type": "code", "checksum": "4cf4c3327edbb18e98fb5d56dec7c8fd", "grade": true, "grade_id": "cell-f196a13adfd12bf2", "locked": true, "points": 1, "schema_version": 3, "solution": false, "task": false } }, "outputs": [], "source": [ "test_that(\"Question 2.2\", {\n", " expect_equal(as.character(rlang::get_expr(answer2.2$mapping$x)), \"month\")\n", " expect_equal(as.character(rlang::get_expr(answer2.2$mapping$y)), \"month\")\n", " expect_equal(as.character(rlang::get_expr(answer2.2$layers[[1]]$mapping$y)), \"conc\")\n", "})" ] }, { "cell_type": "markdown", "metadata": { "deletable": false, "editable": false, "nbgrader": { "cell_type": "markdown", "checksum": "65f2cc20cdf180b3c9986e934b90d83e", "grade": false, "grade_id": "cell-8198872191984be3", "locked": true, "schema_version": 3, "solution": false, "task": false } }, "source": [ "## QUESTION 2.3\n", "\n", "Can you fix what is wrong with the following code?\n", "\n", "```\n", "answer2.3 <- ggplot(gapminder) +\n", " geom_point(x = gdpPercap, y = lifeExp, alpha = 0.1)\n", "```" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "deletable": false, "name": "question-2-5", "nbgrader": { "cell_type": "code", "checksum": "9865846c59547dc4453a355c16e8cd3b", "grade": false, "grade_id": "cell-95c9249da0e6869e", "locked": false, "schema_version": 3, "solution": true, "task": false } }, "outputs": [], "source": [ "# Produce your plot here. \n", "# your code here\n", "fail() # No Answer - remove if you provide an answer\n", "print(answer2.3)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "deletable": false, "editable": false, "name": "test-2-5", "nbgrader": { "cell_type": "code", "checksum": "dc847be2f6fc30e2058186112d9df3c2", "grade": true, "grade_id": "cell-6595fa0ba46b2fc5", "locked": true, "points": 1, "schema_version": 3, "solution": false, "task": false } }, "outputs": [], "source": [ "test_that(\"Question 2.3\", {\n", " expect_true(\n", " as.character(rlang::get_expr(answer2.3$mapping$x)) == \"gdpPercap\" ||\n", " as.character(rlang::get_expr(answer2.3$layers[[1]]$mapping$x)) == \"gdpPercap\"\n", " )\n", " expect_true(\n", " as.character(rlang::get_expr(answer2.3$mapping$y)) == \"lifeExp\" ||\n", " as.character(rlang::get_expr(answer2.3$layers[[1]]$mapping$y)) == \"lifeExp\"\n", " )\n", "})" ] }, { "cell_type": "markdown", "metadata": { "deletable": false, "editable": false, "nbgrader": { "cell_type": "markdown", "checksum": "4014e5e344634c8d6d101e2c1b0e61f1", "grade": false, "grade_id": "cell-ddb61a5fe8365dca", "locked": true, "schema_version": 3, "solution": false, "task": false } }, "source": [ "## QUESTION 2.4\n", "\n", "The following mock dataset marks the (x,y) position of a caribou at four time points (be sure to execute the code in the following cell):" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "deletable": false, "editable": false, "nbgrader": { "cell_type": "code", "checksum": "f95776d94385b77d167a87da863549c3", "grade": false, "grade_id": "cell-739de2abb3036ab5", "locked": true, "schema_version": 3, "solution": false, "task": false } }, "outputs": [], "source": [ "caribou <- tribble(\n", " ~time, ~x, ~y,\n", " 4, 0.4, 0.5,\n", " 1, 0.3, 0.3,\n", " 2, 0.8, 0.7,\n", " 3, 0.5, 0.9\n", ")" ] }, { "cell_type": "markdown", "metadata": { "deletable": false, "editable": false, "nbgrader": { "cell_type": "markdown", "checksum": "2b589030975c7438601b458d33542578", "grade": false, "grade_id": "cell-931828ed4e2af073", "locked": true, "schema_version": 3, "solution": false, "task": false } }, "source": [ "Show the path of the caribou by connecting the dots ordered by time. Add an arrow with `arrow = arrow()` in the appropriate `geom` layer, and add the `time` label with `geom_text()`. Store the plot in a variable named `answer2.4`. \n", "\n", "```\n", "answer2.4 <- caribou %>% \n", " arrange(time) %>% \n", " ggplot(aes(FILL_THIS_IN)) + \n", " FILL_THIS_IN(FILL_THIS_IN) +\n", " geom_text(aes(FILL_THIS_IN), nudge_x = 0.02) +\n", " theme_minimal()\n", "```" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "deletable": false, "nbgrader": { "cell_type": "code", "checksum": "a1be537361a54cff5caece039d2bf199", "grade": false, "grade_id": "cell-12cdffdc7547201a", "locked": false, "schema_version": 3, "solution": true, "task": false } }, "outputs": [], "source": [ "# Produce the plot\n", "# your code here\n", "fail() # No Answer - remove if you provide an answer\n", "print(answer2.4)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "deletable": false, "editable": false, "nbgrader": { "cell_type": "code", "checksum": "4d6ab3401e2111ce8e22a37d5977995c", "grade": true, "grade_id": "cell-9894ed1bcd4691fc", "locked": true, "points": 1, "schema_version": 3, "solution": false, "task": false } }, "outputs": [], "source": [ "test_that(\"Question 2.4\", {\n", " expect_true(\n", " as.character(rlang::get_expr(answer2.4$mapping$x)) == \"x\" ||\n", " (as.character(rlang::get_expr(answer2.4$layers[[1]]$mapping$x)) == \"x\" && \n", " as.character(rlang::get_expr(answer2.4$layers[[2]]$mapping$x)) == \"x\")\n", " )\n", " expect_true(\n", " as.character(rlang::get_expr(answer2.4$mapping$y)) == \"y\" ||\n", " (as.character(rlang::get_expr(answer2.4$layers[[1]]$mapping$y)) == \"y\" && \n", " as.character(rlang::get_expr(answer2.4$layers[[2]]$mapping$y)) == \"y\")\n", " )\n", " geoms <- answer2.4$layers %>% \n", " map(\"geom\") %>% \n", " map(class) %>% \n", " map_chr(1)\n", " expect_true(\"GeomPath\" %in% geoms)\n", " expect_true(\"GeomText\" %in% geoms)\n", " expect_false(\"GeomLine\" %in% geoms)\n", " path_id <- which(geoms == \"GeomPath\")\n", " text_id <- which(geoms == \"GeomText\")\n", " expect_false(is.null(answer2.4$layers[[path_id]]$geom_params$arrow))\n", " expect_true(as.character(rlang::get_expr(answer2.4$layers[[text_id]]$mapping$label)) == \"time\")\n", "})" ] }, { "cell_type": "markdown", "metadata": { "deletable": false, "editable": false, "nbgrader": { "cell_type": "markdown", "checksum": "9f842e831746553b68f33863372ab3c6", "grade": false, "grade_id": "cell-d3cc588b86894ba2", "locked": true, "schema_version": 3, "solution": false, "task": false } }, "source": [ "## QUESTION 2.5\n", "\n", "Here's the number of people having a certain hair colour from a sample of 592 people (be sure to run the following code chunk):" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "deletable": false, "editable": false, "nbgrader": { "cell_type": "code", "checksum": "31480957351415897b7f3583d8dc6b12", "grade": false, "grade_id": "cell-df8babe03471bb86", "locked": true, "schema_version": 3, "solution": false, "task": false } }, "outputs": [], "source": [ "(hair <- as_tibble(HairEyeColor) %>% \n", " count(Hair, wt = n))" ] }, { "cell_type": "markdown", "metadata": { "deletable": false, "editable": false, "nbgrader": { "cell_type": "markdown", "checksum": "10b9251846b8655d8cb79645cd79c5d0", "grade": false, "grade_id": "cell-e8919e88967e0838", "locked": true, "schema_version": 3, "solution": false, "task": false } }, "source": [ "The following code fails at producing a bar chart that displays the counts on the y-axis. Fix the code.\n", "\n", "```\n", "answer2.5 <- ggplot(hair, aes(Hair, n)) +\n", " geom_bar()\n", "```\n", "\n", "Good to know: if you wanted `geom_bar` to specify a _proportion_ instead of a _count_ on the y-axis, you can do this by specifying `after_stat(prop)` as the y variable in your aesthetic mapping.\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "deletable": false, "nbgrader": { "cell_type": "code", "checksum": "3a03eb235821fdf2fe5a934ee7ed4eee", "grade": false, "grade_id": "cell-8f3800041b0b21c4", "locked": false, "schema_version": 3, "solution": true, "task": false } }, "outputs": [], "source": [ "# Produce the plot here. \n", "# your code here\n", "fail() # No Answer - remove if you provide an answer\n", "print(answer2.5)\n", "\n", "\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "deletable": false, "editable": false, "nbgrader": { "cell_type": "code", "checksum": "7dbae34ef0651fe9407226801b5e2d15", "grade": true, "grade_id": "cell-c033d7d6aa040126", "locked": true, "points": 1, "schema_version": 3, "solution": false, "task": false } }, "outputs": [], "source": [ "test_that(\"Question 2.5\", {\n", " geoms <- answer2.5$layers %>% \n", " map(\"geom\") %>% \n", " map(class) %>% \n", " map_chr(1)\n", " if (\"GeomBar\" %in% geoms) {\n", " layer <- answer2.5$layers[[\"GeomBar\" == geoms]]\n", " expect_true(get_expr(answer2.5$mapping$x) == \"Hair\" ||\n", " get_expr(layer$mapping$x) == \"Hair\")\n", " expect_true(get_expr(answer2.5$mapping$weight) == \"n\" ||\n", " get_expr(layer$mapping$weight) == \"n\")\n", " }\n", " if (\"GeomCol\" %in% geoms) {\n", " layer <- answer2.5$layers[[\"GeomCol\" == geoms]]\n", " expect_true(get_expr(answer2.5$mapping$x) == \"Hair\" ||\n", " get_expr(layer$mapping$x) == \"Hair\")\n", " expect_true(get_expr(answer2.5$mapping$y) == \"n\" ||\n", " get_expr(layer$mapping$y) == \"n\")\n", " }\n", " expect_false(\"GeomCol\" %in% geoms && \"GeomBar\" %in% geoms)\n", "})" ] }, { "cell_type": "markdown", "metadata": { "deletable": false, "editable": false, "nbgrader": { "cell_type": "markdown", "checksum": "f1bc110c4f9fa72abe9637ab615a7680", "grade": false, "grade_id": "cell-4d9cf6f3ed6e1fd6", "locked": true, "schema_version": 3, "solution": false, "task": false } }, "source": [ "## QUESTION 2.6\n", "\n", "Using the `penguins` dataset from the palmerpenguins package, suppose you want to visualize the number of penguins per island. It seems that a bar chart could be useful for this purpose. Give it a try! Hint: bar charts only need specifying one axis (use the x axis). Store your answer in a variable named `answer2.6`\n", "\n", "```\n", "answer2.6 <- ggplot(penguins, aes(FILL_THIS_IN)) + FILL_THIS_IN()\n", "```\n", "\n", "Good to know: if you wanted to colour the bars by sex, producing a side-by-side bar chart, then in addition to specifying the `fill = sex` aesthetic, just specify the `position = \"dodge\"` option within the geom that creates the bar." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "deletable": false, "name": "question-2-9", "nbgrader": { "cell_type": "code", "checksum": "e831b39c6acc935e55130620f78e9d61", "grade": false, "grade_id": "cell-b4567343484094b9", "locked": false, "schema_version": 3, "solution": true, "task": false } }, "outputs": [], "source": [ "# Produce your plot here. \n", "# your code here\n", "fail() # No Answer - remove if you provide an answer\n", "print(answer2.6)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "deletable": false, "editable": false, "name": "test-2-9", "nbgrader": { "cell_type": "code", "checksum": "ae1f0e25b5798c91b08ae806f54835fd", "grade": true, "grade_id": "cell-cc7004186fd3616e", "locked": true, "points": 1, "schema_version": 3, "solution": false, "task": false } }, "outputs": [], "source": [ "test_that(\"Question 2.6\", {\n", " expect_true(\n", " as.character(rlang::get_expr(answer2.6$mapping$x)) == \"island\" ||\n", " as.character(rlang::get_expr(answer2.6$layers[[1]]$mapping$x)) == \"island\"\n", " )\n", " expect_true(\n", " \"GeomBar\" %in% class(answer2.6$layers[[1]]$geom) ||\n", " \"GeomCol\" %in% class(answer2.6$layers[[1]]$geom)\n", " )\n", "})" ] }, { "cell_type": "markdown", "metadata": { "deletable": false, "editable": false, "nbgrader": { "cell_type": "markdown", "checksum": "ec5c5d07f1a2bad4128a0d5229f239da", "grade": false, "grade_id": "cell-2df8508a614b2a1f", "locked": true, "schema_version": 3, "solution": false, "task": false } }, "source": [ "Great job! FYI: sometimes it's useful to swap the axes, especially if the category (penguin) names are long. Here is another handy way to flip the coordinates, instead of plotting the graph again." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "deletable": false, "editable": false, "nbgrader": { "cell_type": "code", "checksum": "771634837ba1094c8e7434b98d4e0ed7", "grade": false, "grade_id": "cell-951a858de782b0bc", "locked": true, "schema_version": 3, "solution": false, "task": false } }, "outputs": [], "source": [ "answer2.6 + coord_flip()" ] }, { "cell_type": "markdown", "metadata": { "deletable": false, "editable": false, "nbgrader": { "cell_type": "markdown", "checksum": "ef404b36f499d25f6a1826f43480b241", "grade": false, "grade_id": "cell-3c3a0b0e9dca5855", "locked": true, "schema_version": 3, "solution": false, "task": false } }, "source": [ "## QUESTION 2.7\n", "\n", "In the `penguins` dataset from the palmerpenguins package, explore the relationship between flipper length and body mass (if any!). A scaffold of the ggplot2 recipe can be found below. Use the following parameters:\n", "\n", "- Flipper length should be on the x axis, and body mass should be on the y axis.\n", "- Color by species.\n", "- Set the size of the points to 3, and the alpha (transparency) to 0.8.\n", "\n", "Store the result in a variable named `answer2.7`\n", "\n", "```\n", "answer2.7 <- ggplot(FILL_THIS_IN, aes(FILL_THIS_IN, FILL_THIS_IN)) +\n", " geom_point(aes(color = FILL_THIS_IN),\n", " size = FILL_THIS_IN,\n", " alpha = FILL_THIS_IN) \n", "```" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "deletable": false, "name": "question-2-7", "nbgrader": { "cell_type": "code", "checksum": "b08f07b097f97dedd0620de58e2b267f", "grade": false, "grade_id": "cell-4ba9a5adab668e78", "locked": false, "schema_version": 3, "solution": true, "task": false } }, "outputs": [], "source": [ "# Produce your plot here. \n", "# your code here\n", "fail() # No Answer - remove if you provide an answer\n", "print(answer2.7)\n", "\n", "all(ggplot_build(answer2.7)$data[[1]]$alpha == 0.8)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "deletable": false, "editable": false, "name": "test-2-7", "nbgrader": { "cell_type": "code", "checksum": "e4efe0cc495fde997ca2e85b0496810b", "grade": true, "grade_id": "cell-e15d2ec7b140d6ed", "locked": true, "points": 1, "schema_version": 3, "solution": false, "task": false } }, "outputs": [], "source": [ "test_that(\"Question 2.7\", {\n", " expect_true(\n", " as.character(rlang::get_expr(answer2.7$mapping$x)) == \"flipper_length_mm\" ||\n", " as.character(rlang::get_expr(answer2.7$layers[[1]]$mapping$x)) == \"flipper_length_mm\"\n", " )\n", " expect_true(\n", " as.character(rlang::get_expr(answer2.7$mapping$y)) == \"body_mass_g\" ||\n", " as.character(rlang::get_expr(answer2.7$layers[[1]]$mapping$y)) == \"body_mass_g\"\n", " )\n", " expect_true(\n", " as.character(rlang::get_expr(answer2.7$mapping$colour)) == \"species\" ||\n", " as.character(rlang::get_expr(answer2.7$layers[[1]]$mapping$colour)) == \"species\"\n", " )\n", " expect_true(all(ggplot_build(answer2.7)$data[[1]]$alpha == 0.8))\n", " expect_true(all(ggplot_build(answer2.7)$data[[1]]$size == 3))\n", "})" ] }, { "cell_type": "markdown", "metadata": { "deletable": false, "editable": false, "nbgrader": { "cell_type": "markdown", "checksum": "5be611132c89f68b03a5ff572925a090", "grade": false, "grade_id": "cell-d0ed194b67c03bfd", "locked": true, "schema_version": 3, "solution": false, "task": false } }, "source": [ "## QUESTION 2.8\n", "\n", "Try the same as in 2.7 (flipper length vs. body mass), but this time coloring by island! See if you can write the code without looking at the last question. Store your answer in a variable named `answer2.8`\n", "\n", "```\n", "answer2.8 <- ggplot(FILL_THIS_IN, aes(FILL_THIS_IN, FILL_THIS_IN)) +\n", " geom_point(aes(color = FILL_THIS_IN),\n", " size = FILL_THIS_IN,\n", " alpha = FILL_THIS_IN) \n", "```" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "deletable": false, "name": "question-2-8", "nbgrader": { "cell_type": "code", "checksum": "4d48dae099543d43f9d448877b345174", "grade": false, "grade_id": "cell-e68ab5a4cf8e0418", "locked": false, "schema_version": 3, "solution": true, "task": false } }, "outputs": [], "source": [ "# Produce your plot here. \n", "# your code here\n", "fail() # No Answer - remove if you provide an answer\n", "plot(answer2.8)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "deletable": false, "editable": false, "name": "test-2-8", "nbgrader": { "cell_type": "code", "checksum": "fad07a01033861851864bd42cc1ad184", "grade": true, "grade_id": "cell-f2e828941518af29", "locked": true, "points": 1, "schema_version": 3, "solution": false, "task": false } }, "outputs": [], "source": [ "test_that(\"Question 2.8\", {\n", " expect_true(\n", " as.character(rlang::get_expr(answer2.8$mapping$x)) == \"flipper_length_mm\" ||\n", " as.character(rlang::get_expr(answer2.8$layers[[1]]$mapping$x)) == \"flipper_length_mm\"\n", " )\n", " expect_true(\n", " as.character(rlang::get_expr(answer2.8$mapping$y)) == \"body_mass_g\" ||\n", " as.character(rlang::get_expr(answer2.8$layers[[1]]$mapping$y)) == \"body_mass_g\"\n", " )\n", " expect_true(\n", " as.character(rlang::get_expr(answer2.8$mapping$colour)) == \"island\" ||\n", " as.character(rlang::get_expr(answer2.8$layers[[1]]$mapping$colour)) == \"island\"\n", " )\n", " expect_true(all(ggplot_build(answer2.8)$data[[1]]$alpha == 0.8))\n", " expect_true(all(ggplot_build(answer2.8)$data[[1]]$size == 3))\n", "})" ] }, { "cell_type": "markdown", "metadata": { "deletable": false, "editable": false, "nbgrader": { "cell_type": "markdown", "checksum": "aa641fe3a9c75152a908529add0226d5", "grade": false, "grade_id": "cell-c39ad510b6892d52", "locked": true, "schema_version": 3, "solution": false, "task": false } }, "source": [ "## QUESTION 2.9\n", "\n", "Maybe you want to explore the _distribution_ of body mass. Histograms are useful for this purpose.\n", "\n", "Make a histogram of penguin body mass, and store the result in a variable named `answer2.9`. But, instead of the height of the bars representing a _count_, have it represent the _density_ by specifying `after_stat(density)` as the y variable. \n", "\n", "```\n", "answer2.9 <- ggplot(FILL_THIS_IN, aes(FILL_THIS_IN)) +\n", " geom_histogram()\n", "```" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "deletable": false, "name": "question-2-10", "nbgrader": { "cell_type": "code", "checksum": "fe4743f863f68ed22ae2646f7e4ddb66", "grade": false, "grade_id": "cell-4095f01855b8c595", "locked": false, "schema_version": 3, "solution": true, "task": false } }, "outputs": [], "source": [ "# Produce your plot here. \n", "# your code here\n", "fail() # No Answer - remove if you provide an answer\n", "print(answer2.9)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "deletable": false, "editable": false, "name": "test-2-10", "nbgrader": { "cell_type": "code", "checksum": "6bf71747cb5677b474853fd728a59c71", "grade": true, "grade_id": "cell-bf5b8fd5f1bcc43b", "locked": true, "points": 1, "schema_version": 3, "solution": false, "task": false } }, "outputs": [], "source": [ "test_that(\"Question 2.9\", {\n", " expect_true(\n", " as.character(rlang::get_expr(answer2.9$mapping$x)) == \"body_mass_g\" ||\n", " as.character(rlang::get_expr(answer2.9$layers[[1]]$mapping$x)) == \"body_mass_g\"\n", " )\n", " expect_true(\n", " all(as.character(rlang::get_expr(answer2.9$mapping$y)) == c(\"after_stat\", \"density\")) || \n", " all(as.character(rlang::get_expr(answer2.9$layers[[1]]$mapping$y)) == c(\"after_stat\", \"density\"))\n", " )\n", " expect_true(\"GeomBar\" %in% class(answer2.9$layers[[1]]$geom))\n", "})" ] }, { "cell_type": "markdown", "metadata": { "deletable": false, "editable": false, "nbgrader": { "cell_type": "markdown", "checksum": "0cc223f9ba7e85f2a4998999d701556b", "grade": false, "grade_id": "cell-3e8f00ddb5f7db96", "locked": true, "schema_version": 3, "solution": false, "task": false } }, "source": [ "## QUESTION 2.10\n", "\n", "Another option for viewing distributions, besides histograms, is to plot the _kernel density function_. This geom can be achieved with `geom_density()`.\n", "\n", "Plot the density of body mass for each species. Distinguish species by colour (if you decide to use the `fill` aesthetic, be sure to add some alpha transparency). Store your answer in a variable named `answer2.10`.\n", "\n", "```\n", "answer2.10 <- ggplot(penguins, aes(x = FILL_THIS_IN)) + \n", " geom_density(FILL_THIS_IN)\n", "```" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "deletable": false, "name": "question-2-11", "nbgrader": { "cell_type": "code", "checksum": "76b2b478dd4a5a382e27340fb42d4383", "grade": false, "grade_id": "cell-74f35318290808f1", "locked": false, "schema_version": 3, "solution": true, "task": false } }, "outputs": [], "source": [ "# Produce your plot here. \n", "# your code here\n", "fail() # No Answer - remove if you provide an answer\n", "print(answer2.10)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "deletable": false, "editable": false, "name": "test-2-11", "nbgrader": { "cell_type": "code", "checksum": "e7b755f5ba16bcbaf30d28d085babcf3", "grade": true, "grade_id": "cell-e74c8cd01eea8f9c", "locked": true, "points": 1, "schema_version": 3, "solution": false, "task": false } }, "outputs": [], "source": [ "test_that(\"Question 2.10\", {\n", " expect_true(\n", " as.character(rlang::get_expr(answer2.10$mapping$x)) == \"body_mass_g\" ||\n", " as.character(rlang::get_expr(answer2.10$layers[[1]]$mapping$x)) == \"body_mass_g\"\n", " )\n", " \n", " suppressWarnings(\n", " expect_true(\n", " as.character(rlang::get_expr(answer2.10$mapping$colour)) == \"species\" ||\n", " as.character(rlang::get_expr(answer2.10$layers[[1]]$mapping$colour)) == \"species\" ||\n", " (\n", " (\n", " as.character(rlang::get_expr(answer2.10$mapping$fill)) == \"species\" ||\n", " as.character(rlang::get_expr(answer2.10$layers[[1]]$mapping$fill)) == \"species\"\n", " ) &&\n", " expect_true(all(!is.na(ggplot_build(answer2.10)$data[[1]]$alpha)))\n", " )\n", " )\n", " )\n", " \n", " expect_true(\"GeomDensity\" %in% class(answer2.10$layers[[1]]$geom))\n", "})" ] }, { "cell_type": "markdown", "metadata": { "deletable": false, "editable": false, "nbgrader": { "cell_type": "markdown", "checksum": "fdd70e5a9c2be4491d707423d6e21081", "grade": false, "grade_id": "cell-2ee18ac5e2f68687", "locked": true, "schema_version": 3, "solution": false, "task": false } }, "source": [ "## QUESTION 2.11\n", "\n", "Let's look at two more types of plot to once again explore the relationship between body mass and penguin species. Stripplots are univariate scatterplots, and they are a useful way of visualizing how, in this case, body mass is spread within each species.\n", "\n", "The large amount of overlapping points in the following plot makes it hard to to visualize distributions. Change the plot to a _jitterplot_ by using a different `geom`. Tip: use `width = 0.1` so that the points don't jitter too far away.\n", "\n", "```\n", "answer2.11 <- ggplot(penguins, aes(species, body_mass_g)) + \n", " geom_point(alpha = 0.5)\n", "```" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "deletable": false, "name": "question-2-12", "nbgrader": { "cell_type": "code", "checksum": "4b116258306b15b34db8d5882bc6ba3c", "grade": false, "grade_id": "cell-520bf151ca9cc28b", "locked": false, "schema_version": 3, "solution": true, "task": false } }, "outputs": [], "source": [ "# Produce the plot here. \n", "# your code here\n", "fail() # No Answer - remove if you provide an answer\n", "print(answer2.11)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "deletable": false, "editable": false, "name": "test-2-12", "nbgrader": { "cell_type": "code", "checksum": "aad4c848ad16d59a1c41ce245b193982", "grade": true, "grade_id": "cell-7adad7a8b2bcf435", "locked": true, "points": 1, "schema_version": 3, "solution": false, "task": false } }, "outputs": [], "source": [ "test_that(\"Question 2.11\", {\n", " expect_true(\n", " as.character(rlang::get_expr(answer2.11$mapping$x)) == \"species\" ||\n", " as.character(rlang::get_expr(answer2.11$layers[[1]]$mapping$x)) == \"species\"\n", " )\n", " expect_true(\n", " as.character(rlang::get_expr(answer2.11$mapping$y)) == \"body_mass_g\" ||\n", " as.character(rlang::get_expr(answer2.11$layers[[1]]$mapping$y)) == \"body_mass_g\"\n", " ) \n", " expect_true(\"GeomPoint\" %in% class(answer2.11$layers[[1]]$geom))\n", " expect_true(\"PositionJitter\" %in% class(answer2.11$layers[[1]]$position))\n", "})" ] }, { "cell_type": "markdown", "metadata": { "deletable": false, "editable": false, "nbgrader": { "cell_type": "markdown", "checksum": "996d1d330c42fd060276fbc2a5357b0a", "grade": false, "grade_id": "cell-cbd4aedbc68ca1cd", "locked": true, "schema_version": 3, "solution": false, "task": false } }, "source": [ "## QUESTION 2.12\n", "\n", "Boxplots are another approach for visualizing distributions. Reproduce the plot in Question 2.11, but as boxplots instead of stripplots. Do so by filling in the following scaffolding. Hint: there's a `geom` for boxplots. Tip: as in the jitterplots, we recommend changing the width of the boxplots, too -- say `width = 0.2`. \n", "\n", "```\n", "answer2.12 <- ggplot(FILL_THIS_IN, aes(FILL_THIS_IN, FILL_THIS_IN)) + \n", " FILL_THIS_IN(width = 0.2)\n", "```" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "deletable": false, "name": "question-2-13", "nbgrader": { "cell_type": "code", "checksum": "1a1b6417b025579b67e7663001b42137", "grade": false, "grade_id": "cell-93e1df4dfca6935b", "locked": false, "schema_version": 3, "solution": true, "task": false } }, "outputs": [], "source": [ "# Produce your plot here. \n", "# your code here\n", "fail() # No Answer - remove if you provide an answer\n", "print(answer2.12)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "deletable": false, "editable": false, "name": "test-2-13", "nbgrader": { "cell_type": "code", "checksum": "de6ea09d523d3a97b413c561176c6a71", "grade": true, "grade_id": "cell-15cf5e7794b5146a", "locked": true, "points": 1, "schema_version": 3, "solution": false, "task": false } }, "outputs": [], "source": [ "test_that(\"Question 2.12\", {\n", " expect_true(\n", " as.character(rlang::get_expr(answer2.12$mapping$x)) == \"species\" ||\n", " as.character(rlang::get_expr(answer2.12$layers[[1]]$mapping$x)) == \"species\"\n", " )\n", " expect_true(\n", " as.character(rlang::get_expr(answer2.12$mapping$y)) == \"body_mass_g\" ||\n", " as.character(rlang::get_expr(answer2.12$layers[[1]]$mapping$y)) == \"body_mass_g\"\n", " ) \n", " expect_true(\"GeomBoxplot\" %in% class(answer2.12$layers[[1]]$geom))\n", "})" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## QUESTION 2.13\n", "\n", "Yet another way to plot distributions is to stack multiple kernel density estimates across different categories on the y-axis. The effect is like viewing a mountain range from an airplane.\n", "\n", "Plot the distribution of life expectancy for European countries, using a ridge plot, by filling in the following scaffolding. Hint: use the `geom_density_ridges()` geom from the ggridges package. \n", "\n", "(Sure, the life expectancies associated with a country are observed over time, and are definitely not \"iid\" in the statistical sense, yet this plot still has value.)\n", "\n", "```\n", "answer2.13 <- gapminder %>% \n", " filter(continent == \"Europe\") %>% \n", " ggplot(aes(FILL_THIS_IN, FILL_THIS_IN)) +\n", " ggridges::FILL_THIS_IN()\n", "```" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "deletable": false, "nbgrader": { "cell_type": "code", "checksum": "feb40cc5101cdf62c5f4414d61a405da", "grade": false, "grade_id": "cell-a6c76422069687b6", "locked": false, "schema_version": 3, "solution": true, "task": false } }, "outputs": [], "source": [ "# Produce the plot here. \n", "# your code here\n", "fail() # No Answer - remove if you provide an answer\n", "print(answer2.13)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "deletable": false, "editable": false, "nbgrader": { "cell_type": "code", "checksum": "84c3ec556d57d4b0ffd28ab191df042f", "grade": true, "grade_id": "cell-d360cff0a96a9161", "locked": true, "points": 1, "schema_version": 3, "solution": false, "task": false } }, "outputs": [], "source": [ "test_that(\"Question 2.13\", {\n", " geoms <- answer2.13$layers %>% \n", " map(\"geom\") %>% \n", " map(class) %>% \n", " map_chr(1)\n", " expect_true(\"GeomDensityRidges\" %in% geoms)\n", " layer <- answer2.13$layers[[\"GeomDensityRidges\" == geoms]]\n", " expect_true(get_expr(answer2.13$mapping$x) == \"lifeExp\" ||\n", " get_expr(layer$mapping$x) == \"lifeExp\")\n", " expect_true(get_expr(answer2.13$mapping$y) == \"country\" ||\n", " get_expr(layer$mapping$y) == \"country\")\n", "})" ] }, { "cell_type": "markdown", "metadata": { "deletable": false, "editable": false, "nbgrader": { "cell_type": "markdown", "checksum": "8d7cb9bbc734c40b5a6052b775839922", "grade": false, "grade_id": "cell-aa9543ec02f0d2e6", "locked": true, "schema_version": 3, "solution": false, "task": false } }, "source": [ "## QUESTION 2.14\n", "\n", "The code below produces a scatterplot of GDP per capita against life expectancy, with points coloured by continent. But, it's hard to distinguish between continents. Modify the plot so that continents are separated into their own panels (hint: use facetting).\n", "\n", "Tip: Change the x-axis text to be in \"dollar format\" with `labels = scales::dollar_format()` when specifying the scale. \n", "\n", "```\n", "answer2.14 <- gapminder %>%\n", " ggplot(aes(gdpPercap, lifeExp, colour = continent)) +\n", " geom_point(alpha = 0.2) +\n", " scale_x_log10()\n", "```" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "deletable": false, "nbgrader": { "cell_type": "code", "checksum": "8cb90beff1258e8cf55a4a906ff6a471", "grade": false, "grade_id": "cell-9ee5da2d49d01716", "locked": false, "schema_version": 3, "solution": true, "task": false } }, "outputs": [], "source": [ "# your code here\n", "fail() # No Answer - remove if you provide an answer\n", "print(answer2.14)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "deletable": false, "editable": false, "nbgrader": { "cell_type": "code", "checksum": "fd9d4f4be13b4082ef3faf30e8ce1b93", "grade": true, "grade_id": "cell-40960cdcc5c1b968", "locked": true, "points": 1, "schema_version": 3, "solution": false, "task": false } }, "outputs": [], "source": [ "test_that(\"Answer 2.14\", {\n", " expect_equal(names(answer2.14$facet$params$facets), \"continent\")\n", "})" ] }, { "cell_type": "markdown", "metadata": { "deletable": false, "editable": false, "nbgrader": { "cell_type": "markdown", "checksum": "0ff003e00069e87e6d70f119a9616c5d", "grade": false, "grade_id": "cell-9db267e502962c72", "locked": true, "schema_version": 3, "solution": false, "task": false } }, "source": [ "# Part 3: Fix the plots!\n", "\n", "In this section, we'll be looking at some erroneous plots and fixing them." ] }, { "cell_type": "markdown", "metadata": { "deletable": false, "editable": false, "nbgrader": { "cell_type": "markdown", "checksum": "1e5bdd063d76adfcb288710da397a9fb", "grade": false, "grade_id": "cell-cca88c9f7fd3160c", "locked": true, "schema_version": 3, "solution": false, "task": false } }, "source": [ "## QUESTION 3.0\n", "\n", "Besides alpha transparency, we can fix the issue of overlapping points by making the points smaller. The following code fails to reduce the point size to 0.1 -- can you fix it?\n", "\n", "\n", "```\n", "answer3.0 <- ggplot(gapminder) +\n", " geom_point(aes(gdpPercap, lifeExp, size = 0.1)) +\n", " scale_x_log10(labels = scales::dollar_format())\n", "```" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "deletable": false, "nbgrader": { "cell_type": "code", "checksum": "0715523d3178dcd12b1b1d5d253e4cb9", "grade": false, "grade_id": "cell-b28ea46f0e6cce0d", "locked": false, "schema_version": 3, "solution": true, "task": false } }, "outputs": [], "source": [ "# your code here\n", "fail() # No Answer - remove if you provide an answer\n", "print(answer3.0)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "deletable": false, "editable": false, "nbgrader": { "cell_type": "code", "checksum": "b897024639fd4e7c1aebf76664a8c476", "grade": true, "grade_id": "cell-1bb9ffe3e12eea95", "locked": true, "points": 1, "schema_version": 3, "solution": false, "task": false } }, "outputs": [], "source": [ "test_that(\"Answer 3.0\", {\n", " expect_false(\"size\" %in% names(answer3.0$layers[[1]]$mapping))\n", " expect_true(all(ggplot_build(answer3.0)$data[[1]]$size == 0.1))\n", "})" ] }, { "cell_type": "markdown", "metadata": { "deletable": false, "editable": false, "nbgrader": { "cell_type": "markdown", "checksum": "7d4ffbbea3b0863cf7322fb3b113efe8", "grade": false, "grade_id": "cell-6422befdf23b20c8", "locked": true, "schema_version": 3, "solution": false, "task": false } }, "source": [ "## QUESTION 3.1\n", "\n", "Fix the plot so that the size of the dots is related to the body mass, and so that the dots are colored by species.\n", "\n", "Assign your answer to a variable named `answer3.1`.\n", "\n", "```\n", "answer3.1 <- ggplot(penguins, aes(x = body_mass_g, y = flipper_length_mm) +\n", " geom_point(shape = 21,\n", " size = species,\n", " fill = island))\n", "``` " ] }, { "cell_type": "code", "execution_count": null, "metadata": { "deletable": false, "nbgrader": { "cell_type": "code", "checksum": "1eff8a2a5cf4de125ab8f7518e44f177", "grade": false, "grade_id": "cell-9aa8029613c3c82a", "locked": false, "schema_version": 3, "solution": true, "task": false } }, "outputs": [], "source": [ "# your code here\n", "fail() # No Answer - remove if you provide an answer\n", "print(answer3.1)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "deletable": false, "editable": false, "nbgrader": { "cell_type": "code", "checksum": "5fb5258bb91fd036f8b1936d40fe843c", "grade": true, "grade_id": "cell-86ff95a18e8ad74d", "locked": true, "points": 1, "schema_version": 3, "solution": false, "task": false } }, "outputs": [], "source": [ "test_that(\"Answer 3.1\", {\n", " expect_true(\"x\" %in% names(answer3.1$mapping) || \"x\" %in% names(answer3.1$layers[[1]]$mapping))\n", " expect_true(\"y\" %in% names(answer3.1$mapping) || \"y\" %in% names(answer3.1$layers[[1]]$mapping))\n", " expect_true(\"size\" %in% names(answer3.1$mapping) || \"size\" %in% names(answer3.1$layers[[1]]$mapping))\n", " expect_true(\"fill\" %in% names(answer3.1$mapping) || \"fill\" %in% names(answer3.1$layers[[1]]$mapping))\n", "})" ] }, { "cell_type": "markdown", "metadata": { "deletable": false, "editable": false, "nbgrader": { "cell_type": "markdown", "checksum": "331192db497e43d94afc7df496425e36", "grade": false, "grade_id": "cell-ee84ea7696e7ad0a", "locked": true, "schema_version": 3, "solution": false, "task": false } }, "source": [ "## QUESTION 3.2\n", "\n", "Using the `penguins` dataset from the palmerpenguins package, the following code aims to view the relationship between flipper length (X) and body mass (Y) for each species (facet), by sex (colour). Fix the mistake in the code. \n", "\n", "```\n", "answer3.2 <- ggplot(penguins, aes(flipper_length_mm, body_mass_g, facet = species)) +\n", " geom_point(aes(color = sex),\n", " size = 3,\n", " alpha = 0.8) +\n", " theme_minimal() +\n", " facet_wrap(~ species)\n", "```" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "deletable": false, "nbgrader": { "cell_type": "code", "checksum": "a85c276c01336b99103809fde7fbb42e", "grade": false, "grade_id": "cell-20b4487e862f40c9", "locked": false, "schema_version": 3, "solution": true, "task": false } }, "outputs": [], "source": [ "# your code here\n", "fail() # No Answer - remove if you provide an answer\n", "print(answer3.2)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "deletable": false, "editable": false, "nbgrader": { "cell_type": "code", "checksum": "5b5d186e991ae4ac21f26bc70b6c38b0", "grade": true, "grade_id": "cell-ae29c516f77ef8f6", "locked": true, "points": 1, "schema_version": 3, "solution": false, "task": false } }, "outputs": [], "source": [ "test_that(\"Answer 3.2\", {\n", " expect_true(\"sex\" %in% as_label(answer3.2$mapping$colour) | \n", " \"sex\" %in% as_label(answer3.2$layers[[1]]$mapping$colour))\n", " expect_true(\"flipper_length_mm\" %in% as_label(answer3.2$mapping$x) | \n", " \"flipper_length_mm\" %in% as_label(answer3.2$layers[[1]]$mapping$x))\n", " expect_true(\"body_mass_g\" %in% as_label(answer3.2$mapping$y) | \n", " \"body_mass_g\" %in% as_label(answer3.2$layers[[1]]$mapping$y))\n", " expect_true(all(ggplot_build(answer3.2)$data[[1]]$size == 3))\n", " expect_true(all(ggplot_build(answer3.2)$data[[1]]$alpha == 0.8))\n", " expect_equal(names(answer3.2$facet$params$facets), \"species\")\n", "})" ] }, { "cell_type": "markdown", "metadata": { "deletable": false, "editable": false, "nbgrader": { "cell_type": "markdown", "checksum": "6916875f8ea97643483d9d05ae858493", "grade": false, "grade_id": "cell-f62fcb99be07874a", "locked": true, "schema_version": 3, "solution": false, "task": false } }, "source": [ "## QUESTION 3.3\n", "\n", "The following plot is a failed attempt at plotting each country's life expectancy over time, so that each country gets its own line. To plot multiple lines in one graph, we need to group by country -- but aren't we doing that in the second line? Fix the code. \n", "\n", "```\n", "answer3.3 <- gapminder %>% \n", " group_by(country) %>% \n", " ggplot(aes(year, lifeExp)) +\n", " facet_wrap(~ continent) +\n", " geom_line(alpha = 0.2) +\n", " theme_minimal()\n", "```" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "deletable": false, "nbgrader": { "cell_type": "code", "checksum": "a7fcccbebd08ea3e963c795da0a00c61", "grade": false, "grade_id": "cell-7389d0040fd8bd0e", "locked": false, "schema_version": 3, "solution": true, "task": false } }, "outputs": [], "source": [ "# Produce the plot here. \n", "# your code here\n", "fail() # No Answer - remove if you provide an answer\n", "print(answer3.3)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "deletable": false, "editable": false, "nbgrader": { "cell_type": "code", "checksum": "75b632bd53418c9e8c184dad0509c02a", "grade": true, "grade_id": "cell-fca60e03990c3406", "locked": true, "points": 1, "schema_version": 3, "solution": false, "task": false } }, "outputs": [], "source": [ "test_that(\"Question 3.3\", {\n", " geoms <- answer3.3$layers %>% \n", " map(\"geom\") %>% \n", " map(class) %>% \n", " map_chr(1)\n", " expect_true(\"GeomLine\" %in% geoms)\n", " layer <- answer3.3$layers[[\"GeomLine\" == geoms]]\n", " expect_true(get_expr(answer3.3$mapping$group) == \"country\" ||\n", " get_expr(layer$mapping$group) == \"country\")\n", "})" ] }, { "cell_type": "markdown", "metadata": { "deletable": false, "editable": false, "nbgrader": { "cell_type": "markdown", "checksum": "0a27099465b6715d1f4d5b48b6b5be38", "grade": false, "grade_id": "cell-88aed5be2e42237a", "locked": true, "schema_version": 3, "solution": false, "task": false } }, "source": [ "# Part 4: Challenges (_Not for points_)\n", "\n", "Use your creativity to produce plots for the following situations. This is not for points. Suggested solutions are provided in Part 5. Note that you may need to incorporate data manipulation here.\n", "\n", "## QUESTION 4.0\n", "\n", "Using the `gapminder` dataset: for each continent, how does the number of countries having a \"low\" life expectancy change across time? Let's say life expectancy is \"low\" if it's less than its continent's median life expectancy as observed on the latest year (2007) in the gapminder dataset." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# Your code here. " ] }, { "cell_type": "markdown", "metadata": { "deletable": false, "editable": false, "nbgrader": { "cell_type": "markdown", "checksum": "404bd477b01585eb03e2682f5808f28c", "grade": false, "grade_id": "cell-1932864a643c4808", "locked": true, "schema_version": 3, "solution": false, "task": false } }, "source": [ "## QUESTION 4.1\n", "\n", "From Question 3.3:\n", "\n", "> The following plot is a failed attempt at plotting each country's life expectancy over time, so that each country gets its own line. To plot multiple lines in one graph, we need to group by country -- but aren't we doing that in the second line? Fix the code. \n", "\n", "```\n", "answer3.3 <- gapminder %>% \n", " group_by(country) %>% \n", " ggplot(aes(year, lifeExp)) +\n", " facet_wrap(~ continent) +\n", " geom_line(alpha = 0.2) +\n", " theme_minimal()\n", "```\n", "\n", "In addition: \n", "\n", "1. Produce a band representing the 80% prediction interval of life expectancies for each continent and each year. _Hint_: use Base R's `quantile()` function with `probs = 0.9` and `probs = 0.1` to produce the upper and lower bands, and use `geom_ribbon()` as your geometric object. \n", "2. Drop Oceania, as it only has two countries on record (so a prediction interval wouldn't make much sense)." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# Your code here. " ] }, { "cell_type": "markdown", "metadata": { "deletable": false, "editable": false, "nbgrader": { "cell_type": "markdown", "checksum": "260a6bee9c21f72baaaceba75658c3c9", "grade": false, "grade_id": "cell-c553da022c3457c0", "locked": true, "schema_version": 3, "solution": false, "task": false } }, "source": [ "## QUESTION 4.2\n", "\n", "From the gapminder dataset, was a drop in life expectancy just as likely for any year, or were some years more prone to see a drop than others? " ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# Your code here" ] }, { "cell_type": "markdown", "metadata": { "deletable": false, "editable": false, "nbgrader": { "cell_type": "markdown", "checksum": "5dfe6891357c88c93ea797e254e3c83a", "grade": false, "grade_id": "cell-9a951c572e7e021e", "locked": true, "schema_version": 3, "solution": false, "task": false } }, "source": [ "## QUESTION 4.3\n", "\n", "Using the gapminder dataset, how has the distribution of GDP per capita (across countries) changed over time for each continent?" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# Your code here" ] }, { "cell_type": "markdown", "metadata": { "deletable": false, "editable": false, "nbgrader": { "cell_type": "markdown", "checksum": "7eb18aa0342ea5a7afff9d1119541226", "grade": false, "grade_id": "cell-32ba7c56ae4f6755", "locked": true, "schema_version": 3, "solution": false, "task": false } }, "source": [ "# Part 5: Suggested Solutions to Part 4\n", "\n", "## Suggested Answer to QUESTION 4.0\n", "\n", "> Using the `gapminder` dataset: for each continent, how does the number of countries having a \"low\" life expectancy change across time? Let's say life expectancy is \"low\" if it's less than its continent's median life expectancy as observed on the latest year (2007) in the gapminder dataset." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "deletable": false, "editable": false, "nbgrader": { "cell_type": "code", "checksum": "2fb9b3ad3c860541b1db65d963ac8e25", "grade": false, "grade_id": "cell-80276eb03aa2a6b5", "locked": true, "schema_version": 3, "solution": false, "task": false } }, "outputs": [], "source": [ "gapminder %>% \n", " group_by(continent, year) %>%\n", " mutate(median = median(lifeExp)) %>% \n", " ungroup(year) %>% \n", " arrange(year) %>% \n", " filter(lifeExp < last(median)) %>% \n", " count(continent, year) %>% \n", " ggplot(aes(year, n)) +\n", " geom_line(aes(colour = continent)) +\n", " ylab(\"# of countries with low lifeExp\") +\n", " scale_x_continuous(\"\") +\n", " scale_colour_discrete(\"\") +\n", " theme_minimal()" ] }, { "cell_type": "markdown", "metadata": { "deletable": false, "editable": false, "nbgrader": { "cell_type": "markdown", "checksum": "c913dc542f8a48f8ad74e037731fdd83", "grade": false, "grade_id": "cell-e5a24318502104dd", "locked": true, "schema_version": 3, "solution": false, "task": false } }, "source": [ "## Suggested Answer to QUESTION 4.1\n", "\n", "> From Question 3.3:\n", "> \n", "> > The following plot is a failed attempt at plotting each country's life expectancy over time, so that each country gets its own line. To plot multiple lines in one graph, we need to group by country -- but aren't we doing that in the second line? Fix the code. \n", "> \n", "> ```\n", "answer3.3 <- gapminder %>% \n", " group_by(country) %>% \n", " ggplot(aes(year, lifeExp)) +\n", " facet_wrap(~ continent) +\n", " geom_line(alpha = 0.2) +\n", " theme_minimal()\n", "> ```\n", "> \n", "> In addition: \n", "> \n", "> 1. Produce a band representing the 80% prediction interval of life expectancies for each continent and each year. _Hint_: use Base R's `quantile()` function with `probs = 0.9` and `probs = 0.1` to produce the upper and lower bands, and use `geom_ribbon()` as your geometric object. \n", "> 2. Drop Oceania, as it only has two countries on record (so a prediction interval wouldn't make much sense)." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "deletable": false, "editable": false, "nbgrader": { "cell_type": "code", "checksum": "e9ef3a5493a1cffa6b8b7db54bdf8da1", "grade": false, "grade_id": "cell-a4bf76ba17ca73d8", "locked": true, "schema_version": 3, "solution": false, "task": false } }, "outputs": [], "source": [ "gapminder %>% \n", " filter(continent != \"Oceania\") %>% \n", " group_by(continent, year) %>% \n", " mutate(upper = quantile(gdpPercap, 0.9), \n", " lower = quantile(gdpPercap, 0.1)) %>% \n", " ggplot(aes(year, gdpPercap)) +\n", " geom_ribbon(aes(ymin = lower, ymax = upper), alpha = 2 / 3, fill = \"gray\") +\n", " geom_line(aes(group = country, colour = continent), alpha = 1 / 4) +\n", " facet_wrap(~ continent) +\n", " scale_y_log10(\"GDP Per Capita\", labels = scales::dollar_format()) +\n", " guides(colour = FALSE) +\n", " theme_bw()" ] }, { "cell_type": "markdown", "metadata": { "deletable": false, "editable": false, "nbgrader": { "cell_type": "markdown", "checksum": "5c9c1f424cbcf3959bb351e5d69ab182", "grade": false, "grade_id": "cell-e52421a9dfba0fa3", "locked": true, "schema_version": 3, "solution": false, "task": false } }, "source": [ "## Suggested Answer to QUESTION 4.2\n", "\n", "> From the gapminder dataset, was a drop in life expectancy just as likely for any year, or were some years more prone to see a drop than others? " ] }, { "cell_type": "code", "execution_count": null, "metadata": { "deletable": false, "editable": false, "nbgrader": { "cell_type": "code", "checksum": "a060d2b07deed1f32c09b0b28b4dd3bc", "grade": false, "grade_id": "cell-7c3a08a2f62191bd", "locked": true, "schema_version": 3, "solution": false, "task": false } }, "outputs": [], "source": [ "gapminder %>% \n", " group_by(country) %>% \n", " arrange(year) %>% \n", " mutate(inc = lifeExp - lag(lifeExp)) %>% \n", " filter(inc < 0) %>% \n", " ggplot(aes(year)) +\n", " geom_bar() +\n", " theme_minimal() +\n", " ylab(\"Number of countries with a\\ndrop in life expectancy\")" ] }, { "cell_type": "markdown", "metadata": { "deletable": false, "editable": false, "nbgrader": { "cell_type": "markdown", "checksum": "7773d022df0c83589a855d7627778d4e", "grade": false, "grade_id": "cell-377ad6975173a6ce", "locked": true, "schema_version": 3, "solution": false, "task": false } }, "source": [ "## Suggested Answer to QUESTION 4.3\n", "\n", "> Using the gapminder dataset, how has the distribution of GDP per capita (across countries) changed over time for each continent?\n", "\n", "A plot like the one below might need some buildup before presenting it to an audience. Or, consider facetting. " ] }, { "cell_type": "code", "execution_count": null, "metadata": { "deletable": false, "editable": false, "nbgrader": { "cell_type": "code", "checksum": "0d326195b0ba7b6ab5b2f3d6b83e94e8", "grade": false, "grade_id": "cell-a3c366ae52f40bc3", "locked": true, "schema_version": 3, "solution": false, "task": false } }, "outputs": [], "source": [ "gapminder %>% \n", " filter(continent != \"Oceania\") %>% \n", " ggplot(aes(gdpPercap, factor(year))) +\n", " ggridges::geom_density_ridges(aes(fill = continent), alpha = 1/3) +\n", " scale_x_log10(\"GDP per capita\", labels = scales::dollar_format()) +\n", " ylab(\"Year\") +\n", " theme_minimal() +\n", " scale_fill_discrete(\"\")" ] }, { "cell_type": "markdown", "metadata": { "deletable": false, "editable": false, "nbgrader": { "cell_type": "markdown", "checksum": "8913bf292769bf5fd8bb7c1bdc278955", "grade": false, "grade_id": "cell-d73e90e3fb207ed9", "locked": true, "schema_version": 3, "solution": false, "task": false } }, "source": [ "## Attribution\n", "\n", "Thanks to Icíar Fernández Boyano, Victor Yuan, and Vincenzo Coia for putting this worksheet together.\n", "\n", "The following resources were used as inspiration in the creation of this worksheet:\n", "\n", "+ [R4DS Data Manipulation Chapter](https://r4ds.had.co.nz/transform.html)\n", "+ [Rebecca Barter's post on across()](http://www.rebeccabarter.com/blog/2020-07-09-across/)\n", "+ STAT545 materials from previous years \n", "+ [Palmer penguins dataset](https://allisonhorst.github.io/palmerpenguins/articles/examples.html)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "R", "language": "R", "name": "ir" }, "language_info": { "codemirror_mode": "r", "file_extension": ".r", "mimetype": "text/x-r-source", "name": "R", "pygments_lexer": "r", "version": "4.3.1" } }, "nbformat": 4, "nbformat_minor": 4 }