Есть флаг условной отладки, который я пропускаю из Matlab: dbstop if infnan
, описанный здесь .Если установлено, это условие остановит выполнение кода при обнаружении Inf
или NaN
(IIRC, Matlab не имеет NA).
Как я могу добиться этого в R более эффективным способом, чемтестировать все объекты после каждой операции присваивания?
В настоящий момент я вижу только один способ сделать это с помощью хаков, подобных следующему:
- Вставить тест вручную после всех мест, гдеэти значения могут встречаться (например, деление, где может произойти деление на 0).Тестирование должно было бы использовать
is.finite()
, , описанные в этом разделе вопросов и ответов , на каждом элементе. - Использование
body()
для изменения кода для вызова отдельной функции после каждой операцииили, возможно, только каждое назначение, которое проверяет все объекты (и, возможно, все объекты во всех средах). - Изменение исходного кода R (?!?)
- Попытка использовать
tracemem
дляидентифицируйте те переменные, которые изменились, и проверяйте только их на наличие неправильных значений. - (Новое - см. примечание 2). Для вызова тестовой функции используйте какой-либо обработчик вызовов / обратные вызовы.
Первый вариант - это то, что я делаю в настоящее времяЭто утомительно, потому что я не могу гарантировать, что проверил все.Второй вариант будет проверять все, даже если объект не был обновлен.Это огромная трата времени.Третий вариант будет включать в себя изменение назначений NA, NaN и бесконечных значений (+/- Inf), так что возникает ошибка.Кажется, что лучше оставить R Core.4-й вариант похож на 2-й - мне нужно вызвать отдельную функцию, перечисляющую все области памяти, просто чтобы идентифицировать те, которые изменились, и затем проверить значения;Я даже не уверен, что это будет работать для всех объектов, так как программа может выполнить модификацию на месте, которая, кажется, не вызовет функцию 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
(т. Е. Матрицы на основе дисковой памяти).Похоже, что у них поведение памяти несколько отличается от стандартных операций matrix и data.frame.
Примечание 2. Идея обратных вызовов кажется несколько более многообещающей, поскольку для этого не требуется писать функции, которые изменяют код R,например, с помощью идеи body()
.
Примечание 3. Я не знаю, существует ли какой-либо простой способ проверить наличие неконечных значений, например, метаинформацию об объектах, индексирующих где NA,Инфы и т. Д. Хранятся в объекте, или если они хранятся на месте.До сих пор я пробовал пакет inspect
Саймона Урбанека и не нашел способа предугадать присутствие нечисловых значений.
Продолжение: Саймон Урбанек указалв комментарии, что такая информация недоступна как метаинформация для объектов.
Примечание 4. Я все еще проверяю представленные идеи.Также, как предполагает Саймон, тестирование на наличие неконечных значений должно быть самым быстрым в C / C ++;это должно превосходить даже скомпилированный код R, но я открыт для всего.Для больших наборов данных, например порядка 10-50 ГБ, это должно быть значительной экономией по сравнению с копированием данных.Можно добиться дальнейших улучшений за счет использования нескольких ядер, но это немного сложнее.