多数の項目に対して複雑な関数を実行するために使用しておりlapply
、各項目からの出力 (ある場合) を、生成された警告/エラーとともに保存して、どの項目がどの警告/エラーを生成したかを確認できるようにしたいと考えています。
withCallingHandlers
私は(を使用して警告をキャッチする方法を見つけましたここで説明)。ただし、エラーもキャッチする必要があります。 (以下のコードのように) でラップすることで実現できますtryCatch
が、もっと良い方法はありますか?
catchToList <- function(expr) {
val <- NULL
myWarnings <- NULL
wHandler <- function(w) {
myWarnings <<- c(myWarnings, w$message)
invokeRestart("muffleWarning")
}
myError <- NULL
eHandler <- function(e) {
myError <<- e$message
NULL
}
val <- tryCatch(withCallingHandlers(expr, warning = wHandler), error = eHandler)
list(value = val, warnings = myWarnings, error=myError)
}
この関数のサンプル出力は次のとおりです。
> catchToList({warning("warning 1");warning("warning 2");1})
$value
[1] 1
$warnings
[1] "warning 1" "warning 2"
$error
NULL
> catchToList({warning("my warning");stop("my error")})
$value
NULL
$warnings
[1] "my warning"
$error
[1] "my error"
SOにはエラー処理について議論する質問がいくつかありますtryCatch
が、この特定の問題に対処するものは見つかりませんでした。関数呼び出しによって警告が発生するかどうかを確認するにはどうすればよいですか?、warnings() は関数内では機能しません。どうすればこれを回避できますか?、 そしてlapply にエラーを無視してリスト内の次の項目を処理するように指示するにはどうすればよいですか?最も関連性の高いものを選択してください。
ベストアンサー1
これはあなたの解決策と同じかもしれませんが、私はfactory
単純な古い関数をその値、エラー、警告をキャプチャする関数に変換する関数を書きました。
test <- function(i)
switch(i, "1"=stop("oops"), "2"={ warning("hmm"); i }, i)
res <- lapply(1:3, factory(test))
結果の各要素には値、エラー、および/または警告が含まれます。これは、ユーザー関数、システム関数、または匿名関数(factory(function(i) ...)
)で機能します。これがファクトリーです
factory <- function(fun)
function(...) {
warn <- err <- NULL
res <- withCallingHandlers(
tryCatch(fun(...), error=function(e) {
err <<- conditionMessage(e)
NULL
}), warning=function(w) {
warn <<- append(warn, conditionMessage(w))
invokeRestart("muffleWarning")
})
list(res, warn=warn, err=err)
}
結果リストを処理するためのヘルパー
.has <- function(x, what)
!sapply(lapply(x, "[[", what), is.null)
hasWarning <- function(x) .has(x, "warn")
hasError <- function(x) .has(x, "err")
isClean <- function(x) !(hasError(x) | hasWarning(x))
value <- function(x) sapply(x, "[[", 1)
cleanv <- function(x) sapply(x[isClean(x)], "[[", 1)