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)
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.
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`.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With