Подавить предупреждение на основе их позиции в списке предупреждений или на основе регулярного выражения в R - PullRequest
0 голосов
/ 03 марта 2020

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

Вот пример обычного предупреждения, возвращаемого моей функцией, которое меня не волнует:

Warning message:
Using alpha for a discrete variable is not advised.

Вот теперь пример обычного предупреждения + соответствующее предупреждение, которое я на самом деле хотел бы видеть, когда оно возвращается:

Warning messages:
1: Using alpha for a discrete variable is not advised. 
2: Removed 2 rows containing missing values (geom_point).

Мой вопрос: как я могу подавить 1-е предупреждение? (Using alpha for a discrete variable is not advised.), либо в зависимости от его положения в списке предупреждений, либо с помощью регулярного выражения ... или любой другой идеи, без использования других пакетов, кроме пакетов по умолчанию R (базы, наборы данных, графика, статистика ...) ?

Пока что решение, которое я нашел, использует пакет pkgcond v0.1.0 , который имеет собственную функцию suppress_warnings () . Но я очень хочу не загружать дополнительные пакеты.

Заранее благодарю за помощь!

1 Ответ

3 голосов
/ 03 марта 2020

Вот один из способов решения проблемы, и все это в базе R.

Давайте начнем с функции, которая возвращает желаемое значение, но перед этим выдаст два предупреждения:

make_warnings <- function()
{
  warning("This is a warning that can be ignored")
  warning("This is a warning that shouldn't be ignored")
  return(0)
}

Конечно, если мы запустим это, мы получим предупреждения:

make_warnings()
#> [1] 0
#> Warning messages:
#> 1: In make_warnings() : This is a warning that can be ignored
#> 2: In make_warnings() : This is a warning that shouldn't be ignored

Если мы запустим функцию внутри suppressWarnings, мы просто потеряем все предупреждения, а это не то, что мы хотим. Но мы можем использовать withCallingHandlers, который предоставляет параметр warning, который позволяет нам указать функцию, которая принимает каждое сгенерированное предупреждение и делает с ним все, что нам нравится, программно.

Все, что нам нужно сделать, - это настроить функция, которая проверяет содержимое каждого предупреждения с помощью регулярного выражения с grepl и подавляет это предупреждение, если оно соответствует нашему регулярному выражению.

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

warning_handler <- function(w)
{
  condition <- conditionMessage(w)
  if(grepl("can be ignored", condition)) invokeRestart("muffleWarning")
}

Так что теперь мы можем запустите нашу функцию создания предупреждений и просто отключите предупреждения, которые нас не волнуют.

withCallingHandlers(make_warnings(), warning = warning_handler)
#> [1] 0
#> Warning message:
#> In make_warnings() : This is a warning that shouldn't be ignored

Таким образом, вы можете видеть, что мы подавили предупреждение, которое не хотели видеть, но сохранили важное.

Если вы хотите сделать это более гибким, вы можете обернуть withCallingHandlers и вашу функцию обработки в одну функцию, которая принимает регулярное выражение в качестве первого аргумента:

with_warning_handler <- function(reg, ...)
{
  withCallingHandlers(..., warning = function(w)
    {
        condition <- conditionMessage(w)
        if(grepl(reg, condition)) invokeRestart("muffleWarning")
  })
}

Так что теперь вы можете сделайте что-то вроде этого:

with_warning_handler("can be ignored", make_warnings())
#> [1] 0
#> Warning message:
#> In make_warnings() : This is a warning that shouldn't be ignored

Итак, глядя на пример из реального мира, посмотрите на два предупреждения, которые мы получаем с помощью этой строки кода:

a <- 1:3; a[] <- as.numeric(c("A", "1"))
#> Warning messages:
#> 1: NAs introduced by coercion 
#> 2: In a[] <- as.numeric(c("A", "1")) :
#>   number of items to replace is not a multiple of replacement length

Но если мы Мы не беспокоимся о принуждении, мы можем сделать:

with_warning_handler("coercion", {a <- 1:3; a[] <- as.numeric(c("A", "1"))})
#> Warning message:
#> In a[] <- as.numeric(c("A", "1")) :
#>   number of items to replace is not a multiple of replacement length
...