R Basics Exercises: 15 Practice Problems for Beginners (With Solutions)
The best way to learn R is to write R. These 15 exercises cover variables, operators, functions, vectors, and type conversions — everything from the R Syntax 101 tutorial. Each problem has an interactive code block where you write your solution, plus a collapsible answer.
Try each exercise yourself before looking at the solution. Writing code from scratch — even struggling with it — builds muscle memory that reading alone can't.
How to Use These Exercises
Read the problem description
Write your solution in the interactive code block
Click Run to test it
If stuck, check the hint
Compare with the solution (click to reveal)
Exercises are grouped by difficulty: Easy (1-5), Medium (6-10), Hard (11-15).
Easy (1-5): Variables and Basic Operations
Exercise 1: Variable Assignment
Create three variables: name (your name as text), age (your age as a number), and is_student (TRUE or FALSE). Print all three using cat().
# Exercise 1: Create and print three variables
# Expected output (example):
# Name: Alice
# Age: 25
# Student: TRUE
# Write your code below:
Click to reveal solution
# Solution
name <- "Alice"
age <- 25
is_student <- TRUE
cat("Name:", name, "\n")
cat("Age:", age, "\n")
cat("Student:", is_student, "\n")
Key concept: Use <- for assignment. Character values need quotes. Logical values are TRUE/FALSE (uppercase, no quotes).
Exercise 2: Arithmetic Calculator
A pizza costs $12.99 and you're ordering for 7 people. Calculate: the subtotal, the tax (8.5%), the tip (18% of subtotal), and the total. Print each value rounded to 2 decimal places.
# Exercise 2: Pizza order calculator
# Pizza price: $12.99 per person
# People: 7
# Tax rate: 8.5%
# Tip: 18% of subtotal (before tax)
# Write your code below:
Key concept: R has built-in functions for all common statistics. length() counts elements, not count() or len().
Exercise 5: String Operations
Create a first name and last name variable. Combine them into a full name using paste(). Then print the full name in uppercase and its character count.
# Exercise 5: String operations
# Create first_name and last_name
# Combine into full_name
# Print uppercase version and character count
Key concept:scores >= 70 creates a logical vector. Use it to filter both scores and students. !passed flips TRUE/FALSE.
Exercise 7: Sequence Generation
Create these sequences without typing every number:
1 to 20
Even numbers from 2 to 20
5, 10, 15, ..., 100
1 repeated 10 times
The pattern 1, 2, 3, 1, 2, 3, 1, 2, 3
# Exercise 7: Create sequences efficiently
# Don't type out every number — use :, seq(), and rep()
Click to reveal solution
# Solution
cat("1 to 20:", 1:20, "\n\n")
cat("Even 2-20:", seq(2, 20, by = 2), "\n\n")
cat("5 to 100 by 5:", seq(5, 100, by = 5), "\n\n")
cat("1 repeated 10x:", rep(1, 10), "\n\n")
cat("1,2,3 pattern:", rep(1:3, times = 3), "\n")
Key concept:: for simple integer sequences. seq() for custom step sizes. rep() for repetition — times repeats the whole vector, each repeats each element.
Exercise 8: Named Vectors as Lookup Tables
Create a named vector mapping country codes to country names (US, UK, DE, JP, BR). Then look up the full name for "DE" and "JP".
# Exercise 8: Country code lookup
# Create a named vector: codes → full names
# Look up "DE" and "JP"
Click to reveal solution
# Solution
countries <- c(
US = "United States",
UK = "United Kingdom",
DE = "Germany",
JP = "Japan",
BR = "Brazil"
)
cat("DE:", countries["DE"], "\n")
cat("JP:", countries["JP"], "\n")
# Bonus: look up multiple at once
codes_to_find <- c("US", "BR", "JP")
cat("Multiple:", countries[codes_to_find], "\n")
Key concept: Named vectors work as key-value lookup tables. countries["DE"] returns the value associated with the name "DE".
Exercise 9: Type Detective
Predict the type of each value, then verify with class(). Some are tricky!
# Exercise 9: Predict the type, then verify
a <- 42
b <- 42L
c <- "42"
d <- TRUE
e <- 4 + 2i
f <- c(1, 2, "3")
g <- c(TRUE, FALSE, 0)
# Predict each type, then uncomment to check:
# cat("a:", class(a), "\n")
# cat("b:", class(b), "\n")
# cat("c:", class(c), "\n")
# cat("d:", class(d), "\n")
# cat("e:", class(e), "\n")
# cat("f:", class(f), "\n")
# cat("g:", class(g), "\n")
Click to reveal solution
# Solution
a <- 42 # numeric (not integer — no L)
b <- 42L # integer (L suffix)
c <- "42" # character (quotes)
d <- TRUE # logical
e <- 4 + 2i # complex
f <- c(1, 2, "3") # character (coercion: string wins)
g <- c(TRUE, FALSE, 0) # numeric (coercion: numeric wins over logical)
cat("a (42):", class(a), "\n")
cat("b (42L):", class(b), "\n")
cat("c ('42'):", class(c), "\n")
cat("d (TRUE):", class(d), "\n")
cat("e (4+2i):", class(e), "\n")
cat("f (1,2,'3'):", class(f), "← string coerces everything\n")
cat("g (T,F,0):", class(g), "← numeric coerces logical\n")
Key concept: When mixing types in c(), R coerces to the most flexible: logical → integer → numeric → character.
Exercise 10: Vector Math
Convert temperatures from Fahrenheit to Celsius for an entire week, then find the hottest and coldest days.
# Exercise 10: Temperature conversion
days <- c("Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun")
temps_f <- c(72, 68, 75, 80, 85, 70, 65)
# 1. Convert to Celsius: C = (F - 32) * 5/9
# 2. Find hottest and coldest day (by name)
# 3. How many days were above 25°C?
Key concept:(temps_f - 32) * 5/9 converts ALL temperatures at once — R applies math to every vector element automatically.
Hard (11-15): Combined Skills
Exercise 11: Grade Calculator Function
Write a function that takes a numeric score (0-100) and returns a letter grade: A (90+), B (80+), C (70+), D (60+), F (<60). Test it on a vector of scores.
# Exercise 11: Grade calculator
# Write a function get_grade(score) that returns "A", "B", "C", "D", or "F"
# Then apply it to: scores <- c(95, 82, 73, 61, 55, 88, 77, 100, 42, 90)
Key concept:gsub("\\$", "", x) removes dollar signs ($ is special in regex, so escape with \\). %in% checks membership. na.rm = TRUE ignores NAs in calculations.
Exercise 13: BMI Calculator with Validation
Write a BMI calculator function that validates inputs, handles edge cases, and categorizes the result.
# Solution
bmi_report <- function(weight_kg, height_m) {
# Validate
if (!is.numeric(weight_kg) || !is.numeric(height_m)) {
return("Error: weight and height must be numbers")
}
if (weight_kg <= 0 || height_m <= 0) {
return("Error: weight and height must be positive")
}
if (height_m > 3) {
return("Warning: height seems too large. Did you use cm instead of m?")
}
# Calculate
bmi <- weight_kg / height_m^2
# Categorize
category <- ifelse(bmi < 18.5, "Underweight",
ifelse(bmi < 25, "Normal weight",
ifelse(bmi < 30, "Overweight", "Obese")))
# Report
sprintf("Weight: %.1f kg | Height: %.2f m | BMI: %.1f (%s)",
weight_kg, height_m, round(bmi, 1), category)
}
cat(bmi_report(70, 1.75), "\n")
cat(bmi_report(95, 1.80), "\n")
cat(bmi_report(50, 1.65), "\n")
cat(bmi_report(-5, 1.70), "\n")
cat(bmi_report(70, 175), "\n")
Key concept: Good functions validate inputs before computing. sprintf() creates formatted strings. return() for early exits on errors.
Exercise 14: Fibonacci Generator
Write a function that generates the first n Fibonacci numbers. Use a pre-allocated vector (not growing with c()).
# Exercise 14: Fibonacci sequence
# Write fibonacci(n) that returns the first n Fibonacci numbers
# Rules: F(1)=1, F(2)=1, F(n) = F(n-1) + F(n-2)
# Use pre-allocation for efficiency
# Test: fibonacci(10) should give: 1 1 2 3 5 8 13 21 34 55
Click to reveal solution
# Solution
fibonacci <- function(n) {
if (n <= 0) return(integer(0))
if (n == 1) return(1)
# Pre-allocate (important for large n!)
fib <- numeric(n)
fib[1:2] <- 1
for (i in 3:n) {
fib[i] <- fib[i-1] + fib[i-2]
}
return(fib)
}
cat("First 10:", fibonacci(10), "\n")
cat("First 20:", fibonacci(20), "\n")
cat("F(30):", fibonacci(30)[30], "\n")
# Bonus: verify the golden ratio
fib20 <- fibonacci(20)
ratios <- fib20[-1] / fib20[-length(fib20)]
cat("Ratio converges to golden ratio:", round(tail(ratios, 1), 6), "\n")
cat("Actual golden ratio:", round((1 + sqrt(5))/2, 6), "\n")
Key concept: Pre-allocate with numeric(n) instead of growing with c(). Edge cases (n=0, n=1) need special handling. Fibonacci ratios converge to the golden ratio (1.618...).
Exercise 15: Mini Data Analysis
Perform a complete analysis on this dataset: find summary statistics, identify outliers, and create a report.
# Exercise 15: Complete data analysis
# Daily step counts for a month (30 days)
set.seed(42)
steps <- c(round(rnorm(25, mean = 8000, sd = 2500)),
NA, 450, 25000, NA, 15)
# 1. Basic stats (handle NAs)
# 2. How many NAs? What percentage?
# 3. Find outliers (values < 1000 or > 20000 are likely errors)
# 4. Replace outliers with NA
# 5. Report: mean, median, days above 10000, most active day
Key concept: Real data analysis workflow: explore → identify problems → clean → analyze. Always handle NAs with na.rm = TRUE. Define outlier rules clearly. Report both raw and cleaned statistics.