Подтвердить что ты не робот

Лучшее сообщение об ошибке для 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!?

4b9b3361

Ответ 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")

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