{ "cells": [ { "cell_type": "markdown", "metadata": { "deletable": false, "editable": false, "nbgrader": { "cell_type": "markdown", "checksum": "8133343ab443b8f352f401d833a27484", "grade": false, "grade_id": "cell-5a1648d1099b8d76", "locked": true, "schema_version": 3, "solution": false, "task": false } }, "source": [ "# Worksheet B-2: Strings and Regular Expressions\n", "\n", "\n", "In this tutorial, you'll practice how to:\n", "\n", "- Manipulate a character vector in R using the stringr package.\n", "- Write simple regular expressions (regex).\n", "- Apply regular expressions to data manipulation.\n", "\n", "Load the requirements for this worksheet:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "deletable": false, "editable": false, "lines_to_next_cell": 2, "message": false, "nbgrader": { "cell_type": "code", "checksum": "7e25c87a59f623a346af50073d902483", "grade": false, "grade_id": "cell-af848431e3f81a1f", "locked": true, "schema_version": 3, "solution": false, "task": false }, "warning": false }, "outputs": [], "source": [ "suppressPackageStartupMessages(library(tidyverse))\n", "suppressPackageStartupMessages(library(gapminder))\n", "suppressPackageStartupMessages(library(testthat))\n", "suppressPackageStartupMessages(library(digest))" ] }, { "cell_type": "markdown", "metadata": { "deletable": false, "editable": false, "nbgrader": { "cell_type": "markdown", "checksum": "bbd874af890a71fdea169cac77ff5708", "grade": false, "grade_id": "cell-c454cfe3b9eb71c8", "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": { "deletable": false, "editable": false, "nbgrader": { "cell_type": "code", "checksum": "3e3bd34313b0495214eaa25a27ed9e14", "grade": false, "grade_id": "cell-6884214b97e12c4d", "locked": true, "schema_version": 3, "solution": false, "task": false } }, "outputs": [], "source": [ "# An unlocked code chunk." ] }, { "cell_type": "markdown", "metadata": { "deletable": false, "editable": false, "nbgrader": { "cell_type": "markdown", "checksum": "84d708a28db6692de6d7b09b44d8a79d", "grade": false, "grade_id": "cell-f13d49ed5f0c8271", "locked": true, "schema_version": 3, "solution": false, "task": false } }, "source": [ "# Part 1: Warming up to the stringr functions\n", "\n", "\n", "## Question 1\n", "\n", "There's that famous sentence about the \"quick fox\" that contains all letters of the alphabet, although we don't quite remember the sentence. Obtain a vector of all sentences from the `stringr::sentences` dataset containing the word `\"fox\"`. Store the resulting vector in a variable named `answer1`.\n", "\n", "```\n", "answer1 <- str_subset(FILL_THIS_IN, FILL_THIS_IN)\n", "```" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "deletable": false, "lines_to_next_cell": 0, "nbgrader": { "cell_type": "code", "checksum": "7ff223abe6b9643640add72b73b3ff7f", "grade": false, "grade_id": "cell-a58e8d689deb018c", "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(answer1)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "deletable": false, "editable": false, "nbgrader": { "cell_type": "code", "checksum": "e93e873b14175af702ef881811ee7b4b", "grade": true, "grade_id": "cell-db0455c89d6a2069", "locked": true, "points": 1, "schema_version": 3, "solution": false, "task": false } }, "outputs": [], "source": [ "test_that(\"Question 1\", {\n", " expect_identical(digest(answer1), \"b54efc522343ff2628fee7e71bd17747\")\n", "})" ] }, { "cell_type": "markdown", "metadata": { "deletable": false, "editable": false, "nbgrader": { "cell_type": "markdown", "checksum": "b39cf99a42f570d3fc8dcc5c16b36af3", "grade": false, "grade_id": "cell-4870f5e5546e7b57", "locked": true, "schema_version": 3, "solution": false, "task": false } }, "source": [ "## Question 2\n", "\n", "Make an (atomic) vector of the individual words in the sentence. Store the result in a variable named `answer2`.\n", "\n", "Hint: Use `str_split(string, pattern)`, and carefully note what the output of this function is." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "deletable": false, "nbgrader": { "cell_type": "code", "checksum": "d1e1fd40f516c1c5ab405fc9fcfc20bf", "grade": false, "grade_id": "cell-3b19e819ba1741cc", "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)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "deletable": false, "editable": false, "nbgrader": { "cell_type": "code", "checksum": "5a85827761528c859b7ca173e70eb1d4", "grade": true, "grade_id": "cell-d1935f696f01ac13", "locked": true, "points": 1, "schema_version": 3, "solution": false, "task": false } }, "outputs": [], "source": [ "test_that(\"Question 2\", {\n", " expect_true(digest(answer2) %in% \n", " c(\"e9776d44cb7da14ddffdfa985e1d8908\", \n", " \"ed8ec2bd7d42477ad678dd7f3e077f6e\"))\n", "})" ] }, { "cell_type": "markdown", "metadata": { "deletable": false, "editable": false, "nbgrader": { "cell_type": "markdown", "checksum": "2b6845228d706a2975015ffe299f2480", "grade": false, "grade_id": "cell-7552bac49a0bfb48", "locked": true, "schema_version": 3, "solution": false, "task": false } }, "source": [ "## Question 3\n", "\n", "With stringr, we can substitute parts of a string, too. Replace the word \"fox\" from `answer1` with \"giraffe\" using `str_replace()`, and store the result in a variable named `answer3`.\n", "\n", "```\n", "answer3 <- str_replace(answer1, pattern = FILL_THIS_IN, replacement = FILL_THIS_IN)\n", "```" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "deletable": false, "nbgrader": { "cell_type": "code", "checksum": "415773f3320f5d1abe56deb8dd50b09d", "grade": false, "grade_id": "cell-57e67c68f704efe5", "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)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "deletable": false, "editable": false, "nbgrader": { "cell_type": "code", "checksum": "c3ad9a770e4ad5845143aba5358d7299", "grade": true, "grade_id": "cell-e608b848e630672b", "locked": true, "points": 1, "schema_version": 3, "solution": false, "task": false } }, "outputs": [], "source": [ "test_that(\"Question 3\", {\n", " expect_identical(digest(answer3), \"8659b349bfc1e359cdbb08cd38f5537d\")\n", "})" ] }, { "cell_type": "markdown", "metadata": { "deletable": false, "editable": false, "nbgrader": { "cell_type": "markdown", "checksum": "40983e5b7268597d146ba5c71be9c8d9", "grade": false, "grade_id": "cell-70314b66ec8f657d", "locked": true, "schema_version": 3, "solution": false, "task": false } }, "source": [ "## Question 4: pig latin\n", "\n", "Convert `words` to a simplistic version of pig latin:\n", "\n", "1. Move the first letter to the end of the word.\n", "2. Add \"ay\" to the end of the word.\n", "\n", "Hint: subset by position using `str_sub(string, start, end)`.\n", "\n", "Store the result in a variable named `answer4`." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "deletable": false, "nbgrader": { "cell_type": "code", "checksum": "5165e329c05ab3ef5a3eb4c51b05d32b", "grade": false, "grade_id": "cell-15d22488e4fbf24f", "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", "head(answer4)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "deletable": false, "editable": false, "nbgrader": { "cell_type": "code", "checksum": "09d24ff2e685e3aecab0aae50f0b1304", "grade": true, "grade_id": "cell-0276937d4eb92af6", "locked": true, "points": 1, "schema_version": 3, "solution": false, "task": false } }, "outputs": [], "source": [ "test_that(\"Question 4\", {\n", " expect_identical(digest(answer4), \"66f9cc0b279607492b6d015f979210d2\")\n", "})" ] }, { "cell_type": "markdown", "metadata": { "deletable": false, "editable": false, "nbgrader": { "cell_type": "markdown", "checksum": "206fbf7d348088c61f99857ff0f4dd46", "grade": false, "grade_id": "cell-80604f3d738356db", "locked": true, "schema_version": 3, "solution": false, "task": false } }, "source": [ "Now let's practice working with character columns in a tibble. Consider the wedding dataset on the UBC-STAT/stat545.stat.ubc.ca GitHub repository:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "deletable": false, "editable": false, "nbgrader": { "cell_type": "code", "checksum": "84a330d19146c1b2b775e9e7e4881dde", "grade": false, "grade_id": "cell-6092c25816b4ae37", "locked": true, "schema_version": 3, "solution": false, "task": false } }, "outputs": [], "source": [ "wedding <- suppressMessages(read_csv(\"https://raw.githubusercontent.com/UBC-STAT/stat545.stat.ubc.ca/master/content/data/wedding/attend.csv\"))\n", "head(wedding)" ] }, { "cell_type": "markdown", "metadata": { "deletable": false, "editable": false, "nbgrader": { "cell_type": "markdown", "checksum": "24d2f59a0262bc2a05596d9327e37fef", "grade": false, "grade_id": "cell-5f11b4a5fd8423b5", "locked": true, "schema_version": 3, "solution": false, "task": false } }, "source": [ "Back in Worksheet A-4, we used `tidyr::separate()` to split the `name` column into two columns, named `first` and `last` containing the first and last names (which are currently separated by a space): " ] }, { "cell_type": "code", "execution_count": null, "metadata": { "deletable": false, "editable": false, "nbgrader": { "cell_type": "code", "checksum": "8ff55b6843028d0053c7dc8fe19ce6f6", "grade": false, "grade_id": "cell-4c1655e2ac698c4e", "locked": true, "schema_version": 3, "solution": false, "task": false } }, "outputs": [], "source": [ "wedding_fl <- wedding %>% \n", " separate(name, into = c(\"first\", \"last\"), sep = \" \")\n", "head(wedding_fl)" ] }, { "cell_type": "markdown", "metadata": { "deletable": false, "editable": false, "nbgrader": { "cell_type": "markdown", "checksum": "f17d7dd1d1ffef5fa5450da924f8c997", "grade": false, "grade_id": "cell-a119b9f4940ba4f0", "locked": true, "schema_version": 3, "solution": false, "task": false } }, "source": [ "## Question 5\n", "\n", "Make a new column named `greeting` with entries of each row following the following format: \n", "`\"Hello there, [FIRST_NAME_HERE] from party [PARTY_NUMBER_HERE]!\"` Store the resulting tibble in a variable named `answer5`. \n", "\n", "```\n", "answer5 <- wedding_fl %>%\n", " mutate(greeting = str_c(FILL_THIS_IN))\n", "```\n", "\n", "*Hint 1*: The `str_c()` function can take in any number of character vectors of the same length, stack them up side by side, and glue them together. \n", "\n", "*Hint 2*: `str_c()` can recycle values. For example, if you pass in a character vector of length 1 (say `\"Apple\"`, and a character vector of length 3 (say `c(\"Pie\", \"Crisp\", \"Crumble\")`, then it can return `c(\"Apple Pie\", \"Apple Crisp\", \"Apple Crumble\")`. " ] }, { "cell_type": "code", "execution_count": null, "metadata": { "deletable": false, "nbgrader": { "cell_type": "code", "checksum": "a6cb91a5057f25b9d4b1dfb5a9116726", "grade": false, "grade_id": "cell-77e7d9db69cf47a8", "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(answer5, width=Inf)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "deletable": false, "editable": false, "nbgrader": { "cell_type": "code", "checksum": "eacb8f1ec2148c3ec581220a0a88cde8", "grade": true, "grade_id": "cell-b560283049b996c8", "locked": true, "points": 1, "schema_version": 3, "solution": false, "task": false } }, "outputs": [], "source": [ "test_that(\"Question 5\", {\n", " expect_identical(\n", " digest(unclass(select(answer5, party, first, greeting))), \n", " \"428d7ce6c81771e8ac3cd6a64e31a614\"\n", ")\n", "})" ] }, { "cell_type": "markdown", "metadata": { "deletable": false, "editable": false, "nbgrader": { "cell_type": "markdown", "checksum": "85763ee0cfdb499d0244f3b399671175", "grade": false, "grade_id": "cell-2252c504c7171940", "locked": true, "schema_version": 3, "solution": false, "task": false } }, "source": [ "## Question 6\n", "\n", "Make a tibble with one row per party, with columns named `people` and `wedding_status`:\n", "\n", "- `people`: contains the first names of everyone in the party, separated by commas (and a space: `\", \"`).\n", "- `wedding_status`: should be `\"CONFIRMED\"` if all their wedding status entries are `\"CONFIRMED\"`, and `\"PENDING\"` otherwise. \n", "\n", "Store the resulting tibble in a variable named `answer6`.\n", "\n", "Starter code:\n", "\n", "```\n", "answer6 <- wedding_fl %>% \n", " group_by(party) %>% \n", " summarise(\n", " people = str_flatten(FILL_THIS_IN),\n", " wedding_status = if_else(FILL_THIS_IN, \"CONFIRMED\", \"PENDING\")\n", " )\n", "```\n", "\n", "*Hint*: The `str_flatten()` function concatenates a vector of characters into a single string, with an optional argument that lets you put things between vector elements before concatenating them. " ] }, { "cell_type": "code", "execution_count": null, "metadata": { "deletable": false, "nbgrader": { "cell_type": "code", "checksum": "0705450fe354c78bd8a8179ddc38bb11", "grade": false, "grade_id": "cell-684b49cb1e966bbe", "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(answer6)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "deletable": false, "editable": false, "nbgrader": { "cell_type": "code", "checksum": "c3f300c8ee05619f159de5ccb7d3b8ff", "grade": true, "grade_id": "cell-02b42dee1ed42a07", "locked": true, "points": 1, "schema_version": 3, "solution": false, "task": false } }, "outputs": [], "source": [ "test_that(\"Question 6\", {\n", " expect_identical(\n", " digest(unclass(select(answer6, people, wedding_status))), \n", " \"cf18af7e44c899c48e53b83614739b86\"\n", ")\n", "})" ] }, { "cell_type": "markdown", "metadata": { "deletable": false, "editable": false, "nbgrader": { "cell_type": "markdown", "checksum": "a09cc6db4238c791b56cd0b9f742d459", "grade": false, "grade_id": "cell-96aea45598f83a67", "locked": true, "schema_version": 3, "solution": false, "task": false } }, "source": [ "*Good to know*: If you wanted to be more gramatically correct, you could have replaced `str_flatten()` with the `str_flatten_comma()` function to enforce English grammar rules for listing off items. For example, this function would allow you to separate two names with `\" and \"`. " ] }, { "cell_type": "markdown", "metadata": { "deletable": false, "editable": false, "nbgrader": { "cell_type": "markdown", "checksum": "020035694bcc6a8e63070053cec70ea5", "grade": false, "grade_id": "cell-7e40062d918cda9c", "locked": true, "schema_version": 3, "solution": false, "task": false } }, "source": [ "# Part 2: Introduction to Regular Expressions" ] }, { "cell_type": "markdown", "metadata": { "deletable": false, "editable": false, "nbgrader": { "cell_type": "markdown", "checksum": "b2395642e70fb960336faac7e33a7926", "grade": false, "grade_id": "cell-966c52fd3f31334e", "locked": true, "schema_version": 3, "solution": false, "task": false } }, "source": [ "Regular expressions -- or \"Regex\" for short -- express a pattern in text that can be passed into `stringr` functions to do powerful things. Let's start by learning the basics of how to write these patterns with the helpful `str_view()` function:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "deletable": false, "editable": false, "nbgrader": { "cell_type": "code", "checksum": "3af804462e4d6fe91fa462242ded86b8", "grade": false, "grade_id": "cell-6f500fd32a7773d0", "locked": true, "schema_version": 3, "solution": false, "task": false } }, "outputs": [], "source": [ "str_view(fruit, \"melon\")" ] }, { "cell_type": "markdown", "metadata": { "deletable": false, "editable": false, "nbgrader": { "cell_type": "markdown", "checksum": "0a2a2666bdb43ddd2a2945ce54ba117c", "grade": false, "grade_id": "cell-3479e82ec0ff8e1b", "locked": true, "schema_version": 3, "solution": false, "task": false } }, "source": [ "The `str_view()` function took in a character vector containing fruits, and highlighted the entries matching the regular expression pattern `\"melon\"`. This is the simplest type of regex pattern, and it means to look for an exact match. \n", "\n", "Let's learn more about the language of regex patterns using the countries in the gapminder data set: " ] }, { "cell_type": "code", "execution_count": null, "metadata": { "deletable": false, "editable": false, "nbgrader": { "cell_type": "code", "checksum": "94bbd21ff5e0b237ac8ed5aa752755a7", "grade": false, "grade_id": "cell-dc0f3d9aac8aa10b", "locked": true, "schema_version": 3, "solution": false, "task": false } }, "outputs": [], "source": [ "countries <- levels(gapminder::gapminder$country)\n", "head(countries)" ] }, { "cell_type": "markdown", "metadata": { "deletable": false, "editable": false, "nbgrader": { "cell_type": "markdown", "checksum": "e50dba57a589b9d78f46d8e7fd8edf10", "grade": false, "grade_id": "cell-05c7d18faf298c4c", "locked": true, "schema_version": 3, "solution": false, "task": false } }, "source": [ "## Question 7: \"any\" characters\n", "\n", "The \".\" character when used in a regular expression means \"any single character\". \n", "\n", "Use the `str_subset()` function to find all countries in the gapminder data set with the following pattern: \"i\", followed by any single character, followed by \"a\". Store the result in a vector named `answer7`. \n", "\n", "Note that Italy will not be on the list, because regex is case-sensitive.\n", "\n", "*Good to know*: You can specify \"any single character in this list of characters\" or \"any single character except those in this list of characters\" using square brackets. For example, `\"[abc]\"` for \"a, b, or c\" and `\"[^abc]\"` for \"anything but a, b, or c\". " ] }, { "cell_type": "code", "execution_count": null, "metadata": { "deletable": false, "nbgrader": { "cell_type": "code", "checksum": "43c1465962c38516805283f2524c1a29", "grade": false, "grade_id": "cell-22a801393523e273", "locked": false, "schema_version": 3, "solution": true, "task": false } }, "outputs": [], "source": [ "# str_view(countries, pattern = \"FILL_THIS_IN\")\n", "# answer7 <- str_subset(countries, pattern = \"FILL_THIS_IN\")\n", "\n", "# your code here\n", "fail() # No Answer - remove if you provide an answer\n", "print(answer7)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "deletable": false, "editable": false, "nbgrader": { "cell_type": "code", "checksum": "466006269940c9e27ecde1e9175b8c2b", "grade": true, "grade_id": "cell-c835b50877ea9090", "locked": true, "points": 1, "schema_version": 3, "solution": false, "task": false } }, "outputs": [], "source": [ "test_that(\"Question 7\", {\n", " expect_identical(digest(answer7), \"fdf1c0b93db219fb32d927700cab3c4e\")\n", "})" ] }, { "cell_type": "markdown", "metadata": { "deletable": false, "editable": false, "nbgrader": { "cell_type": "markdown", "checksum": "ff3c68e4d717f276012daa49f3371360", "grade": false, "grade_id": "cell-b406fa6a0014ed7c", "locked": true, "schema_version": 3, "solution": false, "task": false } }, "source": [ "## Question 8: the \"escape\" \n", "\n", "Uh oh! But what if I wanted to literally search for countries with a period in the name? I can't use the regex `\".\"`, since that'll match \"any single character\". I need to \"escape the period\" to indicate that I really mean to search for the character \".\", and don't mean to use the character \".\" in its special regex meaning. We can escape the period by adding `\\\\` in front of it.\n", "\n", "\"Escape the period\" to make a vector of all countries with at least one period in their name. Store the result in a vector named `answer8`.\n", "\n", "*Good to know*: If you've used regex outside of R, you might be surprised to see that we need to add `\\\\` rather than `\\`. This is because `\\` itself is a special character in R strings that need to be escaped with `\\`. " ] }, { "cell_type": "code", "execution_count": null, "metadata": { "deletable": false, "nbgrader": { "cell_type": "code", "checksum": "e4f3162bd13035017073d6af649cccaf", "grade": false, "grade_id": "cell-6837e2f60c9ab577", "locked": false, "schema_version": 3, "solution": true, "task": false } }, "outputs": [], "source": [ "# str_view(countries, pattern = \"FILL_THIS_IN\")\n", "# answer8 <- str_subset(countries, pattern = \"FILL_THIS_IN\")\n", "\n", "# your code here\n", "fail() # No Answer - remove if you provide an answer\n", "print(answer8)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "deletable": false, "editable": false, "nbgrader": { "cell_type": "code", "checksum": "9ff5e4f15af81aa0873e8ede9bd912e9", "grade": true, "grade_id": "cell-900364bf4a541ab3", "locked": true, "points": 1, "schema_version": 3, "solution": false, "task": false } }, "outputs": [], "source": [ "test_that(\"Question 8\", {\n", " expect_identical(digest(answer8), \"4c500f226f5abbe540ef2506a4644375\")\n", "})" ] }, { "cell_type": "markdown", "metadata": { "deletable": false, "editable": false, "nbgrader": { "cell_type": "markdown", "checksum": "3edf434fe4d40c6595849dee1404eafb", "grade": false, "grade_id": "cell-344db5435da777df", "locked": true, "schema_version": 3, "solution": false, "task": false } }, "source": [ "## Question 9: Position indicators\n", "\n", "Use:\n", "\n", "- `^` to correspond to the __beginning__ of a string.\n", "- `$` to correspond to the __end__ of a string.\n", "\n", "Find all countries that end in \"land\". Store the result in a vector named `answer9`." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "deletable": false, "nbgrader": { "cell_type": "code", "checksum": "ceda041f5916a78df57dbd986402766e", "grade": false, "grade_id": "cell-35f0de5542c6d0d0", "locked": false, "schema_version": 3, "solution": true, "task": false } }, "outputs": [], "source": [ "# str_view(countries, \"FILL_THIS_IN\")\n", "# answer9 <- str_subset(countries, \"FILL_THIS_IN\")\n", "\n", "# your code here\n", "fail() # No Answer - remove if you provide an answer\n", "print(answer9)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "deletable": false, "editable": false, "nbgrader": { "cell_type": "code", "checksum": "e7efaffe70e8b80378d0f403ed2b7086", "grade": true, "grade_id": "cell-7dfee270fe57717c", "locked": true, "points": 1, "schema_version": 3, "solution": false, "task": false } }, "outputs": [], "source": [ "test_that(\"Question 9\", {\n", " expect_identical(digest(answer9), \"692ee00b59194cea743c5ac3bf2302ae\")\n", "})" ] }, { "cell_type": "markdown", "metadata": { "deletable": false, "editable": false, "nbgrader": { "cell_type": "markdown", "checksum": "427b99e13b0ff4a8926a159facdb10b8", "grade": false, "grade_id": "cell-df3ce76905844afa", "locked": true, "schema_version": 3, "solution": false, "task": false } }, "source": [ "## Question 10: Quantifiers/Repetition\n", "\n", "The handy ones are:\n", "\n", "- `*` for 0 or more\n", "- `+` for 1 or more\n", "- `?` for 0 or 1\n", "\n", "Find all countries that have any number of \"o\"'s (but at least 1), following an \"r\". Store the resulting vector in a variable named `answer10`." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "deletable": false, "lines_to_next_cell": 2, "nbgrader": { "cell_type": "code", "checksum": "26188621e13f94c518458453aa402cc0", "grade": false, "grade_id": "cell-36d6437e624d72f5", "locked": false, "schema_version": 3, "solution": true, "task": false } }, "outputs": [], "source": [ "# str_view(countries, \"FILL_THIS_IN\")\n", "# answer10 <- str_subset(countries, \"FILL_THIS_IN\")\n", "\n", "# your code here\n", "fail() # No Answer - remove if you provide an answer\n", "print(answer10)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "deletable": false, "editable": false, "nbgrader": { "cell_type": "code", "checksum": "13c94a6ec52633a7a7903b508463a04a", "grade": true, "grade_id": "cell-2755ef7fa0a525de", "locked": true, "points": 1, "schema_version": 3, "solution": false, "task": false } }, "outputs": [], "source": [ "test_that(\"Question 10\", {\n", " expect_identical(digest(answer10), \"fa31d9cfe634b9a841cabdf9e31c0eeb\")\n", "})" ] }, { "cell_type": "markdown", "metadata": { "deletable": false, "editable": false, "nbgrader": { "cell_type": "markdown", "checksum": "368570bde9da73971064ef703d96c890", "grade": false, "grade_id": "cell-d80fd1a2aa56bff1", "locked": true, "schema_version": 3, "solution": false, "task": false } }, "source": [ "## Question 11: \"Or\" and Precedence\n", "\n", "Use `|` to denote \"or\". \"And\" is implied otherwise, and has precedence. Use parentheses to be deliberate with precedence.\n", "\n", "For example:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "deletable": false, "editable": false, "lines_to_next_cell": 2, "nbgrader": { "cell_type": "code", "checksum": "1dd39a81f5b12e9062d94ed5a9d99797", "grade": false, "grade_id": "cell-894e6b100d9b24e0", "locked": true, "schema_version": 3, "solution": false, "task": false } }, "outputs": [], "source": [ "bbb <- c(\"bear\", \"beer\", \"bar\")\n", "cat(\"'bee' or 'ar':\")\n", "str_view(bbb, pattern = \"bee|ar\")\n", "cat(\"'e' or 'a':\")\n", "str_view(bbb, pattern = \"be(e|a)r\") " ] }, { "cell_type": "markdown", "metadata": { "deletable": false, "editable": false, "nbgrader": { "cell_type": "markdown", "checksum": "68cf4aaad12072e8c31438c414d09189", "grade": false, "grade_id": "cell-825d29c47d308e2c", "locked": true, "schema_version": 3, "solution": false, "task": false } }, "source": [ "Now, find all countries that have either \"o\" twice in a row or \"e\" twice in a row (\"oe\" and \"eo\" are not allowed). Store the resulting vector in a variable named `answer11`." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "deletable": false, "lines_to_next_cell": 2, "nbgrader": { "cell_type": "code", "checksum": "6d789d764f67002e7555234a4978e2d6", "grade": false, "grade_id": "cell-7e58b1b7884a641e", "locked": false, "schema_version": 3, "solution": true, "task": false } }, "outputs": [], "source": [ "# str_view(countries, \"FILL_THIS_IN\")\n", "# answer11 <- str_subset(countries, \"FILL_THIS_IN\")\n", "\n", "# your code here\n", "fail() # No Answer - remove if you provide an answer\n", "print(answer11)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "deletable": false, "editable": false, "nbgrader": { "cell_type": "code", "checksum": "f43062757692db28aac16dfb3e4f467f", "grade": true, "grade_id": "cell-9e7786647b5e1c8c", "locked": true, "points": 1, "schema_version": 3, "solution": false, "task": false } }, "outputs": [], "source": [ "test_that(\"Question 11\", {\n", " expect_identical(digest(answer11), \"558af24f1d19b86ffc6b74541aef9f9b\")\n", "})" ] }, { "cell_type": "markdown", "metadata": { "deletable": false, "editable": false, "nbgrader": { "cell_type": "markdown", "checksum": "acd23335e6d31b84b9566ff2e30368d1", "grade": false, "grade_id": "cell-c77eca26543c2632", "locked": true, "schema_version": 3, "solution": false, "task": false } }, "source": [ "## Question 13: Groups\n", "\n", "You can use parentheses not only to specify precendence, but also to indicate groups that you can refer to later using integers to refer to the group number. \n", "\n", "Example using a's and b's: matching all instances of a character sandwiched between the same two characters:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "deletable": false, "editable": false, "nbgrader": { "cell_type": "code", "checksum": "e9004e4f1ecc1b0b514ca82f774a64fc", "grade": false, "grade_id": "cell-c7b58e02356d6bdb", "locked": true, "schema_version": 3, "solution": false, "task": false } }, "outputs": [], "source": [ "ab <- c(\"aaa\", \"aab\", \"aba\", \"baa\", \"abb\", \"bab\", \"bba\", \"bbb\")\n", "str_view(ab, pattern=\"(.)(.)\\\\1\")" ] }, { "cell_type": "markdown", "metadata": { "deletable": false, "editable": false, "nbgrader": { "cell_type": "markdown", "checksum": "ae6859a1ecd33072ef70cb188383504b", "grade": false, "grade_id": "cell-c9ccf764fb47c488", "locked": true, "schema_version": 3, "solution": false, "task": false } }, "source": [ "Example: matching all instances of a character followed by two identical characters:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "deletable": false, "editable": false, "nbgrader": { "cell_type": "code", "checksum": "a01265a3ff1709becff530eda9ba8062", "grade": false, "grade_id": "cell-f86af2dbcd3966ea", "locked": true, "schema_version": 3, "solution": false, "task": false } }, "outputs": [], "source": [ "str_view(ab, pattern=\"(.)(.)\\\\2\")" ] }, { "cell_type": "markdown", "metadata": { "deletable": false, "editable": false, "nbgrader": { "cell_type": "markdown", "checksum": "a714696895beafdec6e91973a5db7656", "grade": false, "grade_id": "cell-b55551b61d558e4d", "locked": true, "schema_version": 3, "solution": false, "task": false } }, "source": [ "Your task: Find all countries that have the same letter repeated twice (like \"Greece\", which has \"ee\"). Store the result in a vector named `answer12`." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "deletable": false, "nbgrader": { "cell_type": "code", "checksum": "89622420de7e027ee13cce625e9c3944", "grade": false, "grade_id": "cell-7be4b6cfc12e36b5", "locked": false, "schema_version": 3, "solution": true, "task": false } }, "outputs": [], "source": [ "# str_view(countries, \"FILL_THIS_IN\")\n", "# answer12 <- str_subset(countries, \"FILL_THIS_IN\")\n", "\n", "# your code here\n", "fail() # No Answer - remove if you provide an answer\n", "print(answer12)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "deletable": false, "editable": false, "nbgrader": { "cell_type": "code", "checksum": "477c63ccafb621870001849fd660a041", "grade": true, "grade_id": "cell-3250e4c8720f31b7", "locked": true, "points": 1, "schema_version": 3, "solution": false, "task": false } }, "outputs": [], "source": [ "test_that(\"Question 12\", {\n", " expect_identical(digest(answer12), \"3531a88f6935e86d4ff1054504182875\")\n", "})" ] }, { "cell_type": "markdown", "metadata": { "deletable": false, "editable": false, "nbgrader": { "cell_type": "markdown", "checksum": "722c972b9def63562f4c332a788e83c6", "grade": false, "grade_id": "cell-79b27633b808bacd", "locked": true, "schema_version": 3, "solution": false, "task": false } }, "source": [ "# Part 3: Stringr with regular expressions" ] }, { "cell_type": "markdown", "metadata": { "deletable": false, "editable": false, "nbgrader": { "cell_type": "markdown", "checksum": "3d588fd85beb0354834e4b863fb778ac", "grade": false, "grade_id": "cell-8d9dd521604370f0", "locked": true, "schema_version": 3, "solution": false, "task": false } }, "source": [ "Now that you have your bearings with stringr and with regular expressions, let's practice putting them together in (semi)realistic scenarios. \n", "\n", "Useful links: \n", "- [Posit Strings cheatsheet](https://github.com/rstudio/cheatsheets/blob/main/strings.pdf) covers stringr on page 1 and regular expressions on page 2.\n", "- [Regexlearn.com](https://regexlearn.com/) for another regular expressions tutorial (general, not specific to R). \n", "- [Regexr](https://regexr.com/) is very helpful, especially when constructing more complex regular expressions." ] }, { "cell_type": "markdown", "metadata": { "deletable": false, "editable": false, "nbgrader": { "cell_type": "markdown", "checksum": "eb8f2712003a0ff19f897df8f32b5b4e", "grade": false, "grade_id": "cell-eaebbc8f707f7c7a", "locked": true, "schema_version": 3, "solution": false, "task": false } }, "source": [ "## Question 13\n", "\n", "Select individuals in the wedding tibble whose first name starts between \"A\" and \"Em\" inclusive, and sort them in alphabetical order by first name. Store the resulting tibble in a variable named `answer14`.\n", "\n", "Starter code:\n", "\n", "```\n", "answer13 <- wedding %>% \n", " filter(FILL_THIS_IN(name, \"FILL_THIS_IN\")) %>% \n", " arrange(name)\n", "```" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "deletable": false, "nbgrader": { "cell_type": "code", "checksum": "c1cf1c4a5e44804a670091467e5597f7", "grade": false, "grade_id": "cell-1e2d94b35a9a495f", "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(answer13)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "deletable": false, "editable": false, "nbgrader": { "cell_type": "code", "checksum": "549a0e461b1a516682ec454beadff66c", "grade": true, "grade_id": "cell-c9b809048a680c8e", "locked": true, "points": 1, "schema_version": 3, "solution": false, "task": false } }, "outputs": [], "source": [ "test_that(\"Question 13\", {\n", " expect_identical(digest(sort(answer13$name)), \"6bbf440d3cca5b2e4b670b48f7bddc14\")\n", "})" ] }, { "cell_type": "markdown", "metadata": { "deletable": false, "editable": false, "nbgrader": { "cell_type": "markdown", "checksum": "78ae70c88a73e019cc59132f42052baf", "grade": false, "grade_id": "cell-659a9254e1ba185a", "locked": true, "schema_version": 3, "solution": false, "task": false } }, "source": [ "## Question 14\n", "\n", "Add a column called `prop_vowels` to the `wedding_fl` tibble that contains the proportion of vowels in each first name. For example, \"Emaan\" has 3 vowels and 5 letters, so the proportion of vowels is 3/5 = 60\\%. Store the resulting tibble in a variable named `answer14`. " ] }, { "cell_type": "code", "execution_count": null, "metadata": { "deletable": false, "nbgrader": { "cell_type": "code", "checksum": "68b676d4669af30d64cb2744f41ab3ac", "grade": false, "grade_id": "cell-8b60c0985702eea5", "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(answer14)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "deletable": false, "editable": false, "nbgrader": { "cell_type": "code", "checksum": "97dc0c8a28d0e119af91cc907ce90672", "grade": true, "grade_id": "cell-a6cd23444c761b38", "locked": true, "points": 1, "schema_version": 3, "solution": false, "task": false } }, "outputs": [], "source": [ "test_that(\"Question 14\", {\n", " expect_identical(\n", " answer14 %>% \n", " select(first, prop_vowels) %>% \n", " arrange(first) %>%\n", " mutate(prop_vowels = round(prop_vowels, digits = 3)) %>% \n", " digest(), \n", " \"f37d71c09ea60921ddd3959252db3f14\"\n", " )\n", "})" ] }, { "cell_type": "markdown", "metadata": { "deletable": false, "editable": false, "nbgrader": { "cell_type": "markdown", "checksum": "34e3d2d4a77cfe181e2f8308be42cffb", "grade": false, "grade_id": "cell-01cb2b580c312841", "locked": true, "schema_version": 3, "solution": false, "task": false } }, "source": [ "## Question 15\n", "\n", "Task: what letters are used in the first sentence of the `stringr::sentences` dataset? Make a vector of all the unique letters in the sentence (in lowercase), and store it in a variable called `answer15`. Don't forget to remove non-letters, which are either a space or a period.\n", "\n", "Hint:\n", "\n", "```\n", "answer15 <- sentences[1] %>% \n", " str_remove_all(\"FILL_THIS_IN\") %>% \n", " FILL_THIS_IN() %>% \n", " str_split(FILL_THIS_IN) %>% \n", " .[[1]] %>% \n", " unique()\n", "```" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "deletable": false, "nbgrader": { "cell_type": "code", "checksum": "0cd60d94bf66fa327f56254a7b8d0ac3", "grade": false, "grade_id": "cell-1c604d815b14c39f", "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(answer15)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "deletable": false, "editable": false, "nbgrader": { "cell_type": "code", "checksum": "ee236652ce0edced5939b912d56c33c6", "grade": true, "grade_id": "cell-a221cbb3ad7d2176", "locked": true, "points": 1, "schema_version": 3, "solution": false, "task": false } }, "outputs": [], "source": [ "test_that(\"Question 15\", {\n", " expect_identical(digest(sort(answer15)), \"d586631001ba6d44947a09efecc4f960\")\n", "})" ] }, { "cell_type": "markdown", "metadata": { "deletable": false, "editable": false, "nbgrader": { "cell_type": "markdown", "checksum": "e9e5d880ba17c0c5ac4521d378046445", "grade": false, "grade_id": "cell-21cd29c7f490f51b", "locked": true, "schema_version": 3, "solution": false, "task": false } }, "source": [ "## Question 16\n", "\n", "Here is a tibble with made-up names and telephone numbers: " ] }, { "cell_type": "code", "execution_count": null, "metadata": { "deletable": false, "editable": false, "nbgrader": { "cell_type": "code", "checksum": "53495b064006c15cb28665740de8e002", "grade": false, "grade_id": "cell-74076a735448e3a9", "locked": true, "schema_version": 3, "solution": false, "task": false } }, "outputs": [], "source": [ "contact <- tibble(name = c(\"Kayden Lavoie\", \n", " \"Ethan Fortin\", \n", " \"Emma Davis\", \n", " \"Aliyah Chan\"), \n", " phone = c(\"604-971-9949\", \n", " \"6046182277\", \n", " \"(778)881-5831\", \n", " \"604-544-2554\"))\n", "print(contact)" ] }, { "cell_type": "markdown", "metadata": { "deletable": false, "editable": false, "nbgrader": { "cell_type": "markdown", "checksum": "bdc0870b86e0f7d741736549d2ff3a7c", "grade": false, "grade_id": "cell-69fc1804815e256b", "locked": true, "schema_version": 3, "solution": false, "task": false } }, "source": [ "Unfortunately, these four people have entered in their phone numbers in different formats. Let's fix that, in the spirit of routine data cleaning. Change the `phone` column to have all four phone numbers match Aliyah Chan's format. Store the resulting tibble in a variable called `answer16`. \n", "\n", "*Hint*: `mutate()`, `str_remove_all()`, `separate()`, and `unite()`. " ] }, { "cell_type": "code", "execution_count": null, "metadata": { "deletable": false, "nbgrader": { "cell_type": "code", "checksum": "b715e1ab4567216f4a69104505824706", "grade": false, "grade_id": "cell-753ecdad7449dc0d", "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(answer16)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "deletable": false, "editable": false, "nbgrader": { "cell_type": "code", "checksum": "791588fcdda0d94ef176b900a57ff459", "grade": true, "grade_id": "cell-b9d9087649c148b5", "locked": true, "points": 1, "schema_version": 3, "solution": false, "task": false } }, "outputs": [], "source": [ "test_that(\"Question 16\", {\n", " expect_identical(answer16 %>% arrange(name) %>% digest(), \n", " \"83e461c86c45469beecbbd011c6b11e6\")\n", "})" ] } ], "metadata": { "jupytext": { "cell_metadata_filter": "warning,message,-all", "main_language": "R", "notebook_metadata_filter": "-all" }, "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 }