8 Stimmen

warnings() funktioniert nicht innerhalb einer Funktion? Wie kann man dies umgehen?

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

Die Anzahl der Warnungen sollte 1 und nicht 0 sein. es scheint, dass warnings() gibt nichts zurück, wenn es innerhalb einer Funktion aufgerufen wird. Wie kann man dies umgehen, um innerhalb einer Funktion zu prüfen, ob Warnungen aufgetreten sind, und diese auszudrucken?

Ich möchte nicht tryCatch weil ich dann den Wert verliere, den die Funktion zurückgibt (sie kann immer noch einen gültigen Wert zurückgeben, auch wenn sie eine Warnung erzeugt hat).

5voto

Richie Cotton Punkte 112708

Hier ist der Code für suppressWarnings

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

Ich habe es ein wenig geändert und zähle jetzt die Anzahl der Warnungen.

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
}

Ein Test:

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

Ein weiterer Test:

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

2voto

Joshua Ulrich Punkte 167720

Ihr Beispiel tut eine Warnung zurückgeben.

> 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!

Die Dokumentation ist nicht eindeutig, aber ich glaube nicht, dass last.warning wird gesetzt, bis der Aufruf beendet ist (zumal der Aufruf Teil dessen ist, was zurückgegeben werden kann).

2voto

kohske Punkte 63276

Wahrscheinlich ist dies eine sehr, sehr schlechte Lösung...

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()

die Funktion zweimal aufrufen, wenn eine Warnung auftritt... obwohl ich glaube, dass es elegantere Lösungen geben muss

1voto

VitoshKa Punkte 8119

Hier ist ein Workaround

..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 
>

0voto

VitoshKa Punkte 8119

Die Warnungen werden nicht ausgegeben, bevor die Funktion zurückkehrt. Siehe die Dokumentation zu options("warn"):

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

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X