R
Completed
-
Section 1: Getting Started
-
Section 2: Core Syntax
-
Section 3: Data Structures
-
Section 4: Data Manipulation
-
Section 5: Visualization and Statistics
-
Section 6: Advanced R
-
Section 7: Practical Projects
-
Section 8: Interview Practice
-
Section 9: More Practice Exercises
-
Section 10: Shiny Apps in Depth
-
Section 11: More Data Wrangling
-
Section 12: Tidyverse Deep Dive
-
Section 13: Statistical Modeling Deep Dive
-
Section 14: Machine Learning in R
-
Section 15: R Visualization Deep Dive
-
Section 16: R Package Development Deep Dive
-
Section 17: R for Reproducible Research
-
Section 18: R and Databases
-
Section 19: R Performance Optimization
-
Section 20: Bioinformatics and Specialized R
-
Section 21: More Shiny Practice
-
Section 22: More Practice Exercises
-
Section 23: R Data Structures Deep Dive
-
Section 24: More Interview and Review
-
Section 25: R for Business Analytics
-
Section 26: R Text Mining and NLP
-
Section 27: R Spatial Data Analysis
-
Section 28: R Deep Learning
-
Section 29: Advanced Statistical Techniques
-
Section 30: R Object Systems Deep Dive
-
Section 31: R Environments and Metaprogramming
-
Section 32: R for Finance
-
Section 33: R for Clinical and Health Data
-
Section 34: More Shiny Advanced Practice
-
Section 35: R Data Cleaning Deep Dive
-
Section 36: R Reporting Automation
-
Section 37: More Practical Projects Round 2
-
Section 38: R Ecosystem and Career
-
Section 39: More Visualization Practice
-
Section 40: R for Experimentation
-
Section 41: R for Genomics and Bioinformatics Deep Dive
-
Section 42: R for Marketing Analytics
-
Section 43: R Data Import/Export Deep Dive
-
Section 44: R String Processing Deep Dive
-
Section 45: R for Actuarial and Insurance Analytics
-
Section 46: R Testing and Quality Assurance Deep Dive
-
Section 47: R Version Control and Collaboration
-
Section 48: R Advanced Functional Programming
-
Section 49: R for Supply Chain and Operations
-
Section 50: More Practice Exercises Round 3
-
Section 51: R Dashboards and BI Integration
-
Section 52: R Data Governance and Ethics
-
Section 53: More Modeling Practice
-
Section 54: R Final Capstone Projects
-
Section 55: R for Sports Analytics
-
Section 56: More Interview Practice Round 2
-
Section 57: R Networking and APIs
-
Section 58: R for Environmental Science
-
Section 59: R Notebook and Documentation Practices
-
Section 60: More Data Wrangling Mastery
-
Section 61: R for A/B Testing at Scale
-
Section 62: R Package Ecosystem Deep Dive
52: purrr Functional Programming In Depth
Imagine you have a stack of a hundred envelopes that all need the same official company stamp on the top-right corner. You could pick up one envelope, stamp it, put it down, and then reach for the next one. That's essentially what a for loop does. It's manual, it's repetitive, and if you get distracted halfway through, you might lose your place.
Now, imagine you have a stamping machine. You feed the entire stack into the machine, and it applies the stamp to every single envelope in one continuous, automated motion. You don't manage the "looping" yourself; you just define the stamp (the function) and the stack (the data), and the machine handles the rest. That is the essence of purrr.
Here is how that maps to the code we're about to write:
- The Stack: This is your vector or list. In R, this is often a list of file paths, a list of data frames, or a character vector of IDs.
- The Stamp: This is the function you want to apply. It could be a built-in function like
mean()or a custom function you wrote to clean a specific type of messy string. - The Machine: This is the
map()family of functions. They take the stack and the stamp and produce a new stack of results.
Trading loops for type-stability
I'll be honest with you: you can do almost anything purrr does using a for loop. But the reason I prefer purrr—and why you should too—is type-stability. When you use a standard for loop, you have to pre-initialize an empty vector or list to hold your results. If you forget, or if you initialize it as the wrong type, R will either complain or start "coercing" your data into something you didn't want, which is a nightmare to debug.
purrr solves this with specialized versions of map(). If you know you want a numeric vector back, don't use map() (which always returns a list); use map_dbl(). If you want strings, use map_chr(). It forces you to be intentional about what your code is producing.
library(purrr)
# Let's say we have a list of numeric vectors
my_data <- list(a = 1:5, b = 6:10, c = 11:15)
# map() returns a list. Good for complex objects, overkill for single numbers.
list_results <- map(my_data, mean)
# map_dbl() returns a numeric vector. Clean, concise, and predictable.
vec_results <- map_dbl(my_data, mean)
# Result: c(a = 3, b = 8, c = 13)
The shorthand that saves your fingers
Writing a full function just to do one tiny thing inside a map() call feels tedious. This is where the tilde ~ comes in. It's basically a shortcut for saying "create an anonymous function here." Inside these shortcuts, we use .x to represent the "current item" being stamped.
Check out the difference here. Instead of writing a whole function(x) { ... } block, we do this:
# I want to square every number and then add 10
# The old way:
map_dbl(my_data, function(x) sum(x^2) + 10)
# The purrr way:
map_dbl(my_data, ~ sum(.x^2) + 10)
Taming the "List-Column" beast
In the real world, you'll often encounter "list-columns" in a tibble. This is where a single cell in a data frame actually contains an entire list or another data frame. It looks intimidating, but it's actually the superpower of the Tidyverse. You can use map() directly inside a mutate() call to perform calculations on those lists without ever leaving the data frame.
For example, if you have a column where each cell is a list of temperature readings for a day, you can create a new column for the "daily average" by mapping mean across that column. It keeps your data tidy and avoids the need to split your data into separate objects and merge them back together later.
📋 Practical Task
Processing Quarterly Financial CSVs
You have been handed four CSV files representing quarterly sales: "q1_sales.csv", "q2_sales.csv", "q3_sales.csv", and "q4_sales.csv". Each file has the same columns: date, product_id, and revenue.
Your goal is to write a purrr pipeline that does the following:
- Creates a character vector of the four file names.
- Uses
map()to read all four files into a list of data frames. - Uses
map_dbl()on that list to calculate the total sum ofrevenuefor each quarter. - Combines these four totals into a single numeric vector.
Constraint: Do not use a for loop. Use the map family of functions to handle the iteration. Assume the files exist in your current working directory.
There are no comments for now.