2015-10-20 2 views
2

В R функция внутри цикла не печатает предупреждения последовательно.R, последовательность предупреждения в цикле

for(i in sample(-2:2)){ 
    cat(sprintf("running for %d\n", i)) 
    j= sqrt(i) 
} 

#running for 0 
#running for -2 
#running for 1 
#running for -1 
#running for 2 
#Warning messages: 
#1: In sqrt(i) : NaNs produced 
#2: In sqrt(i) : NaNs produced 

В предупреждающие сообщения печатаются в конце и не ясно, какие ценности мы получаем предупреждение. Ищу последовательность massege предупреждения в

#running for 0 

#running for -2 
#Warning messages: 
#1: In sqrt(i) : NaNs produced 

#running for 1 

#running for -1 
#Warning messages: 
#2: In sqrt(i) : NaNs produced 

#running for 2 

Как я могу заставить R печатать предупреждение в последовательном пути (или предупреждении печати сразу же после выполнения кода)?

ответ

4

Существует параметр immediate. в функции warning специально для этой цели, попробуйте установить в функции

if (i < 5) warning("A warning", immediate. = TRUE) 

например.

foo <- function(i){ 
    if (i < 5) warning("A warning", immediate. = TRUE) 
    i } 

for (i in 3:7){ 
    cat(sprintf("running for %d\n", i)) 
    foo(i) 
} 

# running for 3 
# Warning in foo(i) : A warning 
# running for 4 
# Warning in foo(i) : A warning 
# running for 5 
# running for 6 
# running for 7 

Редактировать: На вашем новом обновлении, вам, вероятно, нужно обернуть функцию вверх в tryCatch, что-то вроде

set.seed(222) 
for(i in sample(-2:2)){ 
    cat(sprintf("running for %d\n", i)) 
    tryCatch(sqrt(i), warning = function(w) message(paste(w, "\n"))) 
} 

# running for 2 
# running for -2 
# simpleWarning in sqrt(i): NaNs produced 
# 
# 
# running for -1 
# simpleWarning in sqrt(i): NaNs produced 
# 
# 
# running for 1 
# running for 0 
+0

Спасибо, я сохраню этот ум, когда напишу свою собственную функцию. Однако общий подход, при котором нет необходимости изменять функцию foo, будет большим. –

+0

Вся ваша функция 'foo' делает это, чтобы генерировать предупреждение, поэтому его непонятно, что вы после. Возможно, попробуйте улучшить свой пример таким образом, что 'foo' сделает что-то еще, что потребует предупреждения –

+0

Смотрите мое обновление выше. –

0

От ?options опция warn перечислен, чтобы заполнить этот роль. Это не самый лучший вариант; tryCatch, скорее всего, более чистый, если предупреждения используются правильно, но это полезно для отладки.

Предупреждение: устанавливает обработку предупреждающих сообщений. Если предупреждение отрицательное, все предупреждения игнорируются. Если предупреждение равно нулю (по умолчанию), то значения сохраняются до тех пор, пока функция верхнего уровня не вернется. Если было сообщено о 10 или менее предупреждениях , они будут напечатаны в противном случае сообщением о том, как были сообщены сигналы . Создается объект, называемый last.warning, и может быть напечатано через предупреждения о функциях. Если предупреждение - одно, предупреждения печатаются по мере их возникновения. Если предупреждение равно двум или больше, все предупреждения превратились в ошибки.

options(warn=1) 
for(i in sample(-2:2)){ 
    cat(sprintf("running for %d\n", i)) 
    j <- sqrt(i) 
} 
#running for -2 
#Warning in sqrt(i) : NaNs produced 
#running for 2 
#running for 0 
#running for 1 
#running for -1 
#Warning in sqrt(i) : NaNs produced 

Вы также могли бы использовать что-то вроде:

currentWarnLevel <- getOptions("warn") 
# code that should print warn straight away 
options(warn = currentWarnLevel) 

Если вы используете пользовательский регистратор я обнаружил, что лучше всего, чтобы переопределить options(warning.expression) и используя withCallingHandlers, а затем сбросить warning.expression.