Эквивалент «броска» в R

143

Как "выкинуть" ошибку в R? У меня есть функция, которая принимает фрейм данных и некоторые имена столбцов и делает с ними что-то. Если столбцы не существуют, я хочу, чтобы функция остановилась и остановила все функции в зависимости от нее.

Я смотрел recoverи browseи , tracebackно, а, казалось, что они близки , но не то , что я ищу.

вилка
источник
2
Правильно, восстановление, браузер и трассировка предназначены для отладки, а системы try / catch предназначены для обработки ошибок в производственном коде.
Харлан,
20
Мне нравится, когда задающие вопросы используют имя функции, которую они ищут, несколько раз в вопросе;)
Хэдли
Я думаю, что есть причина, по которой у этого вопроса больше голосов, чем у первого ответа. Несмотря на то, что этот другой вопрос технически не по теме, это такое превосходно сжатое резюме незнакомой темы, которым знаменит Stack Overflow.
Джозия Йодер,

Ответы:

116

Смотрите help(tryCatch):

Об условиях сигнализирует ' signalCondition'. Кроме того, функции
' stop' и ' warning' были изменены, чтобы также принимать
аргументы условий.

а затем в разделе "См. также":

' stop' и ' warning' условия сигнала, а ' try' по сути является упрощенной версией ' tryCatch'.

так что вы, наверное, захотите stop.

Дирк Эддельбюттель
источник
24
Это прекрасно работает. R настолько странный, что не по своей вине - он был разработан задолго до того, как мы разработали хороший интерпретируемый язык.
forkandwait,
5
По словам авторов, на него сильно повлияла старая и хорошая схема Scheme. R "шепелявый", но с фанковыми структурами данных. «Интересные» части в R, вероятно, связаны с тем, что многие соглашения отличаются от других языков, в частности, от семейства языков C, которое также является синтаксически близким. Я предполагаю, потому что язык был разработан группой статистиков, которым нужен был хороший инструмент, а не разработчикам, нуждающимся в хорошем инструменте. Потребовалось много времени, чтобы
понять
5
Некоторые базовые примеры здесь были бы замечательными, не только с цитатами. Здесь stackoverflow.com/a/23917007/54964
Лео Леопольд Герц 준영
1
Я пришел к этому вопросу, когда искал, как повторно выдать ошибку в R с более разумным сообщением об ошибке, но с сохранением неповрежденной трассировки (например, вы выполняете traceback()после ошибки, чтобы увидеть, что пошло не так). Использование stopв errorаргументе of tryCatchприведет к нарушению трассировки. Однако finallyаргумент позволит создать дополнительное сообщение и сохранить полезность трассировки. Не совсем по теме, но, как я считаю, достаточно важным, чтобы оправдать несколько минусов и угрозу модерации, которая выбросит этот комментарий из окна. :-)
Mali Remorker
52

Простой пример:

f <- function(a, b){ 

    if (a == 0){ 
            stop("error message")
    }
 }
Кристиан Эррера Хименес
источник
Здесь stackoverflow.com/a/23917007/54964 для переменных в сообщениях об ошибках.
Лео Леопольд Герц 준영
8

Помимо базовых функций, которые упоминает Дирк:

Пакет R.oo имеет дополнительные функции обработки исключений, в том числе функцию throw (), которая очень полезна. Вы можете поймать исключения с помощью обычных функций try или trycatch:

> try(throw("Division by zero.")); print("It's ok!");
Error: [2009-10-22 10:24:07] Exception: Division by zero.
[1] "It's ok!"

Вы можете прочитать об этом здесь: http://www1.maths.lth.se/help/R/R.oo/

Шейн
источник
8
Хе-хе. R не достаточно фанк без OO? Извините, что перевернул, и определенно спасибо за интересный ответ, но я остановлюсь на старой простой остановке () выше.
forkandwait,
1
Теперь еще больше OO. :)
Итератор
3
@ws. Что такого интересного в R? plotотображает функцию, try stop warnвсе работает так, как вы ожидаете, и почти все, что я хочу сделать, - это однострочник.
isomorphismes
4
Часто «сила однострочных» - не лучший показатель для языка. Для многих из нас читаемый, понятный код важнее меньшего количества строк. На самом деле, для меня многое непонятно, потому что я новичок и стараюсь соответствующим образом корректировать ожидания. Но другие языки делают довольно интуитивно понятным переход от 0 к работе. R также, кажется, развил культуру умных, трудных для чтения однострочных. Я бы поспорил за культуру кода, максимально похожего на английский, который часто также может быть однострочным, как Ruby.
Филипп
6

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

Пример: чтобы проверить, существует ли столбец «c» во фрейме данных «df»:

df <- data.frame(a = numeric(), b = numeric())
stopifnot(!is.null(df$c))

Это вызовет следующую ошибку:

Error: !is.null(df$c) is not TRUE
Крис
источник
1

Вы можете проверить, существует ли столбец, и сделать все, что хотите.
Предположим, что data.frameименованный df1и проверяющий, col1существует ли столбец :

if(! any(grepl('^col1$',colnames(df1)))) stop("nonexistent column")

или

if(! any(grepl('^col1$',colnames(df1)))) return(-1)

Например

xm1
источник