Hoe schrijf je trycatch in R

Ik wil tryCatch-code schrijven om fouten bij het downloaden van internet op te lossen.

url <- c(
    "http://stat.ethz.ch/R-manual/R-devel/library/base/html/connections.html",
    "http://en.wikipedia.org/wiki/Xz")
y <- mapply(readLines, con=url)

Deze twee instructies zijn succesvol uitgevoerd. Hieronder maak ik een niet-bestaand webadres aan:

url <- c("xxxxx", "http://en.wikipedia.org/wiki/Xz")

url[1] bestaat niet. Hoe schrijf je een tryCatch lus (functie) zodat:

  1. Als de URL onjuist is, is de uitvoer: “web-URL is verkeerd, kan niet worden opgehaald”.
  2. Als de URL fout is, stopt de code niet, maar gaat door met downloaden tot het einde van de lijst met URL’s?

Antwoord 1, autoriteit 100%

Welnu: welkom in de R-wereld 😉

Hier ga je

De code instellen

urls <- c(
    "http://stat.ethz.ch/R-manual/R-devel/library/base/html/connections.html",
    "http://en.wikipedia.org/wiki/Xz",
    "xxxxx"
)
readUrl <- function(url) {
    out <- tryCatch(
        {
            # Just to highlight: if you want to use more than one 
            # R expression in the "try" part then you'll have to 
            # use curly brackets.
            # 'tryCatch()' will return the last evaluated expression 
            # in case the "try" part was completed successfully
            message("This is the 'try' part")
            readLines(con=url, warn=FALSE) 
            # The return value of `readLines()` is the actual value 
            # that will be returned in case there is no condition 
            # (e.g. warning or error). 
            # You don't need to state the return value via `return()` as code 
            # in the "try" part is not wrapped inside a function (unlike that
            # for the condition handlers for warnings and error below)
        },
        error=function(cond) {
            message(paste("URL does not seem to exist:", url))
            message("Here's the original error message:")
            message(cond)
            # Choose a return value in case of error
            return(NA)
        },
        warning=function(cond) {
            message(paste("URL caused a warning:", url))
            message("Here's the original warning message:")
            message(cond)
            # Choose a return value in case of warning
            return(NULL)
        },
        finally={
        # NOTE:
        # Here goes everything that should be executed at the end,
        # regardless of success or error.
        # If you want more than one expression to be executed, then you 
        # need to wrap them in curly brackets ({...}); otherwise you could
        # just have written 'finally=<expression>' 
            message(paste("Processed URL:", url))
            message("Some other message at the end")
        }
    )    
    return(out)
}

De code toepassen

> y <- lapply(urls, readUrl)
Processed URL: http://stat.ethz.ch/R-manual/R-devel/library/base/html/connections.html
Some other message at the end
Processed URL: http://en.wikipedia.org/wiki/Xz
Some other message at the end
URL does not seem to exist: xxxxx
Here's the original error message:
cannot open the connection
Processed URL: xxxxx
Some other message at the end
Warning message:
In file(con, "r") : cannot open file 'xxxxx': No such file or directory

De output onderzoeken

> head(y[[1]])
[1] "<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">"      
[2] "<html><head><title>R: Functions to Manipulate Connections</title>"      
[3] "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\">"
[4] "<link rel=\"stylesheet\" type=\"text/css\" href=\"R.css\">"             
[5] "</head><body>"                                                          
[6] ""    
> length(y)
[1] 3
> y[[3]]
[1] NA

Aanvullende opmerkingen

tryCatch

tryCatch retourneert de waarde die is gekoppeld aan het uitvoeren van expr tenzij er een fout of waarschuwing is. In dit geval kunnen specifieke retourwaarden (zie return(NA) hierboven) worden gespecificeerd door een respectieve handlerfunctie op te geven (zie argumenten error en warning in ?tryCatch). Dit kunnen functies zijn die al bestaan, maar je kunt ze ook definiëren binnen tryCatch() (zoals ik hierboven deed).

De implicaties van het kiezen van specifieke retourwaarden van de handlerfuncties

Omdat we hebben gespecificeerd dat NA moet worden geretourneerd in geval van een fout, is het derde element in y NA. Als we NULL als retourwaarde hadden gekozen, zou de lengte van y gewoon 2 zijn geweest in plaats van 3 als lapply() zal eenvoudigweg waarden “negeren” die NULL zijn. Merk ook op dat als u geen expliciete retourwaarde opgeeft via return(), de handlerfuncties NULL zullen retourneren (dwz in het geval van een fout of een waarschuwingsconditie).

“Ongewenst” waarschuwingsbericht

Omdat warn=FALSE geen effect lijkt te hebben, is een alternatieve manier om de waarschuwing te onderdrukken (wat in dit geval niet echt van belang is) het gebruik van

suppressWarnings(readLines(con=url))

in plaats van

readLines(con=url, warn=FALSE)

Meerdere uitdrukkingen

Merk op dat u ook meerdere uitdrukkingen in het “werkelijke uitdrukkingsgedeelte” (argument expr van tryCatch()) kunt plaatsen als u ze tussen accolades plaatst (net als Ik illustreerde in het finally deel).


Antwoord 2, autoriteit 12%

tryCatch heeft een enigszins complexe syntaxisstructuur. Zodra we echter de 4 delen begrijpen die een complete tryCatch-aanroep vormen, zoals hieronder weergegeven, wordt het gemakkelijk te onthouden:

expr: [Vereist] R-code(s) die moeten worden geëvalueerd

fout : [Optioneel] Wat moet er worden uitgevoerd als er een fout is opgetreden tijdens het evalueren van de codes in expr

waarschuwing: [Optioneel] Wat moet er worden uitgevoerd als er een waarschuwing is opgetreden tijdens het evalueren van de codes in expr

eindelijk : [Optioneel] Wat moet worden uitgevoerd net voordat de tryCatch-aanroep wordt gestopt, ongeacht of expr succesvol is uitgevoerd, met een fout of met een waarschuwing

tryCatch(
    expr = {
        # Your code...
        # goes here...
        # ...
    },
    error = function(e){ 
        # (Optional)
        # Do this if an error is caught...
    },
    warning = function(w){
        # (Optional)
        # Do this if an warning is caught...
    },
    finally = {
        # (Optional)
        # Do this at the end before quitting the tryCatch structure...
    }
)

Een speelgoedvoorbeeld om het logboek van een waarde te berekenen kan er dus als volgt uitzien:

log_calculator <- function(x){
    tryCatch(
        expr = {
            message(log(x))
            message("Successfully executed the log(x) call.")
        },
        error = function(e){
            message('Caught an error!')
            print(e)
        },
        warning = function(w){
            message('Caught an warning!')
            print(w)
        },
        finally = {
            message('All done, quitting.')
        }
    )    
}

Nu bezig met drie zaken:

Een geldige zaak

log_calculator(10)
# 2.30258509299405
# Successfully executed the log(x) call.
# All done, quitting.

Een waarschuwingsgeval

log_calculator(-10)
# Caught an warning!
# <simpleWarning in log(x): NaNs produced>
# All done, quitting.

Een “fout”-geval

log_calculator("log_me")
# Caught an error!
# <simpleError in log(x): non-numeric argument to mathematical function>
# All done, quitting.

Ik heb geschreven over een aantal handige use-cases die ik regelmatig gebruik. Vind hier meer details: https://rsangole.netlify.com/post/try-catch/

Ik hoop dat dit nuttig is.


Antwoord 3, autoriteit 10%

R gebruikt functies voor het implementeren van try-catch-blok:

De syntaxis ziet er ongeveer als volgt uit:

result = tryCatch({
    expr
}, warning = function(warning_condition) {
    warning-handler-code
}, error = function(error_condition) {
    error-handler-code
}, finally={
    cleanup-code
})

In tryCatch() zijn er twee voorwaarden die kunnen worden afgehandeld: waarschuwingen en fouten . Het belangrijkste om te begrijpen bij het schrijven van elk codeblok is de staat van uitvoering en de reikwijdte.
@source


Antwoord 4, autoriteit 7%

Hier is een duidelijk voorbeeld:

# Do something, or tell me why it failed
my_update_function <- function(x){
    tryCatch(
        # This is what I want to do...
        {
        y = x * 2
        return(y)
        },
        # ... but if an error occurs, tell me what happened: 
        error=function(error_message) {
            message("This is my custom message.")
            message("And below is the error message from R:")
            message(error_message)
            return(NA)
        }
    )
}

Als u ook een “waarschuwing” wilt vastleggen, voegt u gewoon warning= toe, vergelijkbaar met het gedeelte error=.


Antwoord 5, autoriteit 4%

Omdat ik net twee dagen van mijn leven heb verloren bij het oplossen van tryCatch voor een irr-functie, dacht ik dat ik mijn wijsheid moest delen (en wat er ontbreekt). Ter info – irr is een echte functie van FinCal, in dit geval werden er in een paar gevallen fouten gemaakt op een grote dataset.

  1. Stel tryCatch in als onderdeel van een functie. Bijvoorbeeld:

    irr2 <- function (x) {
      out <- tryCatch(irr(x), error = function(e) NULL)
      return(out)
    }
    
  2. Om de fout (of waarschuwing) te laten werken, moet je eigenlijk een functie maken. Ik schreef oorspronkelijk voor het foutgedeelte error = return(NULL) en ALLE waarden kwamen terug op null.

  3. Vergeet niet om een ​​sub-output te maken (zoals mijn “out”) en om return(out) te maken.

LEAVE A REPLY

Please enter your comment!
Please enter your name here

10 + thirteen =

Other episodes