Conditions

Practice with Conditions

Author

Brian Helsel

Published

September 23, 2026

Conditions in R

This practice focuses on working with conditions in R, including warnings, errors, messages, and custom condition handling.


Exercise 1: Handling warnings

Goal

Write a function that calculates the mean of a numeric vector but gives the user a warning when missing values are present.

Task

Create a function called safe_mean() that:

  • Takes a numeric vector x.
  • Calculates the mean using na.rm = TRUE.
  • Issues a warning if x contains any missing values.
  • Returns the calculated mean.

For example, safe_mean(c(1, 2, NA, 4)) should return 2.333333 and generate a warning indicating that missing values were removed.

safe_mean <- function(x) {
  if (anyNA(x)) {
    warning("Missing values were removed.")
  }
  mean(x, na.rm = TRUE)
}


safe_mean(c(1, 2, NA, 4))
[1] 2.333333

Modify safe_mean() so that the warning reports how many missing values were found.

For example: Warning: 2 missing values were removed.

safe_mean <- function(x) {
  n_missing <- sum(is.na(x))

  if (n_missing > 0) {
    warning(
      n_missing,
      " missing value",
      if (n_missing != 1) "s",
      " were removed."
    )
  }

  mean(x, na.rm = TRUE)
}

safe_mean(c(1, 2, NA, 4, NA))
[1] 2.333333

Exercise 2: Catching errors

Goal

Use tryCatch() to make a function robust to errors.

Suppose you have a function that calculates a ratio:

calculate_ratio <- function(x, y) {
  x / y
}

You want to safely calculate several ratios without allowing one problematic calculation to stop the entire analysis.

Task

Create a function called safe_ratio() that:

  • Takes x and y.
  • Attempts to calculate x / y.
  • Returns the result if the calculation succeeds.
  • Returns NA if an error occurs.

Use tryCatch() to handle the error.

Test your function with:

safe_ratio <- function(x, y) {
  tryCatch(
    x / y,
    error = function(e) {
      NA
    }
  )
}

safe_ratio(10, 2)
[1] 5
safe_ratio("ten", 2)
[1] NA

Modify the function so that it also prints a useful message when an error occurs.

For example: Could not calculate ratio: non-numeric argument to binary operator

safe_ratio <- function(x, y) {
  tryCatch(
    x / y,
    error = function(e) {
      message("Could not calculate ratio: ", e$message)
      NA
    }
  )
}

Exercise 3: Creating and handling custom conditions

Goal

Create your own condition and use it to communicate information from a function to its caller.

Imagine that you are processing participant data. A function checks whether a participant has enough valid observations for analysis.

If fewer than 3 observations are available, you want to generate a custom condition called “insufficient_data”.

Task

Create a function called check_data() that:

  • Takes a numeric vector x.
  • Counts the number of non-missing observations.
  • If there are fewer than 3 observations, signals a custom condition with class “insufficient_data”.
  • Otherwise, returns the number of valid observations.

For example: check_data(c(1, 2, 3, NA)) should return [1] 3 while check_data(c(1, NA, NA)) should generate the custom condition.

Then use tryCatch() to handle the “insufficient_data” condition and print:

Participant does not have enough valid observations.

check_data <- function(x) {
  n_valid <- sum(!is.na(x))

  if (n_valid < 3) {
    rlang::abort(
      "Fewer than 3 valid observations.",
      class = "insufficient_data"
    )
  }

  n_valid
}

check_data(c(1, 2, 3, NA))
[1] 3
tryCatch(
  check_data(c(1, NA, NA)),
  insufficient_data = function(cnd) {
    message("Participant does not have enough valid observations.")
  }
)

Modify the function so that the condition contains the number of valid observations. For example, if only 2 observations are available, the condition should contain: n_valid = 2

check_data <- function(x) {
  n_valid <- sum(!is.na(x))

  if (n_valid < 3) {
    rlang::abort(
      "Fewer than 3 valid observations.",
      class = "insufficient_data",
      n_valid = n_valid
    )
  }

  n_valid
}


tryCatch(
  check_data(c(1, 2, NA)),
  insufficient_data = function(cnd) {
    message(
      "Only ",
      cnd$n_valid,
      " valid observations were available."
    )
  }
)