Chapter 44: R Max and Min
1. What do max() and min() actually do?
- max() → returns the largest value in a vector (or across multiple vectors)
- min() → returns the smallest value in a vector (or across multiple vectors)
They are vectorized — they work beautifully on entire columns/vectors at once (this is R’s superpower).
They also have very important arguments: na.rm = TRUE and … (multiple inputs).
2. Basic Usage – Copy-Paste These Right Now
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
# Simple numeric vector marks <- c(78, 92, 65, 88, 71, 84, 95, 59) max(marks) # 95 min(marks) # 59 # With missing values (very common trap!) scores <- c(85, NA, 92, 45, NA, 78) max(scores) # NA ← default behavior min(scores) # NA max(scores, na.rm = TRUE) # 92 min(scores, na.rm = TRUE) # 45 |
Golden rule 2026: Always use na.rm = TRUE unless you deliberately want to know there is missing data.
3. Real-Life Examples – How People Actually Use max() & min()
Example 1 – Find highest & lowest value in a column
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
# mtcars – classic dataset data(mtcars) max(mtcars$mpg, na.rm = TRUE) # highest fuel efficiency min(mtcars$mpg, na.rm = TRUE) # lowest # Nicer message cat("Best mileage:", max(mtcars$mpg), "mpg\n") cat("Worst mileage:", min(mtcars$mpg), "mpg\n") |
Example 2 – Range of values (max – min)
|
0 1 2 3 4 5 6 7 8 9 10 11 |
temps_hyd <- c(28.5, 29.8, 30.2, 27.9, 31.4, 29.1, 32.0) range_temps <- range(temps_hyd) # shortcut: returns c(min, max) range_temps # 27.9 32.0 cat("Temperature range this week:", diff(range_temps), "°C\n") |
Example 3 – Find extreme rows in data frame
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
# Student with highest & lowest average marks students <- data.frame( name = c("Aarav", "Priya", "Rahul", "Sneha", "Vikram"), marks = c(92, 85, 68, 78, 88) ) # Row with max marks students[which.max(students$marks), ] # Row with min marks students[which.min(students$marks), ] |
Example 4 – Clamp / Winsorize values (very common in data cleaning)
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
# Cap outliers at 5th & 95th percentile (simple winsorizing) sales <- c(1200, 1500, 1800, 2200, 50000, 1400, 1600, 1900, 2100, 99999) lower <- quantile(sales, 0.05) upper <- quantile(sales, 0.95) sales_clean <- pmax(pmin(sales, upper), lower) # pmax / pmin = parallel max/min # Before vs after data.frame(original = sales, cleaned = sales_clean) |
→ pmax() and pmin() are parallel/element-wise versions — very useful!
4. Multiple Inputs – Comparing Several Vectors
|
0 1 2 3 4 5 6 7 8 9 10 11 |
group_a <- c(45, 52, 48, 60) group_b <- c(50, 55, 47, 58) group_c <- c(62, 59, 65, 61) max(group_a, group_b, group_c) # 65 min(group_a, group_b, group_c) # 45 |
→ Useful when you want overall min/max across several groups.
5. Important Arguments & Edge Cases (2026 Reality)
| Argument | What it does | Default | Almost always use? |
|---|---|---|---|
| na.rm | Remove NA before calculation | FALSE | YES – almost always |
| … | Multiple vectors/objects | — | Yes for comparison |
| finite (in newer R) | Ignore Inf / -Inf | FALSE | Sometimes |
Edge cases you will meet:
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
# All NA max(NA, NA, NA) # NA max(NA, NA, NA, na.rm = TRUE) # -Inf ← warning! # Only Inf / -Inf max(c(1, Inf, 2)) # Inf min(c(-Inf, 5, -10)) # -Inf # Empty vector max(numeric(0)) # -Inf with warning min(numeric(0)) # Inf with warning |
Rule: If na.rm = TRUE and all values are NA → returns -Inf/Inf + warning. Always check length or use ifelse() / if (all(is.na(x))) …
6. Modern 2026 Nice-to-Haves
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
# Tidyverse style – find row with max/min library(dplyr) mtcars |> slice_max(mpg, n = 1) # row with highest mpg mtcars |> slice_min(mpg, n = 1) # row with lowest mpg # Or with ties mtcars |> slice_max(mpg, n = 3, with_ties = TRUE) |
Your Mini Practice Right Now
Copy & run — then try changing columns:
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
data(mtcars) # Quick extremes cat("Highest MPG:", max(mtcars$mpg), "– car:", rownames(mtcars)[which.max(mtcars$mpg)], "\n") cat("Lowest MPG:", min(mtcars$mpg), "– car:", rownames(mtcars)[which.min(mtcars$mpg)], "\n") # Weight extremes heaviest <- mtcars |> slice_max(wt, n = 1) lightest <- mtcars |> slice_min(wt, n = 1) print(heaviest) print(lightest) |
Now try:
- Find car with highest horsepower (hp)
- Use na.rm = TRUE on a vector with NA
- Use pmax() to cap values at 25
You just used max()/min() in real analysis style!
Feeling good?
Next questions?
- Want to combine max/min with ifelse() for conditional capping?
- Learn range(), quantile(), IQR() next?
- Or move to summary statistics in detail (mean, median, sd, var)?
Just tell me — whiteboard is ready! 📊🧮🚀
