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
80: Profiling R Code with profvis
We've all been there: you write a piece of code that works perfectly on your test set of 100 rows, but the moment you throw it at the real production data, it crawls. The temptation is to start guessing. You might think, "Maybe this lapply is slow," or "I bet this regex is the bottleneck." But guessing is a waste of your time. I prefer to let the computer tell me exactly where it's struggling.
That's where profvis comes in. It's a wrapper around R's built-in profiling tools that gives us a visual, interactive breakdown of where every millisecond is being spent. Let's look at a scenario I ran into recently.
Creating a function that feels sluggish
Suppose I'm writing a function to simulate a random walk and calculate the running maximum at every step. I'll write this the "intuitive" way—the way many of us do when we first start with R—by growing a vector inside a loop.
library(profvis)
simulate_max_walk <- function(n = 10000) {
walk <- numeric(1)
max_vals <- numeric(1)
current_val <- 0
current_max <- 0
for (i in 1:n) {
current_val <- current_val + rnorm(1)
if (current_val > current_max) {
current_max <- current_val
}
# I'm appending the value to the vector here
max_vals <- c(max_vals, current_max)
}
return(max_vals)
}
If you run this with n = 10000, it's fast enough that you might not notice. But if you bump that to 100,000, you'll feel the lag. Instead of just staring at the screen, let's profile it.
Putting the code under the microscope
To use profvis, you wrap the code you want to analyze inside the profvis() function. It'll open an interactive window in your RStudio viewer.
profvis({
simulate_max_walk(100000)
})
When the output loads, you'll see a flame graph at the top and a table below. I'm looking specifically at the "Time" column. In my first run, I noticed something strange. A massive chunk of the time wasn't being spent on rnorm() or the if statement; it was being spent in c() and internal memory allocation functions.
The "Aha!" moment and the fix
Here is where I made my mistake. I initially assumed the bottleneck was the mathematical operations inside the loop. But the profiler showed me that R was spending almost all its effort re-allocating memory for max_vals every single time the loop iterated. Because I used c(max_vals, current_max), R had to find a new, larger spot in memory and copy the entire existing vector into it over and over again. It's a classic R performance trap.
The fix is simple: pre-allocate the vector. I'll tell R exactly how much memory I need upfront.
simulate_max_walk_fast <- function(n = 10000) {
# Pre-allocate the vector with the final size
max_vals <- numeric(n)
current_val <- 0
current_max <- 0
for (i in 1:n) {
current_val <- current_val + rnorm(1)
if (current_val > current_max) {
current_max <- current_val
}
# Assign to a specific index instead of appending
max_vals[i] <- current_max
}
return(max_vals)
}
If you run this through profvis again, you'll see the time spent in c() vanish. The "hot spot" shifts to rnorm(), which is where the actual work is happening. You've successfully moved the bottleneck from memory management to actual computation.
📋 Practical Task
Optimizing a Heavy Data Aggregator
You have been given a function that processes a large set of simulated transaction data. The function is currently far too slow for the production dataset. Your goal is to use profvis to identify the bottleneck and fix it.
library(profvis)
# The slow function
process_transactions <- function(n = 50000) {
data <- data.frame(
id = 1:n,
amount = runif(n, 1, 100),
category = sample(letters[1:5], n, replace = TRUE)
)
results <- list()
unique_cats <- unique(data$category)
for (cat in unique_cats) {
# Intentional bottleneck: filtering the whole dataframe inside a loop
cat_data <- data[data$category == cat, ]
results[[cat]] <- mean(cat_data$amount)
}
return(results)
}
# Your task:
# 1. Run the function inside profvis()
# 2. Identify why the loop is inefficient
# 3. Rewrite the function to be more efficient (Hint: Think about split() or aggregate())
# 4. Profile the new version to verify the time spent in the loop has decreased
There are no comments for now.