Rでtrycatchを書く方法


342

trycatchウェブからのダウンロードのエラーに対処するためのコードを書きたいのですが。

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)

これらの2つのステートメントは正常に実行されます。以下に、存在しないWebアドレスを作成します。

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

url[1]存在しません。どのようにしてtrycatchループ(関数)を 作成するのですか?

  1. URLが間違っている場合、出力は「Web URLが間違っている、取得できません」となります。
  2. URLが間違っている場合、コードは停止しませんが、URLリストの最後までダウンロードを続けますか?

回答:


625

それでは、Rの世界へようこそ;-)

どうぞ

コードを設定する

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 insided 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)
}

コードを適用する

> 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

出力の調査

> 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

追加備考

tryCatch

tryCatchexprエラーや警告がない限り、実行に関連付けられた値を返します。この場合、特定の戻り値(return(NA)上記を参照)は、それぞれのハンドラー関数(引数errorwarningを参照)を提供することによって指定できます?tryCatch。これらは既に存在する関数にすることもできますが、tryCatch()(上記で行ったように)内部で定義することもできます。

ハンドラー関数の特定の戻り値を選択することの意味

NAエラーの場合に返されるように指定したので、の3番目の要素はyですNA。我々が選択した希望の場合NULL、戻り値になるように、長さはyちょうどだっただろう2の代わり3として、lapply()単にある戻り値を「無視」の意志NULL。また、を介して明示的な戻り値を指定しない場合return()、ハンドラー関数が戻りますNULL(つまり、エラーまたは警告状態の場合)。

「望ましくない」警告メッセージ

warn=FALSEどんな効果があるとは思えない、(この場合は本当に興味のない)警告を抑制するための別の方法は使用することです

suppressWarnings(readLines(con=url))

の代わりに

readLines(con=url, warn=FALSE)

複数の表現

あなたも(引数「実際の表現の一部」で複数の式を置くことができることを注意exprtryCatch()あなたは(私はに示されているだけのように中括弧でそれらをラップしている場合)finallyの部分)。


paste関数の最初の文字列がスペースで終わっているとすると、スペースとsep=""
seancarmody 2012

2
@seancarmody:true ;-)私は実際にそれらを書き込むことでスペースを制御しなければならない場合、より長く/より複雑な文字列をまとめるのに慣れています。
Rappster 2012

3
paste0そのために使用する必要があります!
seancarmody 2012

6
paste0() あるベースに。内部的には、両方paste()paste0()通話do_pastepaste.c。唯一の違いはpaste0()sep引数を渡さないことです。
jthetzel 2012

1
@JulienNavarre:「try部分」は常に最後のオブジェクトを返すことに注意してください(現在、readLines(con=url, warn=FALSE)これは実際に問題が発生する可能性があります)。したがって、メッセージを追加する場合は、実際のretun値を変数に格納する必要があります。out <- readLines(con=url, warn=FALSE)これにmessage("Everything worked")続けてout、これを実際に返される最後のオブジェクトにする
Rappster

69

Rは、try-catchブロックを実装するための関数を使用します。

構文は次のようになります。

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

tryCatch()には、「警告」と「エラー」の2つの「条件」があります。コードの各ブロックを記述するときに理解する必要がある重要なことは、実行の状態とスコープです。 @ソース


5
交換するerror-handler-codecat("web url is wrong, can't get")
seancarmody

2
メッセージキャッチを
省略した

52

tryCatch構文構造が少し複雑です。ただし、次に示すように完全なtryCatch呼び出しを構成する4つの部分を理解すると、覚えやすくなります。

expr:[ 必須 ]評価されるRコード

error:[ オプション ] exprのコードの評価中にエラーが発生した場合に実行する必要があるもの

警告:[ オプション ] exprのコードの評価中に警告が発生した場合に実行する必要があるもの

最終的に:[ オプション ] exprが正常に実行されたか、エラーが発生したか、警告が発生したかに関係なく、tryCatch呼び出しを終了する直前に何を実行するか

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

したがって、値のログを計算するおもちゃの例は次のようになります。

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.')
        }
    )    
}

ここで、3つのケースを実行します。

有効なケース

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

「警告」ケース

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

「エラー」ケース

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

私は定期的に使用するいくつかの便利なユースケースについて書きました。詳細はこちら:https : //rsangole.netlify.com/post/try-catch/

これがお役に立てば幸いです。


34

ここに簡単な例があります:

# 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)
        }
    )
}

「警告」もキャプチャしたい場合は、warning=同様のerror=パーツを追加します。


1
expr1本ではなく2本の線があるため、パーツの周りに中括弧が必要ですか?
ポール、

ありがとう!再確認した後、中括弧は必要ない
Paul

再度ご確認いただきありがとうございます。私はあなたのコードを実行すると、私はだError: unexpected ')' in " )"Error: unexpected ')' in " )"。中括弧のペアを追加すると、問題が解決します。
ポール、

ほとんどのユースケースで、あなたは正しいです、ありがとう!修正されました。
ポール、

23

irr関数のtryCatchを解こうとして2日間の人生を失ったばかりなので、自分の知恵(そして何が欠けているか)を共有する必要があると思いました。FYI-irrは、この場合のFinCalの実際の関数で、大きなデータセットでいくつかのケースでエラーが発生しました。

  1. 関数の一部としてtryCatchを設定します。例えば:

    irr2 <- function (x) {
      out <- tryCatch(irr(x), error = function(e) NULL)
      return(out)
    }
  2. エラー(または警告)が機能するためには、実際には関数を作成する必要があります。私はもともとエラーの部分について書いたばかりでerror = return(NULL)、すべての値がnullに戻ってきました。

  3. サブ出力( "out"など)とtoを作成することを忘れないでくださいreturn(out)


3
なぜ3番が必要なのですか?
jan-glx 2017
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.