Skip to Content
Course content

99: Common R Interview Questions on the Apply Family

Click on the "Edit" button in the top corner of the screen to edit your slide content.

Why do interviewers always ask about lapply vs. sapply?

It's a classic for a reason. At their core, they do the exact same thing: they apply a function to each element of a list or vector. The only difference is what they hand back to you. I like to think of lapply as the "honest" function—it always returns a list, no matter what. If you give it a vector of five numbers, you get a list of five results. Period.

sapply is the "convenience" version. It tries to simplify the result. If it sees that every element in the resulting list is a single numeric value, it'll automatically collapse it into a numeric vector for you. It feels like magic until it isn't. For example, if you're calculating the mean of several columns in a weather dataset:

temp_data <- list(NYC = c(72, 75, 68), LDN = c(60, 62, 58), TOK = c(70, 71, 69))

# Always a list
lapply(temp_data, mean) 

# Usually a named numeric vector
sapply(temp_data, mean) 

In an interview, the key is to mention that sapply is essentially a wrapper around lapply. It's great for interactive work, but dangerous in a production pipeline because its return type can change depending on the input data.

Is vapply actually worth the extra typing?

Short answer: Yes. Long answer: If you're writing code that other people (or your future self) will rely on, vapply is your best friend. The problem with sapply is that it guesses the output type. If your data is messy and one element returns a character while the others return numbers, sapply might suddenly return a character vector, which will likely break whatever function comes next in your chain.

With vapply, you explicitly tell R what you expect the output to look like using the FUN.VALUE argument. If the function returns something different, R throws an error immediately. I'd rather have my code crash during a test run than have it silently produce the wrong data type in a production report.

# I'm telling R: "I expect a single numeric value back for each element"
vapply(temp_data, mean, FUN.VALUE = numeric(1))

If mean() somehow returned a string or a vector of two numbers, vapply would stop the execution right there. That's the "type safety" interviewers are looking for when they ask this.

When should I use apply() instead of the others?

This is where people often get tripped up. lapply and sapply are designed for lists or vectors. apply() is specifically for matrices or data frames where you need to specify a margin. This is just a fancy way of saying "do this to every row" or "do this to every column."

If you have a matrix of hourly readings and you want the maximum value for each hour (across all sensors), you'd use apply with MARGIN = 1 for rows or MARGIN = 2 for columns. Here's a quick example using a simple matrix of sensor readings:

# A 3x3 matrix of sensor readings
readings <- matrix(rnorm(9), nrow = 3)

# MARGIN = 1: Apply the function to each ROW
row_means <- apply(readings, 1, mean)

# MARGIN = 2: Apply the function to each COLUMN
col_means <- apply(readings, 2, mean)

Just a heads up: apply coerces data frames into matrices first. If your data frame has a mix of characters and numbers, apply will turn everything into characters, and your math will fail. In those cases, stick to lapply or sapply, as they handle the columns as a list of vectors.




📋 Practical Task

Hardening a Sensor Data Pipeline with vapply

You've been handed a list of sensor readings, but the data is "dirty." Some sensors returned valid numeric vectors, while one faulty sensor returned a character string ("ERROR").

Your goal is to write a robust piece of code that calculates the mean for each sensor. Instead of using sapply, use vapply to ensure that the output is always a single numeric value. You should wrap the mean function in a custom helper function that returns NA if the input is not numeric, ensuring vapply doesn't crash but still maintains the correct return type.

# Setup data
sensor_readings <- list(
  sensor_A = c(10.2, 10.5, 10.1),
  sensor_B = c(20.1, 19.8, 20.5),
  sensor_C = "ERROR", 
  sensor_D = c(15.5, 14.9, 15.2)
)

# Your task: 
# 1. Create a function 'safe_mean' that checks if the input is numeric.
# 2. If numeric, return mean(). If not, return NA_real_.
# 3. Use vapply to apply 'safe_mean' to sensor_readings, specifying the correct FUN.VALUE.
Rating
0 0

There are no comments for now.

to be the first to leave a comment.