Как вызвать ошибку, если встречаются нефинитные значения (NA, NaN или Inf)

В Matlab пропущен флаг условной отладки: dbstop, если описан infnan здесь .Если установлено, это условие остановит выполнение кода при обнаружении Inf или NaN (IIRC, Matlab не имеет NA).

Как я могу добиться этого в R более эффективным способом, чем тестирование всех объектов после каждой операции присваивания?

На данный момент я вижу единственные способы сделать это с помощью хаков вроде следующего:

  1. Вручную вставьте тест после всех мест, где могут встречаться эти значения (например, деление, где может происходить деление на 0). Тестирование будет заключаться в использовании is.finite () , , описанных в этих вопросах и ответах , для каждого элемента.
  2. Используйте body () , чтобы изменить код для вызова отдельной функции после каждой операции или, возможно, только каждого назначения, которое проверяет все объекты (и, возможно, все объекты во всех средах).
  3. Изменить исходный код R (?!?)
  4. Попытка использовать tracemem для идентификации тех переменных, которые изменились, и проверить только их на наличие неверных значений.
  5. (Новое - см. Примечание 2) Используйте какие-то обработчики вызовов / обратные вызовы для вызова тестовой функции.

1-й вариант - это то, что я делаю в настоящее время. Это утомительно, потому что я не могу гарантировать, что все проверил. Второй вариант проверит все, даже если объект не был обновлен. Это огромная трата времени. Третий вариант предполагает изменение присвоений NA, NaN и бесконечных значений (+/- Inf), так что возникает ошибка. Похоже, что лучше оставить R Core.Четвертый вариант похож на второй - мне понадобится вызов отдельной функции, перечисляющей все ячейки памяти, просто для идентификации тех, которые были изменены, а затем для проверки значений; Я даже не уверен, что это сработает для всех объектов, поскольку программа может выполнять модификацию на месте, которая, похоже, не будет вызывать функцию duplicate .

Есть ли лучший подход, который мне не хватает? Может быть, какой-нибудь умный инструмент от Марка Бравингтона, Люка Тирни или что-то относительно простое - что-то вроде параметра options () или флага при компиляции R?

Пример кода Вот несколько очень простых пример кода для тестирования, включающий функцию addTaskCallback , предложенную Джошем О'Брайеном. Код не прерывается, но ошибка возникает в первом сценарии, а во втором случае ошибки не возникает (т. Е. badDiv (0,0, FALSE) не прерывается). Я все еще изучаю обратные вызовы, так как это выглядит многообещающим.

badDiv  <- function(x, y, flag){
    z = x / y
    if(flag == TRUE){
        return(z)
    } else {
        return(FALSE)
    }
}

addTaskCallback(stopOnNaNs)
badDiv(0, 0, TRUE)

addTaskCallback(stopOnNaNs)
badDiv(0, 0, FALSE)

Примечание 1. Я был бы удовлетворен решением для стандартных операций R, хотя во многих моих вычислениях используются объекты, используемые через data.table или bigmemory (т.е. disk- на основе матриц с отображением памяти). Похоже, что у них несколько иное поведение памяти, чем у стандартных операций matrix и data.frame.

Примечание 2. Идея обратных вызовов кажется немного более многообещающей, поскольку это не требует от меня написания функций, которые изменяют код R, например через идею body () .

Примечание 3. Я не знаю, есть ли какой-нибудь простой способ проверить наличие не конечных значений, напримерметаинформация об объектах, которая индексирует, где в объекте хранятся NAs, Infs и т. д., или если они хранятся на месте. До сих пор я пробовал пакет Саймона Урбанека inspect и не нашел способа определить наличие нечисловых значений.

Продолжение: Саймон Урбанек указал в комментарии, что такая информация недоступна в качестве метаинформации для объектов.

Примечание 4. Я все еще тестирую представленные идеи. Кроме того, как предлагает Саймон, тестирование на наличие не конечных значений должно быть самым быстрым в C / C ++;это должно превосходить даже скомпилированный код R, но я открыт для всего. Для больших наборов данных, например порядка 10–50 ГБ, это должна быть значительная экономия по сравнению с копированием данных. Можно получить дополнительные улучшения за счет использования нескольких ядер, но это немного сложнее.

11
задан Community 23 May 2017 в 12:09
поделиться