123

私が書いたR関数を使用するとエラーが発生します:

Warning messages:
1: glm.fit: algorithm did not converge 
2: glm.fit: algorithm did not converge 

私がしたこと:

  1. 関数をステップスルーします
  2. エラーが発生する行を見つけるためにprintを追加すると、を使用してはならない2つの関数が示唆されますglm.fit。彼らはwindow()save()です。

私の一般的なアプローチには、コマンドの追加printstop、例外が見つかるまで関数を1行ずつステップ実行することが含まれます。

ただし、このエラーがコード内で発生する手法を使用することは私にはわかりません。コード内のどの関数がに依存しているかさえわかりませんglm.fit。この問題を診断するにはどうすればよいですか?

4

13 に答える 13

169

デバッグは芸術形式であると言えるので、明確な特効薬はありません。どの言語でもデバッグするための優れた戦略があり、それらはここにも適用されます(たとえば、この素晴らしい記事を読んでください)。たとえば、最初に問題を再現することです...それができない場合は、より多くの情報を取得する必要があります(たとえば、ロギングを使用)。再現できたら、ソース まで減らす必要があります。

「トリック」ではなく、お気に入りのデバッグルーチンがあると言えます。

  1. エラーが発生した場合、私が通常最初に行うことは、traceback():を呼び出してスタックトレースを確認することです。これは、エラーが発生した場所を示します。これは、ネストされた関数が複数ある場合に特に役立ちます。
  2. 次に設定しoptions(error=recover)ます; これにより、エラーが発生したブラウザモードにすぐに切り替わり、そこからワークスペースを参照できます。
  3. それでも十分な情報がない場合は、通常、debug()関数を使用してスクリプトを1行ずつステップ実行します。

R 2.10(スクリプトファイルを操作する場合)の最も優れた新しいトリックは、findLineNum()andsetBreakpoint()関数を使用することです。

最後のコメントとして:エラーによっては、外部関数呼び出しの周りにステートメントを設定することも非常に役立ちますtry()tryCatch()特にS4クラスを処理する場合)。これにより、さらに多くの情報が提供される場合があり、実行時にエラーがどのように処理されるかをより細かく制御することもできます。

これらの関連する質問には多くの提案があります。

于 2009-12-10T17:51:20.497 に答える
39

私がこれまでに見た中で最高のウォークスルーは次のとおりです。

http://www.biostat.jhsph.edu/%7Erpeng/docs/R-debug-tools.pdf

誰かが賛成/反対ですか?

于 2009-07-23T03:48:02.063 に答える
33

別の質問で私Rprof()に指摘されたように、C /C++実装の高速化または移行の恩恵を受ける可能性のあるプログラムの遅い部分summaryRprof()を見つけるための優れたツールです。これは、シミュレーション作業やその他の計算またはデータ集約型のアクティビティを実行している場合に、おそらくより当てはまります。このパッケージは、結果の視覚化に役立ちます。profr

私はデバッグについて少し学んでいるので、別のスレッドからの別の提案:

  • options(warn=2)警告をエラーのように扱うように設定

optionsまた、選択したお気に入りのデバッグ機能を使用して、エラーまたは警告が発生したときにアクションの真っ只中にあなたを落とすために使用することもできます。例えば:

そして、@ Shaneのリンクの1つからの別の2つの方法:

  • 内部関数呼び出しをでラップして、try()より多くの情報を返します。
  • * apply関数.inform=TRUEの場合、applyコマンドのオプションとして(plyrパッケージから)を使用します

@JoshuaUlrichは、クラシックコマンドの条件付き機能を使用してデバッグをオン/オフにする優れた方法も指摘しました。browser()

  • デバッグしたい関数の中に入れてくださいbrowser(expr=isTRUE(getOption("myDebug")))
  • そして、グローバルオプションを設定しますoptions(myDebug=TRUE)
  • ブラウザの呼び出しをラップすることもできます。グローバルを使用myBrowse <- browser(expr=isTRUE(getOption("myDebug")))するため、で呼び出します。myBrowse()

次に、R2.10で使用できる新しい機能があります。

  • findLineNum()ソースファイル名と行番号を受け取り、関数と環境を返します。これは、.Rファイルで、行#nにエラーが返される場合に役立つようですがsource()、行#nにある関数を知る必要があります。
  • setBreakpoint()ソースファイル名と行番号を取得し、そこにブレークポイントを設定します

codetoolsパッケージ、特にその関数は、コンパイラが通常報告する構文エラーと文体エラー(未使用のローカル、未定義のグローバル関数と変数、部分的な引数の一致など)をすばやく検出checkUsageするのに特に役立ちます。

setBreakpoint()は、よりユーザーフレンドリーなフロントエンドtrace()です。これがどのように機能するかの内部の詳細は、最近のRJournalの記事で入手できます。

他の人のパッケージをデバッグしようとしている場合は、問題を特定したら、それらの関数をとで上書きできますが、本番コードでは使用しないでください。fixInNamespaceassignInNamespace

これはいずれも、実証済みの標準Rデバッグツールを排除するものではありません。これらのツールの中には、上記のものとそうでないものがあります。特に、事後デバッグツールは、再実行したくない時間のかかるコードがたくさんある場合に便利です。

最後に、エラーメッセージをスローしないように見えるトリッキーな問題options(error=dump.frames)については、この質問で詳しく説明されているように 使用できます。エラーがスローされないエラー

于 2011-03-01T15:12:05.603 に答える
30

ある時点で、glm.fit呼び出されています。つまり、呼び出す関数の1つ、またはそれらの関数によって呼び出される関数の1つが、、のいずれかを使用していることを意味しglmますglm.fit

また、上記のコメントで述べたように、これはエラーではなく警告であり、大きな違いがあります。警告からRのデバッグツールをトリガーすることはできません(誰かが私が間違っていると言う前のデフォルトオプションを使用して;-)。

警告をエラーに変えるオプションを変更すると、Rのデバッグツールの使用を開始できます。私たちから?options

 ‘warn’: sets the handling of warning messages.  If ‘warn’ is
      negative all warnings are ignored.  If ‘warn’ is zero (the
      default) warnings are stored until the top-level function
      returns.  If fewer than 10 warnings were signalled they will
      be printed otherwise a message saying how many (max 50) were
      signalled.  An object called ‘last.warning’ is created and
      can be printed through the function ‘warnings’.  If ‘warn’ is
      one, warnings are printed as they occur.  If ‘warn’ is two or
      larger all warnings are turned into errors.

だからあなたが実行すると

options(warn = 2)

次にコードを実行すると、Rはエラーをスローします。その時点で、あなたは走ることができます

traceback()

コールスタックを確認します。これが例です。

> options(warn = 2)
> foo <- function(x) bar(x + 2)
> bar <- function(y) warning("don't want to use 'y'!")
> foo(1)
Error in bar(x + 2) : (converted from warning) don't want to use 'y'!
> traceback()
7: doWithOneRestart(return(expr), restart)
6: withOneRestart(expr, restarts[[1L]])
5: withRestarts({
       .Internal(.signalCondition(simpleWarning(msg, call), msg, 
           call))
       .Internal(.dfltWarn(msg, call))
   }, muffleWarning = function() NULL)
4: .signalSimpleWarning("don't want to use 'y'!", quote(bar(x + 
       2)))
3: warning("don't want to use 'y'!")
2: bar(x + 2)
1: foo(1)

ここでは、マークされた以上のフレームを無視できます4:foo呼び出され、警告barが生成されたことがわかります。barこれにより、どの関数が呼び出していたかがわかりglm.fitます。

これをデバッグしたい場合は、別のオプションを使用して、エラーが発生したときにデバッガーに入るようにRに指示できます。警告エラーが発生したため、元の警告がトリガーされたときにデバッガーを取得します。そのためには、以下を実行する必要があります。

options(error = recover)

次に例を示します。

> options(error = recover)
> foo(1)
Error in bar(x + 2) : (converted from warning) don't want to use 'y'!

Enter a frame number, or 0 to exit   

1: foo(1)
2: bar(x + 2)
3: warning("don't want to use 'y'!")
4: .signalSimpleWarning("don't want to use 'y'!", quote(bar(x + 2)))
5: withRestarts({
6: withOneRestart(expr, restarts[[1]])
7: doWithOneRestart(return(expr), restart)

Selection:

次に、これらのフレームのいずれかにステップインして、警告がスローされたときに何が起こっていたかを確認できます。

上記のオプションをデフォルトにリセットするには、次のように入力します

options(error = NULL, warn = 0)

あなたが引用する特定の警告に関しては、コードでより多くの反復を許可する必要がある可能性が高いです。何が呼び出されているかを見つけたら、 -を使用して引数をglm.fit渡す方法を考えます。を参照してください。controlglm.control?glm.control

于 2010-12-14T18:45:05.890 に答える
23

だからbrowser()traceback()そしてdebug()バーに入るが、trace()外で待ってモーターを動かし続ける。

関数のどこかに挿入するbrowserと、実行が停止し、入力を待ちます。n(または)を使用して先に進むかEnter、でチャンク全体を実行(反復)するかc、で現在のループ/関数をf終了するか、Q;で終了することができます。を参照してください?browser

debugを使用すると、ブラウザの場合と同じ効果が得られますが、これにより、関数の実行が最初から停止します。同じショートカットが適用されます。この関数は、を使用してオフにするまで「デバッグ」モードになりますundebug(つまりdebug(foo)、関数fooを実行すると、実行するまで毎回「デバッグ」モードになりますundebug(foo))。

より一時的な代替手段はdebugonce、です。これは、次に評価された後に関数から「デバッグ」モードを削除します。

traceback何かがうまくいかなかったところ(実際のエラー)までの関数の実行の流れをあなたに与えるでしょう。

traceたとえば、を使用して関数にコードビット(つまりカスタム関数)を挿入できますbrowser。これはパッケージの関数に役立ち、怠惰すぎてうまく折りたたまれたソースコードを取得できません。

于 2010-12-14T18:26:14.917 に答える
19

私の一般的な戦略は次のようになります。

  1. 実行traceback()して明らかな問題を探します
  2. options(warn=2)警告をエラーのように扱うように設定
  3. options(error=recover)エラー時にコールスタックにステップインするように設定
于 2010-12-14T18:44:51.060 に答える
16

ここで提案されているすべての手順を実行した後、設定.verbose = TRUEするとforeach()多くの有用な情報が得られることを学びました。特に、foreachループ内を調べずにforeach(.verbose=TRUE)、foreachループ内でエラーが発生した場所を正確に示します。traceback()

于 2010-10-29T19:15:45.457 に答える
14

CRANのパッケージとして利用できるMarkBravingtonのデバッガーdebugは非常に優れており、非常に簡単です。

library(debug);
mtrace(myfunction);
myfunction(a,b);
#... debugging, can query objects, step, skip, run, breakpoints etc..
qqq(); # quit the debugger only
mtrace.off(); # turn off debugging

コードが強調表示されたTkウィンドウにポップアップ表示されるので、何が起こっているかを確認できます。もちろんmtrace()、別の関数で別の関数を呼び出すこともできます。

HTH

于 2009-07-23T08:04:13.713 に答える
12

私はギャビンの答えが好きです:私はオプションについて知りませんでした(エラー=回復)。また、コードを視覚的にステップ実行する方法を提供する「debug」パッケージを使用するのも好きです。

require(debug)
mtrace(foo)
foo(1)

この時点で、関数を示す別のデバッグウィンドウが開き、コード内のどこにいるかを示す黄色の線が表示されます。メインウィンドウでコードはデバッグモードになり、Enterキーを押し続けると、コードをステップ実行したり(他のコマンドもあります)、変数値などを調べたりできます。デバッグウィンドウの黄色い線は動き続け、場所を示します。あなたはコードの中にいます。デバッグが完了したら、次のコマンドでトレースをオフにできます。

mtrace.off()
于 2010-12-15T15:51:46.660 に答える
6

私がここで受け取った答えに基づいて、あなたは間違いなく設定をチェックするべきoptions(error=recover)です。これを設定すると、エラーが発生すると、コンソールに次のようなテキストが表示されます(traceback出力)。

> source(<my filename>)
Error in plot.window(...) : need finite 'xlim' values
In addition: Warning messages:
1: In xy.coords(x, y, xlabel, ylabel, log) : NAs introduced by coercion
2: In min(x) : no non-missing arguments to min; returning Inf
3: In max(x) : no non-missing arguments to max; returning -Inf

Enter a frame number, or 0 to exit   

1: source(<my filename>)
2: eval.with.vis(ei, envir)
3: eval.with.vis(expr, envir, enclos)
4: LinearParamSearch(data = dataset, y = data.frame(LGD = dataset$LGD10), data.names = data
5: LinearParamSearch.R#66: plot(x = x, y = y.data, xlab = names(y), ylab = data.names[i])
6: LinearParamSearch.R#66: plot.default(x = x, y = y.data, xlab = names(y), ylab = data.nam
7: LinearParamSearch.R#66: localWindow(xlim, ylim, log, asp, ...)
8: LinearParamSearch.R#66: plot.window(...)

Selection:

その時点で、入力する「フレーム」を選択できます。選択すると、次のbrowser()モードになります。

Selection: 4
Called from: stop(gettextf("replacement has %d rows, data has %d", N, n), 
    domain = NA)
Browse[1]> 

また、エラー発生時の環境を調べることができます。完了したら、入力cしてフレーム選択メニューに戻ります。完了したら、それが示すように、0終了するように入力します。

于 2012-01-20T15:33:35.190 に答える
5

最近の質問にこの回答をしましたが、完全を期すためにここに追加しています。

個人的には、デバッグに関数を使用しない傾向があります。私はこれが解決するのと同じくらい多くの問題を引き起こすことにしばしば気づきます。また、Matlabのバックグラウンドから来て、コードでこれを行うのではなく、統合開発環境(IDE)でこれを行うことができるのが好きです。IDEを使用すると、コードがクリーンでシンプルに保たれます。

Rには、「RStudio」(http://www.rstudio.com)と呼ばれるIDEを使用します。これは、Windows、Mac、およびLinuxで使用でき、非常に使いやすいものです。

2013年10月頃以降のバージョンのRstudio(0.98ish?)には、スクリプトと関数にブレークポイントを追加する機能があります。これを行うには、ファイルの左マージンをクリックしてブレークポイントを追加します。ブレークポイントを設定して、その時点からステップスルーできます。また、その環境のすべてのデータにアクセスできるため、コマンドを試すことができます。

詳細については、 http://www.rstudio.com/ide/docs/debugging/overviewを参照してください。すでにRstudioをインストールしている場合は、アップグレードが必要になる場合があります。これは比較的新しい(2013年後半)機能です。

同様の機能を持つ他のIDEもあります。

確かに、それが組み込み関数である場合は、このディスカッションで他の人が行った提案のいくつかに頼らなければならない場合があります。ただし、修正が必要なのが独自のコードである場合は、IDEベースのソリューションがまさに必要なものである可能性があります。

于 2013-12-19T02:30:10.423 に答える
1

インスタンス参照なしで参照クラスメソッドをデバッグするには

ClassName$trace(methodName, browser)
于 2017-04-26T11:57:17.487 に答える
0

エラー行番号(最も基本的な要件-BY DEFAILT)を出力しないことは、R/Rstudioのある種の冗談だと思い始めています。エラーが発生した場所を見つけるために私が見つけた唯一の信頼できる方法は、traceback()を呼び出してトップラインを確認するという追加の作業を行うことです。

于 2018-04-19T10:00:35.503 に答える