map() and Typed Variants
Apply functions over lists with map(), map_dbl(), map_chr(), and map_lgl().
map() and Typed Variants is a free R Academy lesson on CoddyKit. This is lesson 1 of 4. Any 3 lessons of this learning path are free to read in full — after that, CoddyKit PRO unlocks every lesson, plus hands-on practice with a built-in code editor and a 24/7 AI tutor. It is part of the R Academy learning path, and your progress syncs across the web and the CoddyKit app. The R Academy course includes 4 lessons in total.
Functional Programming with purrr
The purrr package provides consistent, type-safe tools for functional programming in R. Instead of writing for loops, you map a function over a list or vector. The result is cleaner code that's easier to reason about and compose.
library(purrr)
# A list of numbers
numbers <- list(1, 4, 9, 16, 25)
# Apply sqrt() to each element
result <- map(numbers, sqrt)
print(result)map() — Always Returns a List
map(.x, .f) applies function .f to each element of .x and returns a list. The input can be a list, vector, or data frame (iterates over columns). This is the most general map variant.
library(purrr)
# Map over a character vector
fruits <- c('apple', 'banana', 'cherry')
# nchar() counts characters in each string
result <- map(fruits, nchar)
print(result) # Returns a list
print(class(result))map_dbl() — Returns a Numeric Vector
map_dbl(.x, .f) maps .f over .x and returns a numeric (double) vector. If any result is not a single numeric value, it throws an error — this type safety catches bugs early.
library(purrr)
groups <- list(
A = c(10, 20, 30),
B = c(5, 15, 25, 35),
C = c(100, 200)
)
# Compute mean for each group — returns a named numeric vector
means <- map_dbl(groups, mean)
print(means)
print(class(means))map_chr() — Returns a Character Vector
map_chr(.x, .f) maps and returns a character vector. Useful for extracting string attributes, formatting results, or building file paths. The function must return a single string per element.
library(purrr)
models <- list(
m1 = lm(mpg ~ wt, data=mtcars),
m2 = lm(mpg ~ hp, data=mtcars),
m3 = lm(mpg ~ cyl, data=mtcars)
)
# Extract the formula from each model as a string
map_chr(models, function(m) deparse(formula(m)))map_lgl() — Returns a Logical Vector
map_lgl(.x, .f) returns a logical vector of TRUE/FALSE values. It's perfect for testing conditions across a list — for example, checking which elements meet a criterion.
library(purrr)
datasets <- list(
df1 = data.frame(x=1:3, y=c(NA,2,3)),
df2 = data.frame(x=1:3, y=4:6),
df3 = data.frame(x=c(NA,NA,3), y=1:3)
)
# Does each data frame contain any NA values?
map_lgl(datasets, function(df) anyNA(df))map_int() — Returns an Integer Vector
map_int(.x, .f) returns an integer vector. Use it when your function returns counts, indices, or other whole-number results. Note: in R, length() and nrow() return integers.
library(purrr)
my_lists <- list(
a = 1:10,
b = letters[1:5],
c = c(TRUE, FALSE, TRUE, TRUE)
)
# Count elements in each list item
map_int(my_lists, length)map_df() / map_dfr() — Returns a Data Frame
map_df(.x, .f) (alias: map_dfr()) applies .f and row-binds the results into a single data frame. The function must return a data frame or tibble for each element. map_dfc() column-binds instead.
library(purrr)
files <- c('sales_q1', 'sales_q2', 'sales_q3')
# Simulate reading and labeling each file
map_df(files, function(f) {
data.frame(
file = f,
rows = sample(50:100, 1),
cols = 5
)
})Anonymous Functions with ~
purrr supports a compact formula shorthand for anonymous functions: ~expr where .x refers to the current element. This avoids writing function(x) expr and keeps code concise. Both styles work identically.
library(purrr)
numbers <- list(1, 4, 9, 16, 25)
# Three equivalent ways:
result1 <- map(numbers, function(x) x^2)
result2 <- map(numbers, ~.x^2)
result3 <- map_dbl(numbers, ~.x^2)
print(result2)
print(result3)Mapping Over a Named List
When .x is a named list or vector, the output of map() preserves those names. map_dbl() and other typed variants also carry names through, making results self-documenting.
library(purrr)
region_data <- list(
East = c(100, 120, 115, 130),
West = c(200, 195, 210, 205),
North = c(80, 85, 90, 88)
)
# Named results
map_dbl(region_data, mean)Using map() with Data Frame Columns
A data frame is a list of columns. map(df, fn) applies fn to each column. Combined with map_dbl(), this is a compact way to compute a statistic for every column at once.
library(purrr)
df <- data.frame(
score_a = c(85, 90, 78, 92),
score_b = c(88, 85, 80, 95),
score_c = c(92, 88, 84, 90)
)
# Mean of every column
map_dbl(df, mean)Nesting map() Calls
You can nest map() calls for multi-level iteration — outer map over groups, inner map over parameters. This replaces nested for-loops with a clean, composable structure. Keep nesting depth to 2 levels for readability.
library(purrr)
groups <- list(A = 1:5, B = 6:10)
functions <- list(mean=mean, sd=sd, min=min)
# Apply each function to each group
map(groups, function(g) {
map_dbl(functions, function(f) f(g))
})Quick Check
What is the key difference between map() and map_dbl()?
Recap: map() and Typed Variants
Key takeaways for map() and typed variants:
map(.x, .f)— always returns a list; most flexiblemap_dbl()— returns numeric vector; errors on wrong typemap_chr()— returns character vectormap_lgl()— returns logical vectormap_int()— returns integer vectormap_df()/map_dfr()— row-binds results into a data frame~.xshorthand — compact anonymous function syntax- Named inputs produce named outputs automatically
library(purrr)
# Typed map showcase
data_list <- list(
group_A = c(10, 20, 30),
group_B = c(5, 15),
group_C = c(100, 200, 300, 400)
)
cat('Counts:', map_int(data_list, length), '\n')
cat('Means: ', map_dbl(data_list, mean), '\n')
cat('Any>50:', map_lgl(data_list, ~any(.x > 50)), '\n')Learn R with an AI tutor — free
Write and run real code in your browser, get instant help from a 24/7 AI tutor, and pick up where you left off on the web or in the app.
- Courses
- 43
- Lessons
- 159
Frequently Asked Questions
Is the “map() and Typed Variants” lesson free?
Yes — any 3 lessons of the R Academy learning path, including “map() and Typed Variants”, are free to read in full here on the web. After that, CoddyKit PRO unlocks every lesson, plus interactive practice with a built-in code editor and a 24/7 AI tutor. The R Academy course includes 4 lessons in total.
What will I learn in “map() and Typed Variants”?
Apply functions over lists with map(), map_dbl(), map_chr(), and map_lgl(). You practise R Academy with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.
Do I need any experience to start R Academy?
No prior experience is required. R Academy on CoddyKit is structured for beginners through advanced learners, so you can start here or from the beginning and move at your own pace. This is lesson 1 of 4.
How long does the “map() and Typed Variants” lesson take?
Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.
Can I write and run code in this R Academy lesson?
Yes. Every R Academy lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.
All lessons in this course
- map() and Typed Variants
- map2() and pmap() for Multiple Inputs
- reduce(), accumulate(), and walk()
- keep(), discard(), and List Filtering