Week 7 Live Session (Fall 2026)
This lesson is called Week 7 Live Session (Fall 2026), part of the R in 3 Months (Fall 2026) course. This lesson is called Week 7 Live Session (Fall 2026), part of the R in 3 Months (Fall 2026) course.
Transcript
Click on the transcript to go to that point in the video. Please note that transcripts are auto generated and may contain minor inaccuracies.
Loading transcript...
We started with a short review of tidy data and factors, then spent most of the session on functions. We explained why ggplot code works without argument names, built our own function to tidy spreadsheet data by year, and ran it across several years at once.
You'll learn:
- How factors store levels as metadata that control the order categories appear in a plot, unlike character columns, which sort alphabetically
- How R matches unnamed arguments by position, and why x and y in aes() can be left unnamed but color cannot
- How to turn repeated code into a function with a name, an argument such as year, and a body, and why a single edit then updates every use
- How to keep functions in a separate R script and load them with source() so an import script stays short
- How to run a function across many years with map() and bind_rows(), and why a function argument that is never used does not cause an error
Resources mentioned:
- {tidyverse}
- {ggplot2}
- {readxl}
- {janitor}
- {stringr}
- {forcats}
- {purrr}
- {dplyr}
- {tidyr}
- Positron
- Quarto
Key moments:
- 03:30 Participants share functions they might write
- 09:52 Question on what factors are, from the gss_cat data
- 14:15 Factor levels set bar order in a ggplot chart
- 17:38 Character version sorts alphabetically instead
- 19:59 Why to save data as RDS to keep factors
- 21:34 Why argument names are sometimes left out
- 28:15 Starting a function to tidy the Excel data
- 38:46 Turning the code into a function with a year argument
- 45:46 Storing functions in a separate script with source()
- 49:02 Running the function for many years with map() and bind_rows()
- 53:24 Question on how to know when you need a function
- 55:35 Quiz on why an unused argument causes no error
View code shown in video
The code for the function I created is below:
tidy_gender_age_data <- function(year) {
raw_data_path <-
str_glue("data-raw/{year}-obtn-by-county.xlsx")
read_excel(
path = raw_data_path,
sheet = "Gender Age"
) |>
clean_names() |>
pivot_longer(
cols = -geography,
values_to = "pct"
) |>
separate_wider_delim(
cols = name,
delim = "_",
names = c("gender", "min_age", "max_age"),
too_few = "align_start"
) |>
mutate(age = str_glue("{min_age}-{max_age}")) |>
mutate(age = str_replace(age, pattern = "-NA", "+")) |>
select(geography, gender, age, pct) |>
mutate(age = fct_inorder(age)) |>
mutate(data_year = year)
}
And the code to import multiple years of data is here:
library(tidyverse)
library(readxl)
library(janitor)
source("R/functions.R")
obtn_gender_age_2019 <-
tidy_gender_age_data(year = 2019)
obtn_gender_age_2020 <-
tidy_gender_age_data(year = 2020)
tidy_gender_age_data(year = 2020)
years <- seq(from = 2019, to = 2023, by = 1)
map(years, tidy_gender_age_data) |>
bind_rows()
Have any questions? Put them below and we will help you out!
Course Content
143 Lessons
You need to be signed-in to comment on this post. Login.