Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Convert a specific warning type into an error

Consider the following code:

> df <- tibble(gender=c(1,1,0))
> df$male
Warning: Unknown or uninitialised column: `male`.
NULL

How can I convert this specific warning type into an error?

I would like something like options(warn = 2) but only for this specific type of warning (i.e. refering to a column in a tibble that doesn't exist)

like image 866
robertspierre Avatar asked May 03 '26 08:05

robertspierre


2 Answers

It's a bit hacky but you can patch the function $ i.e. the getter. The warning is thrown by rlang::warn when the column name is not found in df. By substituting this call with one to rlang::abort we transform this warning into an error.

patch_tibble <- function() {
  if(is.null(attr(tibble:::`$.tbl_df`, "patched"))) {
    tt <- get("$.tbl_df", envir=asNamespace("tibble"), inherits=FALSE)
    
    body(tt) <- methods::substituteDirect(body(tt), list(warn=quote(abort)))
    attr(tt, "patched") <- TRUE
    
    unlockBinding("$.tbl_df", asNamespace("tibble"))
    assign("$.tbl_df", tt, envir=asNamespace("tibble"), inherits = FALSE)
    lockBinding("$.tbl_df", asNamespace("tibble"))
    packageStartupMessage("Patched tibble!")
  }
}
library(tibble)
patch_tibble()

df <- tibble(gender=c(1,1,0))
df$male

Error in `df$male`:
! Unknown or uninitialised column: `male`.
Run `rlang::last_trace()` to see where the error occurred.
like image 164
Billy34 Avatar answered May 05 '26 22:05

Billy34


The original function for the S3 method $.tbl_df is defined as:

function (x, name) 
{
    out <- .subset2(x, name)
    if (is.null(out)) {
        warn(paste0("Unknown or uninitialised column: ", tick(name), 
            "."))
    }
    out
}

You can just simply replace the warning with an error using stop or rlang:abort():

`$.tbl_df` <- function (x, name) {
  out <- .subset2(x, name)
  if (is.null(out)) {
    rlang::abort(paste0("Unknown or uninitialised column: ", name, "."))
  }
  out
}

Then, as expected:

> df$male
Error in `$.tbl_df`(df, male) : Unknown or uninitialised column: male.

Addendum

As pointed out in the comments, this solution may cause problems if $.tbl_df is being called internally. Following @Billy34's lead, we can replace the internal $.tbl_df function with our modified function like so:

patch_tibble <- function(){
  
  # The modified "$.tbl_df" function
  f <- function (x, name) {
    out <- .subset2(x, name)
    if (is.null(out)) {
      abort(paste0("Unknown or uninitialised column: ", tick(name), 
                   "."))
    }
    out
  }
  
  # Set the function's namespace to tibble
  environment(f) <- asNamespace("tibble")
  
  # Replace the original function with our modified version
  utils::assignInNamespace("$.tbl_df", f, "tibble")
  
  print("Patched tibble!")
}

This yields the output:

> patch_tibble()
[1] "Patched tibble!"
> df$male
Error in `df$male`:
! Unknown or uninitialised column: `male`.
like image 37
random_walk Avatar answered May 05 '26 22:05

random_walk