Wrangling Variables

Mine Doğucu

Pipe Operator

Three solutions to a single problem

What is the average of 4, 8, 16 approximately?

Breaking down the question

1.What is the average of 4, 8, 16 approximately?

2.What is the average of 4, 8, 16 approximately?

3.What is the average of 4, 8, 16 approximately?

Solution 1: Functions within Functions

c(4, 8, 16)
[1]  4  8 16

mean(c(4, 8, 16))
[1] 9.333333

round(mean(c(4, 8, 16)))
[1] 9

Problem!

Problem with writing functions within functions

Things will get messy and more difficult to read and debug as we deal with more complex operations on data.

Solution 2: Creating Objects

numbers <- c(4, 8, 16)
numbers
[1]  4  8 16

avg_number <- mean(numbers)
avg_number
[1] 9.333333

round(avg_number)
[1] 9

Problem!

Problem with creating many objects

We will end up with too many objects in Environment.

Solution 3: The (forward) Pipe Operator |>

Shortcut:
Ctrl (Command) + Shift + M

RStudio settings

Make sure to select Use native pipe operator under Tools > Global Options > Code in RStudio

Data

library(tidyverse)
board_games <- 
  read_csv(
    here::here(
      "data",
      "games_detailed_info2025.csv"
    )
  ) 

Unless mentioned, today’s functions come from the {dplyr} package which is part of tidyverse.


Data Documentation

Data Glimpse

glimpse(board_games)
Rows: 27,780
Columns: 52
$ ...1                          <dbl> 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12…
$ type                          <chr> "boardgame", "boardgame", "boardgame", "…
$ id                            <dbl> 13, 822, 30549, 68448, 167791, 266192, 1…
$ thumbnail                     <chr> "https://cf.geekdo-images.com/PyUol9QxBn…
$ image                         <chr> "https://cf.geekdo-images.com/PyUol9QxBn…
$ alternate                     <chr> "['Catan', 'Catan (Колонизаторы)', 'Cata…
$ description                   <chr> "In CATAN (formerly The Settlers of Cata…
$ yearpublished                 <dbl> 1995, 2000, 2008, 2010, 2016, 2019, 2015…
$ minplayers                    <dbl> 3, 2, 2, 2, 1, 1, 2, 2, 2, 2, 2, 1, 2, 2…
$ maxplayers                    <dbl> 4, 5, 4, 7, 5, 5, 2, 4, 8, 4, 5, 5, 4, 5…
$ suggested_num_players         <chr> "[{'@numplayers': '1', 'result': [{'@val…
$ suggested_playerage           <chr> "[{'@value': '2', '@numvotes': '1'}, {'@…
$ suggested_language_dependence <chr> "[{'@level': '1', '@value': 'No necessar…
$ playingtime                   <dbl> 120, 45, 45, 30, 120, 70, 30, 45, 15, 30…
$ minplaytime                   <dbl> 60, 30, 45, 30, 120, 40, 30, 30, 15, 30,…
$ maxplaytime                   <dbl> 120, 45, 45, 30, 120, 70, 30, 45, 15, 30…
$ minage                        <dbl> 10, 7, 8, 10, 12, 10, 10, 8, 14, 13, 8, …
$ boardgamecategory             <chr> "['Economic', 'Negotiation']", "['Mediev…
$ boardgamemechanic             <chr> "['Chaining', 'Dice Rolling', 'Hexagon G…
$ boardgamefamily               <chr> "['Animals: Sheep', 'Components: Hexagon…
$ boardgameexpansion            <chr> "['20 Jahre Darmstadt Spielt', 'Brettspi…
$ boardgameaccessory            <chr> "['Catan x Goat Simulator 3: Resource Re…
$ boardgamecompilation          <chr> "[\"CATAN 3D Collector's Edition\", 'Cat…
$ boardgameimplementation       <chr> "['Baden-Württemberg Catan', 'Catan Geog…
$ boardgamedesigner             <chr> "['Klaus Teuber']", "['Klaus-Jürgen Wred…
$ boardgameartist               <chr> "['Volkan Baga', 'Tanja Donner', 'Pete F…
$ boardgamepublisher            <chr> "['KOSMOS', '64 Ounce Games', '999 Games…
$ usersrated                    <dbl> 132477, 131182, 128935, 107506, 103923, …
$ average                       <dbl> 7.09526, 7.41145, 7.52913, 7.67463, 8.35…
$ bayesaverage                  <dbl> 6.91526, 7.29556, 7.42156, 7.56393, 8.20…
$ `Board Game Rank`             <dbl> 573, 230, 158, 101, 7, 32, 20, 83, 151, …
$ `Strategy Game Rank`          <dbl> 533, NA, 168, 111, 7, 40, 23, NA, NA, 13…
$ `Family Game Rank`            <dbl> 196, 55, 32, 18, NA, 2, NA, 13, NA, NA, …
$ stddev                        <dbl> 1.49966, 1.31135, 1.33643, 1.27648, 1.42…
$ median                        <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0…
$ owned                         <dbl> 218546, 204049, 211600, 147129, 145458, …
$ trading                       <dbl> 2264, 1995, 3228, 1896, 785, 795, 1198, …
$ wanting                       <dbl> 518, 656, 620, 979, 1905, 1303, 885, 969…
$ wishing                       <dbl> 7367, 9787, 10981, 14247, 24807, 19886, …
$ numcomments                   <dbl> 22600, 22150, 19897, 16690, 14696, 13335…
$ numweights                    <dbl> 8299, 8414, 6138, 5365, 4280, 3297, 3151…
$ averageweight                 <dbl> 2.2881, 1.8894, 2.3974, 2.3171, 3.2657, …
$ boardgameintegration          <chr> NA, "['Carcassonne: Wheel of Fortune', '…
$ `Abstract Game Rank`          <dbl> NA, NA, NA, NA, NA, NA, NA, 2, NA, NA, N…
$ `Party Game Rank`             <dbl> NA, NA, NA, NA, NA, NA, NA, NA, 5, NA, N…
$ `Thematic Rank`               <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, …
$ `War Game Rank`               <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, …
$ `Customizable Rank`           <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, …
$ `Children's Game Rank`        <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, …
$ `RPG Item Rank`               <lgl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, …
$ `Accessory Rank`              <lgl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, …
$ name                          <chr> "CATAN", "Carcassonne", "Pandemic", "7 W…

Changing Variable Names

Tidy style variable names

janitor::clean_names(board_games)
# A tibble: 27,780 × 52
      x1 type          id thumbnail    image alternate description yearpublished
   <dbl> <chr>      <dbl> <chr>        <chr> <chr>     <chr>               <dbl>
 1     0 boardgame     13 https://cf.… http… ['Catan'… In CATAN (…          1995
 2     1 boardgame    822 https://cf.… http… ['Carcas… Carcassonn…          2000
 3     2 boardgame  30549 https://cf.… http… ['EPIZOo… In Pandemi…          2008
 4     3 boardgame  68448 https://cf.… http… ['7 csod… You are th…          2010
 5     4 boardgame 167791 https://cf.… http… ['A Mars… In the 240…          2016
 6     5 boardgame 266192 https://cf.… http… ['Fesztá… Wingspan i…          2019
 7     6 boardgame 173346 https://cf.… http… ['7 Csod… In many wa…          2015
 8     7 boardgame 230802 https://cf.… http… ['Azul M… Introduced…          2017
 9     8 boardgame 178900 https://cf.… http… ['Codena… Two rival …          2015
10     9 boardgame  36218 https://cf.… http… ['Domini… &quot;You …          2008
# ℹ 27,770 more rows
# ℹ 44 more variables: minplayers <dbl>, maxplayers <dbl>,
#   suggested_num_players <chr>, suggested_playerage <chr>,
#   suggested_language_dependence <chr>, playingtime <dbl>, minplaytime <dbl>,
#   maxplaytime <dbl>, minage <dbl>, boardgamecategory <chr>,
#   boardgamemechanic <chr>, boardgamefamily <chr>, boardgameexpansion <chr>,
#   boardgameaccessory <chr>, boardgamecompilation <chr>, …

Rename variables

board_games |> 
  rename(index = ...1)
# A tibble: 27,780 × 52
   index type          id thumbnail    image alternate description yearpublished
   <dbl> <chr>      <dbl> <chr>        <chr> <chr>     <chr>               <dbl>
 1     0 boardgame     13 https://cf.… http… ['Catan'… In CATAN (…          1995
 2     1 boardgame    822 https://cf.… http… ['Carcas… Carcassonn…          2000
 3     2 boardgame  30549 https://cf.… http… ['EPIZOo… In Pandemi…          2008
 4     3 boardgame  68448 https://cf.… http… ['7 csod… You are th…          2010
 5     4 boardgame 167791 https://cf.… http… ['A Mars… In the 240…          2016
 6     5 boardgame 266192 https://cf.… http… ['Fesztá… Wingspan i…          2019
 7     6 boardgame 173346 https://cf.… http… ['7 Csod… In many wa…          2015
 8     7 boardgame 230802 https://cf.… http… ['Azul M… Introduced…          2017
 9     8 boardgame 178900 https://cf.… http… ['Codena… Two rival …          2015
10     9 boardgame  36218 https://cf.… http… ['Domini… &quot;You …          2008
# ℹ 27,770 more rows
# ℹ 44 more variables: minplayers <dbl>, maxplayers <dbl>,
#   suggested_num_players <chr>, suggested_playerage <chr>,
#   suggested_language_dependence <chr>, playingtime <dbl>, minplaytime <dbl>,
#   maxplaytime <dbl>, minage <dbl>, boardgamecategory <chr>,
#   boardgamemechanic <chr>, boardgamefamily <chr>, boardgameexpansion <chr>,
#   boardgameaccessory <chr>, boardgamecompilation <chr>, …

The rename() function changes the name of the variable. The new_variable_name has to be set to equal to the old_variable_name.

The clean_names() function changes all variable names to tidyverse style.

Step 1

In fact there are many variables that do not adhere to tidyverse style convention. I will go ahead and rename only those that will come up in subsequent slides.

board_games |> 
  janitor::clean_names()
# A tibble: 27,780 × 52
      x1 type          id thumbnail    image alternate description yearpublished
   <dbl> <chr>      <dbl> <chr>        <chr> <chr>     <chr>               <dbl>
 1     0 boardgame     13 https://cf.… http… ['Catan'… In CATAN (…          1995
 2     1 boardgame    822 https://cf.… http… ['Carcas… Carcassonn…          2000
 3     2 boardgame  30549 https://cf.… http… ['EPIZOo… In Pandemi…          2008
 4     3 boardgame  68448 https://cf.… http… ['7 csod… You are th…          2010
 5     4 boardgame 167791 https://cf.… http… ['A Mars… In the 240…          2016
 6     5 boardgame 266192 https://cf.… http… ['Fesztá… Wingspan i…          2019
 7     6 boardgame 173346 https://cf.… http… ['7 Csod… In many wa…          2015
 8     7 boardgame 230802 https://cf.… http… ['Azul M… Introduced…          2017
 9     8 boardgame 178900 https://cf.… http… ['Codena… Two rival …          2015
10     9 boardgame  36218 https://cf.… http… ['Domini… &quot;You …          2008
# ℹ 27,770 more rows
# ℹ 44 more variables: minplayers <dbl>, maxplayers <dbl>,
#   suggested_num_players <chr>, suggested_playerage <chr>,
#   suggested_language_dependence <chr>, playingtime <dbl>, minplaytime <dbl>,
#   maxplaytime <dbl>, minage <dbl>, boardgamecategory <chr>,
#   boardgamemechanic <chr>, boardgamefamily <chr>, boardgameexpansion <chr>,
#   boardgameaccessory <chr>, boardgamecompilation <chr>, …

Step 2

board_games |> 
  janitor::clean_names() |> 
  rename(
    index = x1,
    year_published = yearpublished,
    board_game_category = boardgamecategory,
    num_comments = numcomments,
    users_rated = usersrated,
    max_players = maxplayers,
    designer = boardgamedesigner
  )
# A tibble: 27,780 × 52
   index type          id thumbnail   image alternate description year_published
   <dbl> <chr>      <dbl> <chr>       <chr> <chr>     <chr>                <dbl>
 1     0 boardgame     13 https://cf… http… ['Catan'… In CATAN (…           1995
 2     1 boardgame    822 https://cf… http… ['Carcas… Carcassonn…           2000
 3     2 boardgame  30549 https://cf… http… ['EPIZOo… In Pandemi…           2008
 4     3 boardgame  68448 https://cf… http… ['7 csod… You are th…           2010
 5     4 boardgame 167791 https://cf… http… ['A Mars… In the 240…           2016
 6     5 boardgame 266192 https://cf… http… ['Fesztá… Wingspan i…           2019
 7     6 boardgame 173346 https://cf… http… ['7 Csod… In many wa…           2015
 8     7 boardgame 230802 https://cf… http… ['Azul M… Introduced…           2017
 9     8 boardgame 178900 https://cf… http… ['Codena… Two rival …           2015
10     9 boardgame  36218 https://cf… http… ['Domini… &quot;You …           2008
# ℹ 27,770 more rows
# ℹ 44 more variables: minplayers <dbl>, max_players <dbl>,
#   suggested_num_players <chr>, suggested_playerage <chr>,
#   suggested_language_dependence <chr>, playingtime <dbl>, minplaytime <dbl>,
#   maxplaytime <dbl>, minage <dbl>, board_game_category <chr>,
#   boardgamemechanic <chr>, boardgamefamily <chr>, boardgameexpansion <chr>,
#   boardgameaccessory <chr>, boardgamecompilation <chr>, …

Step 3

board_games <-
  board_games |> 
  janitor::clean_names() |> 
  rename(
    index = x1,
    year_published = yearpublished,
    board_game_category = boardgamecategory,
    num_comments = numcomments,
    users_rated = usersrated,
    max_players = maxplayers,
    designer = boardgamedesigner
  )

Subsetting Data Frames

Subsetting Variables/Columns

Side-by-side schematic of a data frame and a subset of it. On the left, a table labeled data_frame shows four rows (1–4) and four columns named variable_1, variable_2, variable_3, and variable_4. The columns variable_2 and variable_3 are shaded in pink to indicate selection. On the right, a smaller table labeled select(data_frame, variable_2, variable_3) displays only the two shaded columns, variable_2 and variable_3, for the same four rows, illustrating how selecting columns reduces the data frame to those variables.

Column-wise subsetting can be done using select().

Subsetting Observations/Rows

Side-by-side schematic illustrating row selection in a data frame. On the left, a table labeled data_frame shows four rows (1–4) and four columns (variable_1 to variable_4). Rows 2 and 3 are shaded in pink to indicate they are selected, while rows 1 and 4 are unshaded. On the right, a smaller table labeled filter(data_frame, condition) and slice(data_frame, row_indices) displays only the selected rows (rows 2 and 3) with all four columns preserved, demonstrating how filtering or slicing keeps rows that meet a condition.

Row-wise subsetting can be done with slice() and filter()

select()

board_games |> 
  select(name, year_published, board_game_category, num_comments, users_rated, max_players)
# A tibble: 27,780 × 6
   name  year_published board_game_category num_comments users_rated max_players
   <chr>          <dbl> <chr>                      <dbl>       <dbl>       <dbl>
 1 CATAN           1995 ['Economic', 'Nego…        22600      132477           4
 2 Carc…           2000 ['Medieval', 'Terr…        22150      131182           5
 3 Pand…           2008 ['Medical']                19897      128935           4
 4 7 Wo…           2010 ['Ancient', 'Card …        16690      107506           7
 5 Terr…           2016 ['Economic', 'Envi…        14696      103923           5
 6 Wing…           2019 ['Animals', 'Card …        13335      100009           5
 7 7 Wo…           2015 ['Ancient', 'Card …        13122       99655           2
 8 Azul            2017 ['Abstract Strateg…        12071       96502           4
 9 Code…           2015 ['Card Game', 'Ded…        12566       96053           8
10 Domi…           2008 ['Card Game', 'Med…        15218       92958           4
# ℹ 27,770 more rows

select() is used to select certain variables in the data frame.

Dropping Variables

board_games |> 
  select(-index)
# A tibble: 27,780 × 51
   type       id thumbnail image alternate description year_published minplayers
   <chr>   <dbl> <chr>     <chr> <chr>     <chr>                <dbl>      <dbl>
 1 board…     13 https://… http… ['Catan'… In CATAN (…           1995          3
 2 board…    822 https://… http… ['Carcas… Carcassonn…           2000          2
 3 board…  30549 https://… http… ['EPIZOo… In Pandemi…           2008          2
 4 board…  68448 https://… http… ['7 csod… You are th…           2010          2
 5 board… 167791 https://… http… ['A Mars… In the 240…           2016          1
 6 board… 266192 https://… http… ['Fesztá… Wingspan i…           2019          1
 7 board… 173346 https://… http… ['7 Csod… In many wa…           2015          2
 8 board… 230802 https://… http… ['Azul M… Introduced…           2017          2
 9 board… 178900 https://… http… ['Codena… Two rival …           2015          2
10 board…  36218 https://… http… ['Domini… &quot;You …           2008          2
# ℹ 27,770 more rows
# ℹ 43 more variables: max_players <dbl>, suggested_num_players <chr>,
#   suggested_playerage <chr>, suggested_language_dependence <chr>,
#   playingtime <dbl>, minplaytime <dbl>, maxplaytime <dbl>, minage <dbl>,
#   board_game_category <chr>, boardgamemechanic <chr>, boardgamefamily <chr>,
#   boardgameexpansion <chr>, boardgameaccessory <chr>,
#   boardgamecompilation <chr>, boardgameimplementation <chr>, …

select() can also be used to drop variables.

Is type also an unnecessary variable?

Count

count(board_games, type)
# A tibble: 1 × 2
  type          n
  <chr>     <int>
1 boardgame 27780

Dropping Variables

board_games |> 
  select(-c(index, type))
# A tibble: 27,780 × 50
       id thumbnail        image alternate description year_published minplayers
    <dbl> <chr>            <chr> <chr>     <chr>                <dbl>      <dbl>
 1     13 https://cf.geek… http… ['Catan'… In CATAN (…           1995          3
 2    822 https://cf.geek… http… ['Carcas… Carcassonn…           2000          2
 3  30549 https://cf.geek… http… ['EPIZOo… In Pandemi…           2008          2
 4  68448 https://cf.geek… http… ['7 csod… You are th…           2010          2
 5 167791 https://cf.geek… http… ['A Mars… In the 240…           2016          1
 6 266192 https://cf.geek… http… ['Fesztá… Wingspan i…           2019          1
 7 173346 https://cf.geek… http… ['7 Csod… In many wa…           2015          2
 8 230802 https://cf.geek… http… ['Azul M… Introduced…           2017          2
 9 178900 https://cf.geek… http… ['Codena… Two rival …           2015          2
10  36218 https://cf.geek… http… ['Domini… &quot;You …           2008          2
# ℹ 27,770 more rows
# ℹ 43 more variables: max_players <dbl>, suggested_num_players <chr>,
#   suggested_playerage <chr>, suggested_language_dependence <chr>,
#   playingtime <dbl>, minplaytime <dbl>, maxplaytime <dbl>, minage <dbl>,
#   board_game_category <chr>, boardgamemechanic <chr>, boardgamefamily <chr>,
#   boardgameexpansion <chr>, boardgameaccessory <chr>,
#   boardgamecompilation <chr>, boardgameimplementation <chr>, …

Selection helpers

starts_with()
ends_with()
contains()

starts_with()

select(board_games, starts_with("boardgame"))
# A tibble: 27,780 × 9
   boardgamemechanic       boardgamefamily boardgameexpansion boardgameaccessory
   <chr>                   <chr>           <chr>              <chr>             
 1 ['Chaining', 'Dice Rol… "['Animals: Sh… "['20 Jahre Darms… "['Catan x Goat S…
 2 ['Area Majority / Infl… "['Category: D… "['20 Jahre Darms… "['The Adults of …
 3 ['Action Points', 'Coo… "['Components:… "['Pandemic: Gen … "['Pandemic: Fold…
 4 ['Closed Drafting', 'H… "['Ancient: Ba… "['7 Wonders: Arm… "['7 Wonders: Eur…
 5 ['Closed Drafting', 'C… "['Category: D… "['Meeple BR Jogo… "['Terraforming M…
 6 ['Action Queue', 'Dice… "['Animals: Bi… "['Frogmouth Fan … "['Na křídlech: D…
 7 ['End Game Bonuses', '… "['Ancient: Ba… "['7 Wonders Duel… "['7 Wonders Duel…
 8 ['End Game Bonuses', '… "['Components:… "['Azul: Crystal … "['Azul: 2 Player…
 9 ['Communication Limits… "['Components:… "['Brettspiel Adv… "['Codenames: Bro…
10 ['Deck, Bag, and Pool … "['Crowdfundin… "['Ancient Times … "['Dominion: Base…
# ℹ 27,770 more rows
# ℹ 5 more variables: boardgamecompilation <chr>,
#   boardgameimplementation <chr>, boardgameartist <chr>,
#   boardgamepublisher <chr>, boardgameintegration <chr>

ends_with()

select(board_games, ends_with("rank"))
# A tibble: 27,780 × 11
   board_game_rank strategy_game_rank family_game_rank abstract_game_rank
             <dbl>              <dbl>            <dbl>              <dbl>
 1             573                533              196                 NA
 2             230                 NA               55                 NA
 3             158                168               32                 NA
 4             101                111               18                 NA
 5               7                  7               NA                 NA
 6              32                 40                2                 NA
 7              20                 23               NA                 NA
 8              83                 NA               13                  2
 9             151                 NA               NA                 NA
10             139                136               NA                 NA
# ℹ 27,770 more rows
# ℹ 7 more variables: party_game_rank <dbl>, thematic_rank <dbl>,
#   war_game_rank <dbl>, customizable_rank <dbl>, childrens_game_rank <dbl>,
#   rpg_item_rank <lgl>, accessory_rank <lgl>

contains()

select(board_games, contains("game"))
# A tibble: 27,780 × 17
   board_game_category      boardgamemechanic boardgamefamily boardgameexpansion
   <chr>                    <chr>             <chr>           <chr>             
 1 ['Economic', 'Negotiati… ['Chaining', 'Di… "['Animals: Sh… "['20 Jahre Darms…
 2 ['Medieval', 'Territory… ['Area Majority … "['Category: D… "['20 Jahre Darms…
 3 ['Medical']              ['Action Points'… "['Components:… "['Pandemic: Gen …
 4 ['Ancient', 'Card Game'… ['Closed Draftin… "['Ancient: Ba… "['7 Wonders: Arm…
 5 ['Economic', 'Environme… ['Closed Draftin… "['Category: D… "['Meeple BR Jogo…
 6 ['Animals', 'Card Game'… ['Action Queue',… "['Animals: Bi… "['Frogmouth Fan …
 7 ['Ancient', 'Card Game'… ['End Game Bonus… "['Ancient: Ba… "['7 Wonders Duel…
 8 ['Abstract Strategy', '… ['End Game Bonus… "['Components:… "['Azul: Crystal …
 9 ['Card Game', 'Deductio… ['Communication … "['Components:… "['Brettspiel Adv…
10 ['Card Game', 'Medieval… ['Deck, Bag, and… "['Crowdfundin… "['Ancient Times …
# ℹ 27,770 more rows
# ℹ 13 more variables: boardgameaccessory <chr>, boardgamecompilation <chr>,
#   boardgameimplementation <chr>, boardgameartist <chr>,
#   boardgamepublisher <chr>, board_game_rank <dbl>, strategy_game_rank <dbl>,
#   family_game_rank <dbl>, boardgameintegration <chr>,
#   abstract_game_rank <dbl>, party_game_rank <dbl>, war_game_rank <dbl>,
#   childrens_game_rank <dbl>

“Save” data frame

board_games <- 
  board_games |> 
  select(
    name, 
    year_published, 
    board_game_category, 
    num_comments, 
    users_rated, 
    max_players, 
    designer
    )
glimpse(board_games)
Rows: 27,780
Columns: 7
$ name                <chr> "CATAN", "Carcassonne", "Pandemic", "7 Wonders", "…
$ year_published      <dbl> 1995, 2000, 2008, 2010, 2016, 2019, 2015, 2017, 20…
$ board_game_category <chr> "['Economic', 'Negotiation']", "['Medieval', 'Terr…
$ num_comments        <dbl> 22600, 22150, 19897, 16690, 14696, 13335, 13122, 1…
$ users_rated         <dbl> 132477, 131182, 128935, 107506, 103923, 100009, 99…
$ max_players         <dbl> 4, 5, 4, 7, 5, 5, 2, 4, 8, 4, 5, 5, 4, 5, 5, 5, 6,…
$ designer            <chr> "['Klaus Teuber']", "['Klaus-Jürgen Wrede']", "['M…

slice()

slice() subsets rows based on a row number.

The data below include all the rows from third to seventh, including the third and the seventh.

slice(board_games, 3:7)
# A tibble: 5 × 7
  name   year_published board_game_category num_comments users_rated max_players
  <chr>           <dbl> <chr>                      <dbl>       <dbl>       <dbl>
1 Pande…           2008 ['Medical']                19897      128935           4
2 7 Won…           2010 ['Ancient', 'Card …        16690      107506           7
3 Terra…           2016 ['Economic', 'Envi…        14696      103923           5
4 Wings…           2019 ['Animals', 'Card …        13335      100009           5
5 7 Won…           2015 ['Ancient', 'Card …        13122       99655           2
# ℹ 1 more variable: designer <chr>

Relational and Logical Operators

Operator Description
< Less than
> Greater than
<= Less than or equal to
>= Greater than or equal to
== Equal to
!= Not equal to
Operator Description
& and
| or

filter() - Example 1

filter() subsets rows based on a condition.

The data below includes rows when the publication year is 2004.

board_games |> 
  filter(year_published == 2024)
# A tibble: 973 × 7
   name  year_published board_game_category num_comments users_rated max_players
   <chr>          <dbl> <chr>                      <dbl>       <dbl>       <dbl>
 1 Harm…           2024 ['Animals', 'Envir…         1525       11448           4
 2 Wyrm…           2024 ['Animals', 'Card …         1415        8721           5
 3 Arcs            2024 ['Science Fiction'…         1623        7643           4
 4 The …           2024 ['Card Game', 'Fan…         1074        6771           2
 5 Slay…           2024 ['Adventure', 'Car…          974        4823           4
 6 Let'…           2024 ['Card Game', 'Tra…          780        3743           4
 7 MLEM…           2024 ['Animals', 'Dice'…          624        3586           5
 8 SETI…           2024 ['Science Fiction'…          617        3546           4
 9 Capt…           2024 ['Pirates']                  550        3419           5
10 Unco…           2024 ['Medical']                  840        3174           4
# ℹ 963 more rows
# ℹ 1 more variable: designer <chr>

Number of games - Example 1

How many games were published in 2024 based on this dataset?

board_games |> 
  filter(year_published == 2024) |> 
  nrow()
[1] 973

filter() - Example 2

How many games were in the Medical category and only in the Medical category?

board_games |> 
  filter(board_game_category == "['Medical']")
# A tibble: 9 × 7
  name   year_published board_game_category num_comments users_rated max_players
  <chr>           <dbl> <chr>                      <dbl>       <dbl>       <dbl>
1 Pande…           2008 ['Medical']                19897      128935           4
2 Uncon…           2024 ['Medical']                  840        3174           4
3 Quara…           2013 ['Medical']                  290         916           4
4 Headi…           2022 ['Medical']                   37         119           1
5 Trepa…           2023 ['Medical']                   27          95           5
6 Intern           1979 ['Medical']                   44          71           4
7 Code …           2018 ['Medical']                   17          43           4
8 Infec…           1998 ['Medical']                   12          34           8
9 Emerg…           2021 ['Medical']                   11          33           4
# ℹ 1 more variable: designer <chr>

Number of games - Example 2

How many games were in the Medical category and only in the Medical category?

board_games |> 
  filter(board_game_category == "['Medical']") |> 
  nrow()
[1] 9

filter() - Example 3

How many of the games published in 2024 were in the Medical category and only in the Medical category?

board_games |> 
  filter(year_published == 2024 & board_game_category == "['Medical']")
# A tibble: 1 × 7
  name   year_published board_game_category num_comments users_rated max_players
  <chr>           <dbl> <chr>                      <dbl>       <dbl>       <dbl>
1 Uncon…           2024 ['Medical']                  840        3174           4
# ℹ 1 more variable: designer <chr>

Number of games - Example 3

How many games were in the Medical category and only in the Medical category?

board_games |> 
  filter(year_published == 2024 & board_game_category == "['Medical']") |> 
  nrow()
[1] 1

filter() - Example 4

How many of the games were either published in 2024 or were in the Medical category and only in the Medical category?

board_games |> 
  filter(year_published == 2024 | board_game_category == "['Medical']")
# A tibble: 981 × 7
   name  year_published board_game_category num_comments users_rated max_players
   <chr>          <dbl> <chr>                      <dbl>       <dbl>       <dbl>
 1 Pand…           2008 ['Medical']                19897      128935           4
 2 Harm…           2024 ['Animals', 'Envir…         1525       11448           4
 3 Wyrm…           2024 ['Animals', 'Card …         1415        8721           5
 4 Arcs            2024 ['Science Fiction'…         1623        7643           4
 5 The …           2024 ['Card Game', 'Fan…         1074        6771           2
 6 Slay…           2024 ['Adventure', 'Car…          974        4823           4
 7 Let'…           2024 ['Card Game', 'Tra…          780        3743           4
 8 MLEM…           2024 ['Animals', 'Dice'…          624        3586           5
 9 SETI…           2024 ['Science Fiction'…          617        3546           4
10 Capt…           2024 ['Pirates']                  550        3419           5
# ℹ 971 more rows
# ℹ 1 more variable: designer <chr>

Number of games - Example 4

How many of the games were either published in 2024 or were in the Medical category and only in the Medical category?

board_games |> 
  filter(year_published == 2024 | board_game_category == "['Medical']") |> 
  nrow()
[1] 981

Multiple or statements with %in%

specific_years <- c(1995, 2004, 2016)


board_games |>
  filter(year_published %in% specific_years)
# A tibble: 2,138 × 7
   name  year_published board_game_category num_comments users_rated max_players
   <chr>          <dbl> <chr>                      <dbl>       <dbl>       <dbl>
 1 CATAN           1995 ['Economic', 'Nego…        22600      132477           4
 2 Terr…           2016 ['Economic', 'Envi…        14696      103923           5
 3 Tick…           2004 ['Trains']                 15064       92827           5
 4 Scyt…           2016 ['Economic', 'Figh…        12785       86921           5
 5 Powe…           2004 ['Economic', 'Indu…        11750       66812           6
 6 King…           2016 ['City Building', …         6915       49468           4
 7 Betr…           2004 ['Adventure', 'Exp…         9722       47586           6
 8 Arkh…           2016 ['Adventure', 'Car…         6970       44782           2
 9 Clan…           2016 ['Adventure', 'Fan…         5692       44050           4
10 Grea…           2016 ['American West', …         5378       41915           4
# ℹ 2,128 more rows
# ℹ 1 more variable: designer <chr>

Checking for NA values

board_games |> 
  filter(is.na(board_game_category))
# A tibble: 372 × 7
   name  year_published board_game_category num_comments users_rated max_players
   <chr>          <dbl> <chr>                      <dbl>       <dbl>       <dbl>
 1 Kelt…           2008 <NA>                        1390        6659           4
 2 Reav…           2019 <NA>                         671        3085           4
 3 Bad …           2021 <NA>                         519        2965           6
 4 Roya…           2014 <NA>                         647        2826           5
 5 Piec…           2008 <NA>                         726        2445           5
 6 Jórv…           2016 <NA>                         563        2351           5
 7 Coff…           2023 <NA>                         320        2206           4
 8 3 Ri…           2023 <NA>                         357        2176           4
 9 Bag …           2021 <NA>                         299        1879           5
10 Adve…           2019 <NA>                         415        1819           4
# ℹ 362 more rows
# ℹ 1 more variable: designer <chr>

Making Changes to Variables

Creating New Variables Using Operations Between Existing Variables

board_games |> 
  mutate(num_comments_k = num_comments/1000)
# A tibble: 27,780 × 8
   name  year_published board_game_category num_comments users_rated max_players
   <chr>          <dbl> <chr>                      <dbl>       <dbl>       <dbl>
 1 CATAN           1995 ['Economic', 'Nego…        22600      132477           4
 2 Carc…           2000 ['Medieval', 'Terr…        22150      131182           5
 3 Pand…           2008 ['Medical']                19897      128935           4
 4 7 Wo…           2010 ['Ancient', 'Card …        16690      107506           7
 5 Terr…           2016 ['Economic', 'Envi…        14696      103923           5
 6 Wing…           2019 ['Animals', 'Card …        13335      100009           5
 7 7 Wo…           2015 ['Ancient', 'Card …        13122       99655           2
 8 Azul            2017 ['Abstract Strateg…        12071       96502           4
 9 Code…           2015 ['Card Game', 'Ded…        12566       96053           8
10 Domi…           2008 ['Card Game', 'Med…        15218       92958           4
# ℹ 27,770 more rows
# ℹ 2 more variables: designer <chr>, num_comments_k <dbl>

Creating New Variables Using Operations Between Existing Variables

board_games |> 
  mutate(num_comments_k = num_comments/1000) |> 
  select(num_comments, num_comments_k)
# A tibble: 27,780 × 2
   num_comments num_comments_k
          <dbl>          <dbl>
 1        22600           22.6
 2        22150           22.2
 3        19897           19.9
 4        16690           16.7
 5        14696           14.7
 6        13335           13.3
 7        13122           13.1
 8        12071           12.1
 9        12566           12.6
10        15218           15.2
# ℹ 27,770 more rows

Creating New Variables Based on Conditions

board_games |> 
  mutate(
    popularity_class = if_else(
      users_rated >= 10000,
      "Highly popular",
      "Less popular"
    )
  ) |> 
  select(users_rated, popularity_class)
# A tibble: 27,780 × 2
   users_rated popularity_class
         <dbl> <chr>           
 1      132477 Highly popular  
 2      131182 Highly popular  
 3      128935 Highly popular  
 4      107506 Highly popular  
 5      103923 Highly popular  
 6      100009 Highly popular  
 7       99655 Highly popular  
 8       96502 Highly popular  
 9       96053 Highly popular  
10       92958 Highly popular  
# ℹ 27,770 more rows

if_else() summary

Flowchart illustrating an if–else decision. At the top is the text if_else(condition, do this, do that). A central pink rectangle labeled condition branches into two paths: to the left, labeled if TRUE, an arrow points down to a green circle labeled do this; to the right, labeled if FALSE, an arrow points down to a green circle labeled do that. The diagram shows how a condition determines which action is executed.

Figure 1

Creating New Variables Based on Conditions

board_games |> 
  mutate(
    popularity_level = case_when(
      users_rated < 1000 ~ "Fewer than 1,000 ratings",
      users_rated < 10000 ~ "1,000 to 9,999 ratings",
      users_rated < 50000 ~ "10,000 to 49,999 ratings",
      users_rated >= 50000 ~ "50,000 or more ratings",
      TRUE ~ "Missing"
    )
  ) |> 
  select(users_rated, popularity_level)
# A tibble: 27,780 × 2
   users_rated popularity_level      
         <dbl> <chr>                 
 1      132477 50,000 or more ratings
 2      131182 50,000 or more ratings
 3      128935 50,000 or more ratings
 4      107506 50,000 or more ratings
 5      103923 50,000 or more ratings
 6      100009 50,000 or more ratings
 7       99655 50,000 or more ratings
 8       96502 50,000 or more ratings
 9       96053 50,000 or more ratings
10       92958 50,000 or more ratings
# ℹ 27,770 more rows

case_when() summary

Flowchart illustrating case_when logic. At the top is the text case_when(condition1 ~ action1, condition2 ~ action2, condition3 ~ action3). A vertical sequence of pink rectangles labeled condition1, condition2, and condition3 represents conditions evaluated in order. For each condition, a rightward arrow labeled if TRUE leads to a green circle labeled action1, action2, or action3, respectively. If a condition is false, the flow continues downward to the next condition. If all conditions are false, a final arrow leads to a green circle labeled return NA. The diagram shows how the first true condition determines the returned action.

Figure 2

Changing Variable Type

board_games |> 
  mutate(
    popularity_level = case_when(
      users_rated < 1000 ~ "Fewer than 1,000 ratings",
      users_rated < 10000 ~ "1,000 to 9,999 ratings",
      users_rated < 50000 ~ "10,000 to 49,999 ratings",
      users_rated >= 50000 ~ "50,000 or more ratings",
      TRUE ~ "Missing"
    ),
    popularity_level = as.factor(popularity_level)
  )
# A tibble: 27,780 × 8
   name  year_published board_game_category num_comments users_rated max_players
   <chr>          <dbl> <chr>                      <dbl>       <dbl>       <dbl>
 1 CATAN           1995 ['Economic', 'Nego…        22600      132477           4
 2 Carc…           2000 ['Medieval', 'Terr…        22150      131182           5
 3 Pand…           2008 ['Medical']                19897      128935           4
 4 7 Wo…           2010 ['Ancient', 'Card …        16690      107506           7
 5 Terr…           2016 ['Economic', 'Envi…        14696      103923           5
 6 Wing…           2019 ['Animals', 'Card …        13335      100009           5
 7 7 Wo…           2015 ['Ancient', 'Card …        13122       99655           2
 8 Azul            2017 ['Abstract Strateg…        12071       96502           4
 9 Code…           2015 ['Card Game', 'Ded…        12566       96053           8
10 Domi…           2008 ['Card Game', 'Med…        15218       92958           4
# ℹ 27,770 more rows
# ℹ 2 more variables: designer <chr>, popularity_level <fct>

Changing variable types

as.factor() - makes a vector factor
as.numeric() - makes a vector numeric
as.integer() - makes a vector integer
as.double() - makes a vector double
as.character() - makes a vector character

Cleaning in one long chain

board_games <-
  board_games |> 
  janitor::clean_names() |> 
  rename(
    index = x1,
    year_published = yearpublished,
    board_game_category = boardgamecategory,
    num_comments = numcomments,
    users_rated = usersrated,
    max_players = maxplayers
  )|> 
  select(name, year_published, board_game_category, num_comments, users_rated, max_players) |> 
  mutate(
    popularity_class = if_else(
      users_rated >= 10000,
      "Highly popular",
      "Less popular"
    ),
    popularity_level = case_when(
      users_rated < 1000 ~ "Fewer than 1,000 ratings",
      users_rated < 10000 ~ "1,000 to 9,999 ratings",
      users_rated < 50000 ~ "10,000 to 49,999 ratings",
      users_rated >= 50000 ~ "50,000 or more ratings",
      TRUE ~ "Missing"
    ),
    popularity_level = as.factor(popularity_level)
  ) 

Cleaning in one long chain - glimpse

glimpse(board_games)
Rows: 27,780
Columns: 8
$ name                <chr> "CATAN", "Carcassonne", "Pandemic", "7 Wonders", "…
$ year_published      <dbl> 1995, 2000, 2008, 2010, 2016, 2019, 2015, 2017, 20…
$ board_game_category <chr> "['Economic', 'Negotiation']", "['Medieval', 'Terr…
$ num_comments        <dbl> 22600, 22150, 19897, 16690, 14696, 13335, 13122, 1…
$ users_rated         <dbl> 132477, 131182, 128935, 107506, 103923, 100009, 99…
$ max_players         <dbl> 4, 5, 4, 7, 5, 5, 2, 4, 8, 4, 5, 5, 4, 5, 5, 5, 6,…
$ popularity_class    <chr> "Highly popular", "Highly popular", "Highly popula…
$ popularity_level    <fct> "50,000 or more ratings", "50,000 or more ratings"…

Pay attention to first argument

The functions clean_names(), select(), filter(), mutate() all take a data frame as the first argument. Even though we do not see it, the data frame is piped through from the previous step of code at each step. When we use these functions without the |> we have to include the data frame explicitly.

Data frame is used as the first argument

clean_names(board_games)

Data frame is piped

board_games |> 
  clean_names()

Aggregating Data

Data vs. Aggregate Data

Data

Observations

Aggregate Data

Summaries of observations

Aggregating Categorical Data

Categorical data are summarized with counts or proportions.

Counts and proportions

board_games |> 
  count(popularity_level)
# A tibble: 4 × 2
  popularity_level             n
  <fct>                    <int>
1 1,000 to 9,999 ratings    3346
2 10,000 to 49,999 ratings   451
3 50,000 or more ratings      38
4 Fewer than 1,000 ratings 23945
board_games |> 
  count(popularity_level) |> 
  mutate(prop = n/sum(n))
# A tibble: 4 × 3
  popularity_level             n    prop
  <fct>                    <int>   <dbl>
1 1,000 to 9,999 ratings    3346 0.120  
2 10,000 to 49,999 ratings   451 0.0162 
3 50,000 or more ratings      38 0.00137
4 Fewer than 1,000 ratings 23945 0.862  

Aggregating Numerical Data

Mean, median, standard deviation, variance, and quartiles are some of the numerical summaries of numerical variables. Recall

summarize(board_games, 
          mean_num_comments = mean(num_comments),
          sd_num_comments = sd(num_comments))
# A tibble: 1 × 2
  mean_num_comments sd_num_comments
              <dbl>           <dbl>
1              217.            718.

Aggregating Data By Groups

Side-by-side schematic illustrating grouping in a data frame. On the left, a table labeled data_frame shows four rows (1–4) and four columns (variable_1 to variable_4). Values in variable_2 are highlighted with two colors, indicating two groups: rows 1 and 4 share one group, and rows 2 and 3 share another. On the right, a table labeled group_by(data_frame, variable_2) shows the same data with all columns present, but rows are visually grouped by variable_2, using the same colors across all columns to indicate group membership.

Figure 3: Grouping a data frame by a specific variable

group_by() separates the data frame by the groups. Any action following group_by() will be completed for each group separately.

Example

Q. What is the median number of comments for each popularity level?

Example

board_games |> 
  group_by(popularity_level)
# A tibble: 27,780 × 8
# Groups:   popularity_level [4]
   name  year_published board_game_category num_comments users_rated max_players
   <chr>          <dbl> <chr>                      <dbl>       <dbl>       <dbl>
 1 CATAN           1995 ['Economic', 'Nego…        22600      132477           4
 2 Carc…           2000 ['Medieval', 'Terr…        22150      131182           5
 3 Pand…           2008 ['Medical']                19897      128935           4
 4 7 Wo…           2010 ['Ancient', 'Card …        16690      107506           7
 5 Terr…           2016 ['Economic', 'Envi…        14696      103923           5
 6 Wing…           2019 ['Animals', 'Card …        13335      100009           5
 7 7 Wo…           2015 ['Ancient', 'Card …        13122       99655           2
 8 Azul            2017 ['Abstract Strateg…        12071       96502           4
 9 Code…           2015 ['Card Game', 'Ded…        12566       96053           8
10 Domi…           2008 ['Card Game', 'Med…        15218       92958           4
# ℹ 27,770 more rows
# ℹ 2 more variables: popularity_class <chr>, popularity_level <fct>

Example

Note that when group_by() is used there have been no changes to the number of columns or rows. The only difference we can observe is now Groups: popularity_level[4] is displayed indicating the data frame (i.e., tibble) is divided into three groups.

Example

board_games |> 
  group_by(popularity_level) |> 
  summarize(med_num_comments = median(num_comments))
# A tibble: 4 × 2
  popularity_level         med_num_comments
  <fct>                               <dbl>
1 1,000 to 9,999 ratings               554 
2 10,000 to 49,999 ratings            3219 
3 50,000 or more ratings             11214.
4 Fewer than 1,000 ratings              40 

Example

We can also add how many board games there were in each group.

board_games |> 
  group_by(popularity_level) |> 
  summarize(med_num_comments = median(num_comments),
            count = n())
# A tibble: 4 × 3
  popularity_level         med_num_comments count
  <fct>                               <dbl> <int>
1 1,000 to 9,999 ratings               554   3346
2 10,000 to 49,999 ratings            3219    451
3 50,000 or more ratings             11214.    38
4 Fewer than 1,000 ratings              40  23945

Note that n() does not take any arguments.