Лучшее сообщение об ошибке для stopifnot? - PullRequest
28 голосов
/ 01 декабря 2011

Я использую stopifnot, и я понимаю, что он просто возвращает первое значение, которое не было TRUE. Если бы это было какое-то странное динамическое выражение, то кто-то, кто не входит в пользовательскую функцию, не может реально что-то из этого сделать. Поэтому я хотел бы добавить собственное сообщение об ошибке. Есть предложения?

Error: length(unique(nchar(check))) == 1 is not TRUE

В основном утверждает, что элементы вектора check не имеют одинаковую длину. Есть ли способ сказать: Error: Elements of your input vector do not have the same length!?

Ответы [ 6 ]

32 голосов
/ 01 декабря 2011

Используйте 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!
12 голосов
/ 08 декабря 2014

Пакеты 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.
5 голосов
/ 01 декабря 2011

Или вы можете упаковать его.

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 голосов
/ 27 июня 2017

Как насчет встраивания stopifnot в tryCatch и последующего преобразования исключения в stop с использованием настроенного сообщения?

Что-то вроде:

tryCatch(stopifnot(...,error=stop("Your customized error message"))

В отличие от некоторых других решений, для этого не требуются дополнительные пакеты. По сравнению с использованием оператора if в сочетании с stop вы сохраняете преимущества производительности stopifnot при использовании новых версий R. Поскольку версия R 3.5.0 stopifnot вычисляет выражения последовательно и останавливается при первом сбое.

1 голос
/ 02 ноября 2016

Ответы, которые уже предоставлены, довольно хороши, и мой - только дополнение к этой коллекции. Для некоторых людей было бы удобнее использовать однострочник в виде следующей функции:

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")

Помните, что это решение предоставляет вам только одно (общее) сообщение об ошибке для всех параметров в ....

1 голос
/ 01 декабря 2011

Я бы порекомендовал вам проверить пакет Хадли 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.Я знаю, это кажется простым, но это вызвало у меня много головных болей!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...