Checkpoint: R Basics
Reviewed & published by Brayan K
A checkpoint is a consolidation lesson where you prove you can combine the skills from the previous module — here, the core of base R — by solving a realistic, multi-step problem.
Part of the free R course at LearnCodingFast — hands-on lessons with worked examples and the output they print, plus practice exercises and a quick quiz.
You'll recap data types, subsetting, missing data, vectorization, regex, frequency tables, error handling, and environments, then tackle a build challenge that chains them together and test yourself with a short quiz.
What This Checkpoint Covers
- Data types & classes, and coercion
- Subsetting with [ ], [[ ]], and $
- Missing data: is.na() and na.rm
- Vectorization over explicit loops
- Regex cleaning with grepl/gsub
- Frequency tables, error handling, environments
1️⃣ The 60-Second Recap
Every idea from R Basics, in one runnable block. If any line surprises you, that's your cue to revisit the matching lesson.
# A 60-second tour of everything in R Basics.
# Data types & classes
class(42L) # -> [1] "integer"
class("hi") # -> [1] "character"
# Subsetting
v <- c(a = 1, b = 2, c = 3)
v["b"] # by name; v[v > 1] filters; lst[[1]] / lst$x dig in
# Missing data
mean(c(1, NA, 3), na.rm = TRUE) # -> [1] 2
# Vectorization
c(1, 2, 3) * 10 # -> [1] 10 20 30 (no loop needed)
# Regex
grepl("^a", c("apple", "berry")) # -> [1] TRUE FALSE
# Frequency tables
table(c("x", "y", "x")) # counts each category
# Error handling
tryCatch(log(-1), warning = function(w) NA) # catches the NaN warning
# Environments
counter <- 0; bump <- function() counter <<- counter + 1Your turn. This warm-up chains three of the ideas above — vectorized arithmetic, an NA-aware mean, and a logical mask for subsetting — on one small named vector. Replace each ___ with the value in its hint, then run it and compare with the output panel.
# 🎯 YOUR TURN — replace each ___ then run it.
# Combines three ideas from this module: vectorization, missing data, subsetting.
# A week of daily high temperatures in Celsius. Tuesday's sensor failed.
temps_c <- c(mon = 18, tue = NA, wed = 24, thu = 27, fri = 21)
# 1) Convert EVERY reading to Fahrenheit in one vectorized line: F = C * 9/5 + 32
temps_f <- temps_c ___ 9/5 + 32 # 👉 replace ___ with *
print(temps_f)
# 2) Average the week, ignoring the missing Tuesday reading
avg_f <- mean(temps_f, na.rm = ___) # 👉 replace ___ with TRUE
print(avg_f)
# 3) Keep only the days warmer than 75F — the !is.na() mask drops the NA first
warm <- temps_f[!is.na(temps_f) & temps_f ___ 75] # 👉 replace ___ with >
print(names(warm))
# ✅ Expected output:
# mon tue wed thu fri
# 64.4 NA 75.2 80.6 69.8
# [1] 72.5
# [1] "wed" "thu"2️⃣ Build Challenge: Clean a Survey Column
This single task chains regex cleaning, type coercion, NA handling, and a frequency table — the exact pipeline you'll run on real data. Fill in the three blanks, run it, and predict the output before you check the solution.
# 🎯 BUILD CHALLENGE: clean a messy survey column.
#
# You are given raw text responses to "How many pets?".
# Some are blank ("") and some have stray words.
raw <- c("2", "", "3 cats", "1", "", "two", "4")
# GOAL — produce, step by step:
# 1) A cleaned NUMERIC vector with text/blanks turned to NA.
# 2) The mean number of pets, ignoring NA.
# 3) A frequency table of the valid counts.
#
# HINTS:
# - gsub("[^0-9]", "", x) strips non-digits ("3 cats" -> "3", "two" -> "").
# - as.numeric("") and as.numeric("") give NA (with a warning) — good!
# - mean(x, na.rm = TRUE) for the average.
# - table(x) for the frequency table (drops NA automatically).
#
# Fill in the blanks:
digits <- gsub("[^0-9]", "", raw) # keep only digit characters
nums <- as.numeric(___) # 👉 replace ___ with digits
avg <- mean(nums, na.rm = ___) # 👉 replace ___ with TRUE
counts <- table(___) # 👉 replace ___ with nums
print(nums)
print(avg)
print(counts)Here's a complete, commented solution. The key moves: gsub("[^0-9]", "", raw) keeps only digits, coercing the leftover blanks to NA, then na.rm = TRUE and table() summarise the clean data.
Run it in RStudio or rdrr.io/snippets to confirm every line.
3️⃣ Checkpoint Quiz
Answer each in your head first, then expand to check. If you miss one, the topic in brackets tells you which lesson to revisit.
📝 Checkpoint Quiz
"character". A vector holds one type, so R coerces everything to the most flexible present — and character can represent any value, so it wins over numeric and logical.
lst[["a"]] or lst$a. Single brackets lst["a"] would keep the list wrapper; [[ ]] and $ extract the element itself.
NA propagates — any arithmetic touching it is unknown. Add na.rm = TRUE: sum(c(1, NA, 3), na.rm = TRUE) gives 4.
x + 1. The single value 1 is recycled across every element, so no loop is needed.
"12". The negated class [^0-9] matches every non-digit, and gsub deletes them all, leaving only the digits.
The first creates/updates a local count that disappears when the function returns. The second (<<-) reaches outward to update an existing count in an enclosing environment.
Pro Tips for Consolidating
- 💡 Teach it: explaining each topic aloud in one sentence is the fastest test of real understanding.
- 💡 Re-run with new data: swap the build-challenge raw vector for your own messy values and confirm the pipeline still works.
- 💡 Keep a cheat sheet: jot the one-liner for each skill — it becomes muscle memory surprisingly fast.
🎉 Checkpoint Complete!
- ✅ You recapped types, subsetting, NA, vectorization, regex, tables, errors, and environments
- ✅ You built a real cleaning pipeline: regex → coerce → NA handling → frequency table
- ✅ You tested yourself with the checkpoint quiz and found any gaps
- ✅ The build-challenge pattern mirrors how genuine data analysis flows
Practice quiz
What does class(c(1, "2", TRUE)) return?
- "numeric"
- "logical"
- "character"
- "list"
Answer: "character". A vector holds a single type, so R coerces to the most flexible present — character can represent any value, so it wins.
Given lst <- list(a = 1:3), which expression returns the bare vector 1 2 3?
- lst[["a"]]
- lst["a"]
- lst[1:3]
- lst@a
Answer: lst[["a"]]. Double brackets [[ ]] (or $) extract the element itself; single brackets ["a"] keep the list wrapper.
What is the result of sum(c(1, NA, 3))?
- 4
- 0
- An error
- NA
Answer: NA. NA propagates through arithmetic. Add na.rm = TRUE to ignore it and get 4.
How do you make mean(c(1, NA, 3)) return 2 instead of NA?
- Use mean(c(1, NA, 3), skip = TRUE)
- Use mean(c(1, NA, 3), na.rm = TRUE)
- Wrap it in suppressWarnings()
- Use na.omit() on the result
Answer: Use mean(c(1, NA, 3), na.rm = TRUE). na.rm = TRUE drops NA values before computing, so the mean of 1 and 3 is 2.
What is the idiomatic, vectorized way to add 1 to every element of x?
- x + 1
- for (i in x) i + 1
- sapply(x, +1)
- add(x, 1)
Answer: x + 1. The scalar 1 is recycled across every element, so no loop is needed — that is vectorization.
What does gsub("[^0-9]", "", "a1b2") produce?
- "ab"
- "a1b2"
- "12"
- "1 2"
Answer: "12". The negated class [^0-9] matches every non-digit, and gsub deletes them, leaving only the digits.
What does grepl("^a", c("apple", "berry")) return?
- c(FALSE, TRUE)
- c(TRUE, FALSE)
- c(TRUE, TRUE)
- "apple"
Answer: c(TRUE, FALSE). ^a anchors the match to the start of the string, so only "apple" matches.
What does table(c("x", "y", "x")) compute?
- The sum of the values
- The unique values only
- An error (non-numeric)
- A frequency count of each category
Answer: A frequency count of each category. table() builds a contingency table — here counting x twice and y once.
Inside a function, what does count <<- count + 1 do differently from count <- count + 1?
- Nothing — they are identical
- <<- reaches outward to update count in an enclosing environment
- <<- creates a faster local copy
- <<- deletes count after assignment
Answer: <<- reaches outward to update count in an enclosing environment. The super-assignment <<- modifies an existing variable in an enclosing/global environment instead of creating a local one.
What does tryCatch(log(-1), warning = function(w) NA) return?
- NaN
- An error
- NA
- -Inf
Answer: NA. log(-1) raises a warning, which the handler catches and replaces with NA.
Continue this course
- Previous: Environments & Scoping
- Next: Tibbles (Modern Data Frames) — The tidyverse data frame — nicer printing and no surprising conversions
- Quick reference: R cheat sheet
Frequently asked questions
What should I be able to do after this checkpoint?
You should be able to identify and convert data types, subset vectors and lists with [ ], [[ ]], and $, detect and handle missing values with is.na() and na.rm, replace explicit loops with vectorized operations, clean strings with regular expressions, summarise categories with table() and prop.table(), guard code with tryCatch() and stopifnot(), and reason about where R looks up variables. The build challenge above weaves several of these together, which is exactly how real data work feels.
I'm shaky on one topic — what should I do?
Go back to that specific lesson and redo its 'Your Turn' and Mini-Challenge with fresh data, then try to explain the idea out loud in one sentence. The fastest way to find a weak spot is the checkpoint quiz below: any question you cannot answer immediately points you straight to the lesson to revisit. Spacing your review over a couple of days helps far more than one long session.
Why does the build challenge combine cleaning, regex, and tables?
Because that is the shape of nearly every real analysis: raw data arrives messy, you scrub it (regex and type coercion), you handle the gaps (NA), and then you summarise it (a frequency table or mean). Practising the steps in isolation builds the skills; chaining them in one task builds the workflow. If you can complete this challenge unaided, you have the core of practical base R.
What comes after R Basics?
Next you move into the modern data-handling toolkit, starting with tibbles — a friendlier kind of data frame — and continuing into the tidyverse for manipulation, summarising, joining, and plotting. Everything you mastered here (types, subsetting, NA handling, vectorization) underpins those tools, so this checkpoint is the launchpad rather than the finish line.