2010-10-26 20 views
8
op <- options(warn=0) #although doesn't work for any value of warn 
assign("last.warning", NULL, envir = baseenv()) 
thisDoesntWork<- function() { 
warning("HEY, this is definitely a warning!") 
cat(paste("number of warnings:",length(warnings()))) 
} 
>thisDoesntWork() 
Warning in thisDoesntWork() : HEY, this is definitely a warning! 
number of warnings: 0 

El número de advertencias debe ser 1 en lugar de 0 - Parece que warnings() no devuelve nada si se llama dentro de una función. ¿Por qué? ¿Cómo se puede solucionar esto para verificar dentro de una función si se producen advertencias e imprimirlas?warnings() no funciona dentro de una función? ¿Cómo puede uno solucionar esto?

No quiero usar tryCatch, porque luego pierdo el valor que devuelve la función (aún puede devolver un valor válido, incluso si generó una advertencia).

Respuesta

5

Aquí está el código para suppressWarnings

function (expr) 
{ 
    withCallingHandlers(expr, warning = function(w) invokeRestart("muffleWarning")) 
} 

he retocado un poco para cuente el número de advertencias en su lugar.

countWarnings <- function(expr) 
{ 
    .number_of_warnings <- 0L 
    frame_number <- sys.nframe() 
    ans <- withCallingHandlers(expr, warning = function(w) 
    { 
     assign(".number_of_warnings", .number_of_warnings + 1L, 
     envir = sys.frame(frame_number)) 
     invokeRestart("muffleWarning") 
    }) 
    message(paste("No. of warnings thrown:", .number_of_warnings)) 
    ans 
} 

Una prueba:

countWarnings(log(-1)) 
No. of warnings thrown: 1 
[1] NaN 

Otra prueba:

foo <- function() 
{ 
    warning("first warning!") 
    warning("second warning!") 
    warning("third warning!") 
    invisible() 
} 
countWarnings(foo()) 
No. of warnings thrown: 3 
NULL 
+1

También es posible que desee devolver el número de advertencias como un atributo de la respuesta. 'attr (ans," number_of_warnings ") <- .number_of_warnings' –

+0

¡Estupendo! También puedo tomar el mensaje de advertencia de esta manera ('w') –

+1

De nada. Nada dice gracias como un voto positivo. :) –

2

Su ejemplo hace devolver una advertencia.

> assign("last.warning", NULL, envir = baseenv()) 
> thisDoesntWork <- function() { 
+ warning("HEY, this is definitely a warning!") 
+ cat(paste("number of warnings:",length(warnings())),"\n") 
+ } 
> thisDoesntWork() 
number of warnings: 0 
Warning message: 
In thisDoesntWork() : HEY, this is definitely a warning! 
> warnings() # HEY, here's your warning!!! 
Warning message: 
In thisDoesntWork() : HEY, this is definitely a warning! 

La documentación no es explícita, pero no creo last.warning consigue el sistema hasta que termine la llamada (especialmente teniendo en cuenta la llamada es parte de lo que puede ser devuelto).

+0

gracias, como se ve en la mina donde escupir "número de advertencias: 0" no funciona en mi máquina-OSX con R 2.11.1 GUI 1.34 Leopard build 32-bit (5589). ¿Qué debería intentar ahora? –

+0

Ver mi edición (se me olvidó borrar 'last.warning'). No creo que nada de esto sea específico de la plataforma. –

+0

Si tiene razón acerca de que 'last.warning' no se configuró hasta que vuelva, entonces estoy atascado. Dentro de una función, ¿cómo puedo determinar si se produjo una advertencia, sin perder el valor que devuelve la función? El uso de 'tryCatch' atrapa las advertencias, por supuesto, pero parece perder el valor que la función habría devuelto si no está incrustado en un' tryCatch' –

2

Probablemente esta es una muy mala solución ...

fw<-function(){warning("warn...");return(99)} 
fn<-function(){return(88)} 

f<-function(){ 
    w<-0 
    v<-NULL 
    v<-tryCatch(fw(),warning=function(w){w}) 
    if("warning"%in%class(v)){ 
     w<-w+1 # e.g., count up the number of warning 
     v<-fw() 
    } 
    print(v) 

    v<-NULL 
    v<-tryCatch(fn(),warning=function(w){w}) 
    if("warning"%in%class(v)){ 
     w<-w+1 # e.g., count up the number of warning 
     v<-fn() 
    } 
    print(v) 
} 
f() 

llamar a la función dos veces si se produce la advertencia ... aunque creo que tiene que haber soluciones más elegantes

+0

Sí, acabo de empezar a pensar en esto yo mismo :) Es un dolor codificar tan poco elegante –

0

Las advertencias son emitido no antes de que la función regrese. Consulte la documentación de opciones ("advertir"):

options(warn=1L) 
thisDoesntWork() 
#Warning in thisDoesntWork() : HEY, this is definitely a warning! 
#number of warnings: 1 
+0

Al igual que la primera persona en responder, creo que se olvidó de llamar a assign ("last.warning", NULL, envir = baseenv()) primero.Si es así, esa 1 advertencia que la función encuentra es de una llamada previa ... –

+0

Oh, maldición, eso es correcto. Algo sospechoso está sucediendo allí. – VitoshKa

+0

Esto parece un error para mí. Lo reportaría en r-devel. – VitoshKa

1

Aquí es una solución

..my_warning <- 0L 

thisDoesWork<- function(){ 
    assign("last.warning", NULL, envir = baseenv()) 
    warning("HEY, this is definitely a warning!", {..my_warning <<- ..my_warning+1L;""}) 
    str(last.warning) 
    cat(paste("number of warnings:", ..my_warning, "\n")) 
} 


thisDoesWork() 
Warning in thisDoesWork() : HEY, this is definitely a warning! 
NULL 
number of warnings: 1 
>  thisDoesWork() 
Warning in thisDoesWork() : HEY, this is definitely a warning! 
NULL 
number of warnings: 2 
>  thisDoesWork() 
Warning in thisDoesWork() : HEY, this is definitely a warning! 
NULL 
number of warnings: 3 
> 
+0

Sí, un error, pero, para ser honesto, uso '<< -' mucho :) –

+1

Otra forma es usar las opciones. En cualquier caso, se necesita algún tipo de "globalidad" . – VitoshKa

Cuestiones relacionadas