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

We've all been there. You write a function that works perfectly on your test case, you deploy it to a larger dataset, and suddenly R screams at you with an error that feels like a riddle. One of the most frustrating errors for R developers is the dreaded the condition has length > 1 warning or error. It usually happens when you're trying to use a standard if statement on something that R thinks is a vector.

Take a look at this snippet. I'm trying to write a simple function to categorize the "health" of a server based on its response time in milliseconds.

categorize_latency <- function(latency) {
  if (latency < 100) {
    return("Healthy")
  } else if (latency < 500) {
    return("Warning")
  } else {
    return("Critical")
  }
}

# This works fine
categorize_latency(50) 

# But this crashes the pipeline
latencies <- c(50, 120, 600)
categorize_latency(latencies)

When you run that last line, R throws: Error in if (latency < 100) { : the condition has length > 1. If this were buried inside a 500-line script, you might spend an hour staring at the code wondering why it's failing now when it worked five minutes ago.

Tracing the crash with traceback()

When a script crashes, your first instinct might be to just restart the session and try again. Don't do that. Instead, immediately run traceback() in your console. This function prints the call stack—essentially a map of every function call that led up to the error.

In a complex project, traceback() tells you exactly which nested function failed. In our case, it would point directly to the if (latency < 100) line. The problem is that if is a scalar operator; it expects a single TRUE or FALSE. But we passed it a vector of three values. R doesn't know which one of those three you want to use to decide the branch, so it gives up.

Using browser() to pause time

If traceback() isn't enough because the logic is more subtle, I want you to start using browser(). This is my absolute favorite tool in R. By inserting browser() into your code, you tell R: "Stop everything right here and let me look around."

categorize_latency <- function(latency) {
  browser() # The execution will pause here
  if (latency < 100) {
    return("Healthy")
  }
  # ... rest of code
}

When the code hits that line, your console changes. You are now "inside" the function. You can type latency to see exactly what the variable contains at that microsecond, or test latency < 100 to see that it returns TRUE FALSE TRUE instead of a single value. Once you've found the culprit, type c to continue execution or Q to quit the debugger.

Switching to vectorized logic

The fix here isn't to write a loop (which is slow in R). The fix is to use ifelse() or dplyr::case_when(). These functions are designed to handle vectors by applying the logic to every element individually.

categorize_latency_fixed <- function(latency) {
  # ifelse takes (test, value_if_true, value_if_false)
  # We nest them to handle multiple categories
  result <- ifelse(latency < 100, "Healthy",
              ifelse(latency < 500, "Warning", "Critical"))
  return(result)
}

latencies <- c(50, 120, 600)
categorize_latency_fixed(latencies)
# Returns: "Healthy" "Warning" "Critical"

The reason this works is that ifelse() is vectorized. It doesn't try to make one single decision for the whole vector; it makes a decision for every single element in that vector and returns a vector of the same length. This is the "R way" of thinking—whenever you find yourself fighting with if statements in a data pipeline, you probably need a vectorized alternative.




📋 Practical Task

Fixing the Tiered Tax Calculator

You've been handed a function that calculates the tax rate for a client based on their annual income. However, the function is currently broken because it was written for single values and is now being applied to a full column of data in a dataframe.

The Broken Code:

calculate_tax_rate <- function(income) {
  if (income < 30000) {
    return(0.10)
  } else if (income < 70000) {
    return(0.20)
  } else {
    return(0.30)
  }
}

incomes <- c(25000, 50000, 100000)
# This line causes the "condition has length > 1" error:
tax_rates <- calculate_tax_rate(incomes)

Your Goal:

  • Rewrite the calculate_tax_rate function so that it can accept a vector of incomes and return a vector of corresponding tax rates.
  • Ensure the function uses a vectorized approach (like ifelse()) rather than a for loop.
  • Verify that calling calculate_tax_rate(c(25000, 50000, 100000)) returns c(0.10, 0.20, 0.30).
Rating
0 0

There are no comments for now.

to be the first to leave a comment.