Лучшее сообщение об ошибке для stopifnot?
Я использую stopifnot
, и я понимаю, что он просто возвращает первое значение, которое не было TRUE
. Я - это какое-то причудливое динамическое выражение. Кто-то, кто не входит в пользовательскую функцию, не может сделать что-то из этого. Поэтому я хотел бы добавить настраиваемое сообщение об ошибке. Любые предложения?
Error: length(unique(nchar(check))) == 1 is not TRUE
В основном утверждает, что элементы вектора check
не имеют одинаковой длины.
Есть ли способ сказать: Error: Elements of your input vector do not have the same length!
?
Ответы
Ответ 1
Используйте оператор stop
и if
:
if(length(unique(nchar(check))) != 1)
stop("Error: Elements of your input vector do not have the same length!")
Просто помните, что stopifnot
имеет удобство указания отрицательного значения, поэтому ваше условие в if
должно быть отрицанием вашего условия остановки.
Вот как выглядит сообщение об ошибке:
> check = c("x", "xx", "xxx")
> if(length(unique(nchar(check))) != 1)
+ stop("Error: Elements of your input vector do not have the same length!")
Error in eval(expr, envir, enclos) :
Error: Elements of your input vector do not have the same length!
Ответ 2
Пакеты assertive
и assertthat
имеют более читаемые функции проверки.
library(assertthat)
assert_that(length(unique(nchar(check))) == 1)
## Error: length(unique(nchar(check))) == 1 are not all true.
library(assertive)
assert_is_scalar(unique(nchar(check)))
## Error: unique(nchar(check)) does not have length one.
if(!is_scalar(unique(nchar(check))))
{
stop("Elements of check have different numbers of characters.")
}
## Error: Elements of check have different numbers of characters.
Ответ 3
Или вы можете упаковать его.
assert <- function (expr, error) {
if (! expr) stop(error, call. = FALSE)
}
Итак, у вас есть:
> check = c("x", "xx", "xxx")
> assert(length(unique(nchar(check))) == 1, "Elements of your input vector do not have the same length!")
Error: Elements of your input vector do not have the same length!
Ответ 4
Как встраивать stopifnot
в tryCatch
, а затем переделывать исключение с помощью stop
с помощью настраиваемого сообщения?
Что-то вроде:
tryCatch(stopifnot(...,error=stop("Your customized error message"))
В отличие от некоторых других решений это не требует дополнительных пакетов. По сравнению с использованием оператора if
в сочетании с stop
вы сохраняете преимущества производительности stopifnot
при использовании новых версий R. Поскольку R версия 3.5.0 stopifnot
последовательно оценивает выражения и останавливается при первом сбое.
Ответ 5
Я бы порекомендовал вам проверить пакет Hadley testthat
. Это позволяет интуитивно понятное тестирование: имена функций велики, и то, как вы их пишете, похоже на предложение - "Я ожидаю, что length(unique(nchar(check)))
будет [точно | приблизительно] 1". Полученные ошибки являются информативными.
Смотрите здесь:
http://journal.r-project.org/archive/2011-1/RJournal_2011-1_Wickham.pdf
В вашем случае
> library(testthat)
> check = c("x", "xx", "xxx")
> expect_that(length(unique(nchar(check))), equals(1))
Error: length(unique(nchar(check))) not equal to 1
Mean relative difference: 2
Также обратите внимание, что у вас нет проблемы с тем, что @Andrie ссылается на то, что иногда приходится думать о двойных отрицаниях с помощью stopifnot
. Я знаю, что это кажется простым, но это вызвало у меня много головных болей!
Ответ 6
Ответы, которые уже были предоставлены, довольно хороши, а мои - просто дополнение к этой коллекции. Для некоторых людей было бы удобнее использовать однострочный в виде следующей функции:
stopifnotinform <- function(..., message = "err") {
args <- list(...)
if (length(args) == 0) {
return(NULL)
}
for (i in 1:length(args)) {
result <- args[[i]]
if (is.atomic(result) && result == FALSE) {
stop(message)
}
}
}
# throws an error
stopifnotinform(is.integer(1L), is.integer(2), message = "Some number(s) provided is not an integer")
# continues with execution
stopifnotinform(is.integer(1L), is.integer(2L), message = "Some number(s) provided is not an integer")
Имейте в виду, что это решение предоставляет вам только одно (общее) сообщение об ошибке для всех параметров в ...
.