14

Rで奇妙な問題に直面しています。

次のコードを考えてみましょう (実際のコードの非常に単純化されたバージョンですが、まだ問題があります)。

library(timeSeries)

tryCatch(
{
  specificWeekDay <- 2

  currTs <- timeSeries(c(1,2),c('2012-01-01','2012-01-02'),
                       format='%Y-%m-%d',units='A')
  # just 2 dates out of range
  start <- time(currTs)[2]+100*24*3600
  end <- time(currTs)[2]+110*24*3600

  # this line returns an empty timeSeries
  currTs <- window(currTs,start=start,end=end)

  message("Up to now, everything is OK")

  # this is the line with the uncatchable error
  currTs[!(as.POSIXlt(time(currTs))$wday %in% specificWeekDay),] <- NA

  message("I'm after the bugged line !")

},error=function(e){message(e)})

message("End")

そのコードを RGui で実行すると、次の出力が正しく得られます。


関数 '[<-' のメソッドを選択する際に引数 'i' を評価する際にエラーが発生しました: as.POSIXlt.numeric(time(currTs)) のエラー: 'origin' を指定する必要があります
End

代わりに、次の行を使用して RScript (Windows) で実行すると:

RScript.exe --vanilla "myscript.R"

私はこの出力を得る:

ここまではOK
実行中断

RScriptがクラッシュするようです...

理由について何か考えはありますか?
これは timeSeries パッケージのバグですか、それとも何か間違っていますか?
後者の場合、すべてのエラーを確実にキャッチする正しい方法は何ですか?

前もって感謝します。


編集 :

timeSeries パッケージを使用しない問題を再現する小さな例を次に示します。テストするには、上記のように実行します。

library(methods)
# define a generic function
setGeneric("foo", 
           function(x, ...){standardGeneric("foo")})
# set a method for the generic function
setMethod("foo", signature("character"),
          function(x) {x})
tryCatch(
{
  foo("abc")
  foo(notExisting)
},error=function(e)print(e))

ジェネリック メソッドのディスパッチに関連しているようです。メソッドの引数によってエラーが発生した場合、ディスパッチャーはメソッドのシグネチャを見つけることができず、その結果、RScript をtryCatch介して実行したときに関数が処理できないように見える例外を発生させます。
奇妙なことに、たとえばprint(notExisting);では起こりません。その場合、例外は正しく処理されます。

この種のエラーをキャッチする理由と方法について何か考えはありますか?

注:
Windows 7 で R-2.14.2 を使用しています。

4

2 に答える 2

17

問題は、S4 メソッド ディスパッチを実装する内部 C コードがいくつかのエラーをキャッチして処理しようとする方法と、このアプローチで非対話的なケースがどのように処理されるかです。回避策が R-devel に配置され、R-パッチがすぐに適用されるはずです。

回避策が R-devel にコミットされ、R-パッチが適用されました。

于 2012-07-11T16:46:05.723 に答える
6

tryCatch()[OPはすでに知っていて使用していましたが、気づかなかった]に関する情報

エラーに対して特別なことをしていないtryCatch()ことを見逃していると思います。したがって、通常の方法でエラーが発生しています。インタラクティブな使用では、エラーは通常の方法でスローおよび処理されますが、非インタラクティブセッション(a la )で実行されたスクリプト内のエラーは、実行中のスクリプトを中止します。Rscript

tryCatch()は、エラーだけでなく、R内のあらゆる種類のイベントをトラップして処理できるようにする複雑な関数です。ただし、デフォルトでは、標準のRエラー処理手順を模倣するように設定されています。基本的に、エラーがスローされ、Rによって報告されることを許可します。Rに基本的な動作以外のことを実行させたい場合は、エラーの特定のハンドラーを追加する必要があります。

> e <- simpleError("test error")
> tryCatch(foo, error = function(e) e,
+          finally = writeLines("There was a problem!"))
There was a problem!
<simpleError in doTryCatch(return(expr), name, parentenv, handler): object 'foo'
not found>

?tryCatchそれが何をするのかをよりよく理解するために、より詳細に読むことをお勧めします。

別の方法は、を使用することtry()です。スクリプトを変更するには、次のようにします。

# this is the line with the uncatchable error
tried <- try(currTs[!(as.POSIXlt(time(currTs))$wday %in% specificWeekDay),] <- NA,
             silent = TRUE)
if(inherits(tried, "try-error")) {
    writeLines("There was an error!")
} else {
    writeLines("Everything worked fine!")
}

重要なのは、返されるオブジェクトを保存してtry()、クラスをテストできるようにし、try()サイレントに動作させることです。違いを考慮してください:

> bar <- try(foo)
Error in try(foo) : object 'foo' not found
> bar <- try(foo, silent = TRUE)
> class(bar)
[1] "try-error"

上記の最初の呼び出しでは、エラーがキャッチれ、メッセージとして報告されることに注意してください。第二に、それは報告されていません。どちらの場合も、クラスのオブジェクト"try-error"が返されます。

内部的には、エラーをメッセージとして報告し、返されたオブジェクトを設定するエラーハンドラーのカスタム関数を設定try()する単一の呼び出しとして記述されます。を使用する別の例としてtryCatch()、Rコードを調べたいと思うかもしれません。try()tryCatch()

于 2012-07-09T11:19:48.953 に答える