I sometimes load multiple packages that export functions of the same name. For example, both Hmisc and dplyr have a summarize
function, and I sometimes load both packages. I then call summarize
, thinking that I am calling dplyr::summarize
when I am really calling Hmisc::summarize
. When that happens, I get an error message like this:
Error in summarize(., mean = mean(instRating)) :
argument "by" is missing, with no default
The message is initially hard to understand, because my code contains no errors. It takes me a minute to realize that I've called a function in the wrong package. The error message would be easier to understand if its first line included the name of the relevant package:
Error in Hmisc::summarize(., mean = mean(instRating)) :
Is there a way to force R to display the package name in these error messages?
I know that I can get around the problem by typing out dplyr::summarize
or by changing the order in which I load packages. But my interest lies with adding detail to R's error messages.
From the documentation of the base option error
:
'error': either a function or an expression governing the handling of non-catastrophic errors such as those generated by 'stop' as well as by signals and internally detected errors. If the option is a function, a call to that function, with no arguments, is generated as the expression. By default the option is not set: see 'stop' for the behaviour in that case. The functions 'dump.frames' and 'recover' provide alternatives that allow post-mortem debugging. Note that these need to specified as e.g. 'options(error = utils::recover)' in startup files such as '.Rprofile'.
So it should be possible to define a function that returns the name of the package where the function that’s throwing the error lives. For example:
library(dplyr)
library(Hmisc)
data(mtcars)
print_package <- function() {
calls <- sys.calls()
call <- calls[[length(calls) - 1]]
fun.name <- as.character(call)[1]
pkg.name <- sub("package:", "", getAnywhere(fun.name)$where[1], fixed = TRUE)
message (paste0("In ", pkg.name))
}
options(error = print_package)
summarize(mtcars$mpg)
Returns:
Error in summarize(mtcars$mpg) :
argument "by" is missing, with no default
In Hmisc
rlang::trace_back
)It turns out that there is a much cleaner way of doing this (credit goes to Hadley Wickham and his "Advanced R, Second edition"):
library(dplyr)
library(Hmisc)
data(mtcars)
print_trace_back <- function() {
print(rlang::trace_back(bottom = sys.frame(-1)))
}
options(error = print_trace_back)
Seems to handle errors gracefully:
> summarize(mtcars$mpg)
Error in summarize(mtcars$mpg) :
argument "by" is missing, with no default
█
1. └─Hmisc::summarize(mtcars$mpg)
>
> Hmisc::summarize(mtcars$mpg)
Error in Hmisc::summarize(mtcars$mpg) :
argument "by" is missing, with no default
█
1. └─Hmisc::summarize(mtcars$mpg)
>
> summarize(mtcars$mpg, as.character(mtcars$apa), mean)
Error in tapply(X, INDEX, FUN, ..., simplify = simplify) :
arguments must have same length
█
1. └─Hmisc::summarize(mtcars$mpg, as.character(mtcars$apa), mean)
2. └─Hmisc::mApply(X, byc, FUN, ..., keepmatrix = nc > 1)
3. └─base::tapply(X, INDEX, FUN, ..., simplify = simplify)
4. └─base::stop("arguments must have same length")
>
> (function() stop("Error"))()
Error in (function() stop("Error"))() : Error
█
1. └─(function() stop("Error"))()
2. └─base::stop("Error")
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