Foundations of
Data Science

Spring 2026 | Data 2 (399)
Jeffrey M. Girard | Lecture 04c

Setup

library(tidyverse)
data("starwars", package = "dplyr")
glimpse(starwars)
Rows: 87
Columns: 14
$ name       <chr> "Luke Skywalker", "C-3PO", "R2-D2", "Darth Vader", "Leia Or…
$ height     <int> 172, 167, 96, 202, 150, 178, 165, 97, 183, 182, 188, 180, 2…
$ mass       <dbl> 77.0, 75.0, 32.0, 136.0, 49.0, 120.0, 75.0, 32.0, 84.0, 77.…
$ hair_color <chr> "blond", NA, NA, "none", "brown", "brown, grey", "brown", N…
$ skin_color <chr> "fair", "gold", "white, blue", "white", "light", "light", "…
$ eye_color  <chr> "blue", "yellow", "red", "yellow", "brown", "blue", "blue",…
$ birth_year <dbl> 19.0, 112.0, 33.0, 41.9, 19.0, 52.0, 47.0, NA, 24.0, 57.0, …
$ sex        <chr> "male", "none", "none", "male", "female", "male", "female",…
$ gender     <chr> "masculine", "masculine", "masculine", "masculine", "femini…
$ homeworld  <chr> "Tatooine", "Tatooine", "Naboo", "Tatooine", "Alderaan", "T…
$ species    <chr> "Human", "Droid", "Droid", "Human", "Human", "Human", "Huma…
$ films      <list> <"A New Hope", "The Empire Strikes Back", "Return of the J…
$ vehicles   <list> <"Snowspeeder", "Imperial Speeder Bike">, <>, <>, <>, "Imp…
$ starships  <list> <"X-wing", "Imperial shuttle">, <>, <>, "TIE Advanced x1",…

Roadmap

  • Use the pipe (|>) to efficiently pass an object to a function

  • Build a pipeline by connecting multiple pipes together

The Pipe

The Pipe Operator

  • The pipe passes the object on the left to the
    first argument of the function on the right
    • Think of it as reading “and then…”
    • e.g., take x and then square root it
  • Why use it?
    1. Readability: Code reads left-to-right (like English), not inside-out (like math functions).
    2. Cleanliness: Avoids creating temporary variables for every single step.

RStudio Setup & Shortcuts

  1. Configure RStudio
    • Go to Tools > Global Options
    • Click Code (on the left)
    • Check box: “Use native pipe operator”
    • Click Apply / OK
  2. Keyboard Shortcut
    • Let RStudio insert |> for you
    • Win: Ctrl+Shift+M
    • Mac: Cmd+Shift+M
    • Without the setting above, you get %>% which is similar but requires tidyverse to be loaded

Piping to a simple function

# Traditional way
sqrt(100)
[1] 10
# Piped way
100 |> sqrt()
[1] 10
# Saving the output
x <- 100 |> sqrt()
x
[1] 10

Piping with extra arguments

# Traditional way
round(3.14159, digits = 2)
[1] 3.14
# Piped way
3.14159 |> round(digits = 2)
[1] 3.14
# Be careful not to give x twice
x <- 3.14159 
x |> round(x, digits = 2)
Error in `round()`:
! unused argument (3.14159)

Piping to other arguments

seq(from = 1, to = 10)
 [1]  1  2  3  4  5  6  7  8  9 10
# The pipe defaults to filling in the *first* argument of the function
1 |> 
  seq(to = 10)
 [1]  1  2  3  4  5  6  7  8  9 10
# But, if needed, we can use the _ placeholder to pipe to a different argument
10 |> 
  seq(from = 1, to = _)
 [1]  1  2  3  4  5  6  7  8  9 10

Bridging to dplyr

# Traditional way (hard to read)
x <- select(starwars, name, species, homeworld)
# Piped way ("Take starwars AND THEN select...")
x <- 
  starwars |> 
  select(name, species, homeworld)
x
# A tibble: 87 × 3
  name           species homeworld
  <chr>          <chr>   <chr>    
1 Luke Skywalker Human   Tatooine 
2 C-3PO          Droid   Tatooine 
3 R2-D2          Droid   Naboo    
4 Darth Vader    Human   Tatooine 
5 Leia Organa    Human   Alderaan 
# ℹ 82 more rows

Pipelines

Building Pipelines

  • We rarely do just one thing to data
    • We usually want to filter, and then select, and then arrange…
  • We can chain multiple pipes together
    • This is called building a pipeline
    • The result of each line becomes the input for the next line, creating a kind of “assembly line”

Formatting Tip:

Add a line break after each pipe |> and then indent the next line. RStudio will do this automatically.

Traditional Approaches

Intermediate Assignment

# Error-prone: easy to use wrong variable name or overwrite data
x <- 100
y <- sqrt(x)
z <- log(y, base = 2)
z
[1] 3.321928

Nested Functions

# Difficult to read and add on to, especially as this gets longer
z <- log(sqrt(100), base = 2)
z
[1] 3.321928

Compare: The Pipeline

# Clean, linear, and easy to read and add on to
z <- 
  100 |> 
  sqrt() |> 
  log(base = 2)
z
[1] 3.321928
# We can even add print to the end to save and print
z <- 
  100 |> 
  sqrt() |> 
  log(base = 2) |> 
  print()
[1] 3.321928

Data Pipeline 1

# What are the names and genders of all the Droids?
out <- 
  starwars |> 
  filter(species == "Droid") |> 
  select(name, gender) |> 
  print()
# A tibble: 6 × 2
  name   gender   
  <chr>  <chr>    
1 C-3PO  masculine
2 R2-D2  masculine
3 R5-D4  masculine
4 IG-88  masculine
5 R4-P17 feminine 
# ℹ 1 more row

Data Pipeline 2

# Which characters have a BMI (Body Mass Index) greater than 30?
out <- 
  starwars |> 
  mutate(bmi = mass / ((height / 100)^2)) |> 
  filter(bmi > 30) |> 
  arrange(desc(bmi)) |> 
  select(name, bmi, mass, height) |> 
  print()
# A tibble: 12 × 4
  name                    bmi  mass height
  <chr>                 <dbl> <dbl>  <int>
1 Jabba Desilijic Tiure 443.   1358    175
2 Dud Bolt               50.9    45     94
3 Yoda                   39.0    17     66
4 Owen Lars              37.9   120    178
5 IG-88                  35     140    200
# ℹ 7 more rows

Data Pipeline 3

# What unique homeworlds are represented by the Human characters?
out <-
  starwars |>
  filter(species == "Human") |>
  distinct(homeworld) |>
  arrange(homeworld) |>
  print()
# A tibble: 15 × 1
  homeworld   
  <chr>       
1 Alderaan    
2 Bespin      
3 Chandrila   
4 Concord Dawn
5 Corellia    
# ℹ 10 more rows

Data Pipeline 4

# Which non-humans are shorter than 100cm? (Rename height for clarity)
out <-
  starwars |>
  filter(species != "Human", height < 100) |>
  rename(height_cm = height) |> 
  select(name, species, height_cm) |>
  print()
# A tibble: 7 × 3
  name                  species        height_cm
  <chr>                 <chr>              <int>
1 R2-D2                 Droid                 96
2 R5-D4                 Droid                 97
3 Yoda                  Yoda's species        66
4 Wicket Systri Warrick Ewok                  88
5 Ratts Tyerel          Aleena                79
# ℹ 2 more rows