rerror-handlingtidyversetibble

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)


Solution

  • 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`.