source

R에서 디버깅을 위한 일반적인 제안 사항

nicesource 2023. 7. 8. 10:59
반응형

R에서 디버깅을 위한 일반적인 제안 사항

다음과 같이 작성한 R 함수를 사용할 때 오류가 발생합니다.

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

내가 한 일:

  1. 기능을 단계적으로 수행합니다.
  2. 위해 ▁functions▁adding▁to▁not▁use▁two▁should▁occurs다▁print있▁the니습▁error오류▁find▁suggests▁line기▁what할 두 가지 기능을 사용하면 안 됩니다.glm.fit은.그들은 그렇다.window()그리고.save().

나의 일반적인 접근 방식은 다음을 포함합니다.print그리고.stop예외를 찾을 수 있을 때까지 한 줄씩 기능을 수행합니다.

그러나 코드에서 이 오류가 발생하는 기술을 사용하는 것은 명확하지 않습니다.코드 내에서 어떤 기능이 종속되는지조차 확실하지 않습니다.glm.fit이 문제를 진단하려면 어떻게 해야 합니까?

디버깅은 예술의 한 형태이기 때문에 명확한 은총이 없습니다.모든 언어로 디버깅할 수 있는 좋은 전략이 있으며 여기에도 적용됩니다(예: 이 좋은 기사 읽기).예를 들어, 첫 번째는 문제를 재현하는 것입니다.그렇게 할 수 없다면 더 많은 정보(예: 로깅)를 얻어야 합니다.일단 번식할 수 있게 되면, 근원지까지 줄여야 합니다.

저는 "꼼수"보다는 "디버깅" 루틴을 가장 좋아한다고 말하고 싶습니다.

  1. 오류가 발생할 때 가장 먼저 수행하는 작업은 호출을 통해 스택 추적을 보는 것입니다.traceback()이는 오류가 발생한 위치를 보여 주며, 여러 개의 중첩 함수가 있는 경우 특히 유용합니다.
  2. 다음은 제가 설정하겠습니다.options(error=recover)그러면 오류가 발생하는 브라우저 모드로 즉시 전환되므로 작업영역을 탐색할 수 있습니다.
  3. 아직 충분한 정보가 없으면 보통 다음을 사용합니다.debug()한 줄씩 스크립트를 실행할 수 있습니다.

R 2.10(스크립트 파일로 작업할 때)의 가장 좋은 새로운 트릭은 다음과 같은 기능을 사용하는 것입니다.findLineNum()그리고.setBreakpoint()기능들.

마지막으로, 오류에 따라 설정하는 것도 매우 유용합니다.try()또는tryCatch()외부 함수 호출에 대한 문장(특히 S4 클래스를 다룰 때).이 기능은 때때로 훨씬 더 많은 정보를 제공하며 런타임에 오류를 처리하는 방법을 보다 효과적으로 제어할 수 있습니다.

다음과 같은 관련 질문에는 많은 제안이 있습니다.

제가 지금까지 본 최고의 워크스루는 다음과 같습니다.

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

찬성/반대하는 사람?

다른 질문에서 제게 지적되었듯이,Rprof()그리고.summaryRprof()C/C++ 구현의 속도를 높이거나 C/C++ 구현으로 전환하면 프로그램의 느린 부분을 찾을있는 좋은 도구입니다.시뮬레이션 작업이나 기타 컴퓨팅 또는 데이터 집약적인 작업을 수행하는 경우에는 이 기능이 더 많이 적용될 수 있습니다.패키지는 결과를 시각화하는 데 도움이 됩니다.

저는 디버깅에 대해 조금 배우고 있기 때문에 다른 스레드에서 제안할 수 있습니다.

  • options(warn=2)

사용할 수도 있습니다.options원하는 디버깅 기능을 사용하여 오류나 경고가 발생할 때 작업의 열기 속으로 바로 들어갑니다.예를 들어:

  • options(error=recover)리다달을 recover()Shane이 언급한 것처럼 오류가 발생할 때(및 R 디버깅 가이드에 문서화되어 있음).또는 실행하는 데 유용하다고 생각되는 다른 편리한 기능.

@Shane의 링크 중 하나에서 제공되는 또 다른 두 가지 방법:

  • 은 부내함호다마음무다니합리로으출로 끝냅니다.try()자세한 정보를 제공합니다.
  • **적용 함수를 사용합니다..inform=TRUE(플라이어 패키지에서) apply 명령에 대한 옵션으로

@Joshua Ulrich는 또한 고전의 조건부 능력을 사용하는 깔끔한 방법을 지적했습니다.browser(): " " " "/" " " " " " " "

  • 수 .browser(expr=isTRUE(getOption("myDebug")))
  • 글로벌 을 글벌옵을설정다니합으로 합니다.options(myDebug=TRUE)
  • 당신은 을 감쌀 수도 .myBrowse <- browser(expr=isTRUE(getOption("myDebug")))그리고 나서 전화합니다.myBrowse()글로벌을 사용하기 때문입니다.

R2.10에서는 다음과 같은 새로운 기능을 사용할 수 있습니다.

  • findLineNum()소스 파일 이름과 줄 번호를 사용하고 함수와 환경을 반환합니다.이것은 당신이 도움이 되는 것 같습니다.source()#.R 파일은 줄 #n에 오류를 반환하지만 줄 #n에 어떤 함수가 있는지 알아야 합니다.
  • setBreakpoint()과 줄 합니다.

코드 도구 패키지, 그리고 특히.checkUsage함수는 컴파일러가 일반적으로 보고하는 구문 및 스타일 오류(로컬 오류, 정의되지 않은 전역 함수 및 변수, 부분 인수 일치 등)를 빠르게 선택하는 데 특히 유용합니다.

setBreakpoint()는 보다사친프다니입드론엔화트인적용자-에 보다 친화적인 프런트 입니다.trace()이 기능의 작동 방식에 대한 자세한 내용은 최근 R Journal 기사에서 확인할 수 있습니다.

다른 사람의 패키지를 디버그하려는 경우 문제를 찾은 후 해당 기능을 덮어쓸있습니다.fixInNamespace그리고.assignInNamespace그러나 생산 코드에는 사용하지 마십시오.

이 중 어느 것도 검증된 표준 R 디버깅 도구를 배제해서는 안 되며, 그 중 일부는 위에 있고 다른 일부는 그렇지 않습니다.특히 사후 디버깅 도구는 시간이 많이 걸리는 코드 뭉치를 다시 실행하지 않을 때 유용합니다.

마지막으로, 메시지가 는 마막으로, 오류메표지않시까는문다있경수사습니다용할음을우제지운다의로되가시를 사용할 수 .options(error=dump.frames)이 질문에서 자세히 설명한 대로: 오류가 발생하지 않은 오류

부턴가, 순간어느glm.fit호출 중입니다., 여러분이 중 그 중 가 즉, 호는함수중하또호는함출는하수중것다다입니음중사는하하용나를하가나나하출▁either▁that▁using▁called다것니입,▁you▁one즉▁is▁one는▁functions▁by▁or▁functions▁of사▁those▁means▁the를 사용하는 것입니다.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)

서는 " 서표시프무수있시다습니할을임레여기된▁marked다▁frames있▁the▁here"라고 표시된 프레임을 할 수 .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그것을 통과시키는 방법을 생각해냅니다.control사한인수를 glm.control 보다?glm.control.

그렇게browser(),traceback()그리고.debug()trace()밖에서 대기하고 모터를 계속 작동시킵니다.

를 으로써.browser기능의 어딘가에서 실행이 중지되고 입력을 기다립니다.(또는 )를 사용하여 앞으로 이동하거나, 를 사용하여 전체 청크(반복)를 실행하거나, 로 현재 루프/함수를 완료하거나, 를 사용하여 종료할 수 있습니다; 참조?browser.

와 함께debug브라우저의 경우와 동일한 효과를 얻지만, 이렇게 하면 처음부터 함수의 실행이 중지됩니다.동일한 바로 가기가 적용됩니다.은 "debug"에서 "debug" 하여 해제할 까지 사용할 수 있습니다.undebug (으) 뒤에, 에이후즉.debug(foo) 함수 foo됩니다.undebug(foo)).

일시적인 은 보다일시인대다같다습니과음안은적다▁a입니다.debugonce다음 번 평가 후 기능에서 "비활성" 모드를 제거합니다.

traceback를 사용하면 오류가 발생한 부분(실제 오류)까지 함수 실행의 흐름을 볼 수 있습니다.

비트(즉, 함수에 삽입할 수 .trace를 들어, 예를 들어, 면들를예.browser이것은 패키지의 기능에 유용하며 잘 접힌 소스 코드를 얻기가 너무 귀찮습니다.

일반적인 전략은 다음과 같습니다.

  1. 려달을 합니다.traceback()한 문제를
  2. options(warn=2)
  3. options(error=recover)가 발생하면 콜 .

에 저는 설정하는 것을 ..verbose = TRUEforeach()또한 많은 유용한 정보를 제공합니다. ㅠㅠforeach(.verbose=TRUE)는 각, 는 루프마다 오류가 발생하는 위치를 보여줍니다.traceback()각 루프의 내부를 보지 않습니다.

는 Mark Bravington입니다.debugCRAN은 매우 좋고 꽤 솔직합니다.

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

개빈의 대답이 마음에 듭니다.옵션(오류 = 복구)에 대해 몰랐습니다.저는 또한 당신의 코드를 시각적으로 확인할 수 있는 '디버그' 패키지를 사용하는 것을 좋아합니다.

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

이 시점에서 사용자의 기능을 보여주는 별도의 디버그 창이 열리고 사용자가 코드에서 어디에 있는지 보여주는 노란색 선이 표시됩니다.메인 창에서 코드가 디버그 모드로 전환되고, 계속 Enter를 눌러 코드를 단계적으로 진행하고(다른 명령도 있음), 변수 값 등을 검사할 수 있습니다.디버그 창의 노란색 선이 계속 이동하여 코드의 위치를 표시합니다.디버깅을 마치면 다음을 사용하여 추적을 해제할 수 있습니다.

mtrace.off()

제가 여기서 받은 답변을 토대로, 당신은 확실히 설정을 확인해야 합니다.이 설정을 하면 오류가 발생하면 콘솔에 다음과 유사한 텍스트가 표시됩니다.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종료합니다.

최근 질문에 대한 답변을 드렸는데, 완성도를 높이기 위해 여기에 추가합니다.

저는 개인적으로 디버깅할 때 함수를 사용하지 않는 경향이 있습니다.저는 종종 이것이 해결되는 만큼 문제를 일으킨다는 것을 발견합니다.또한 Matlab 배경을 가진 저는 코드에서 이 작업을 수행하는 것보다 통합 개발 환경(IDE)에서 이 작업을 수행할 수 있는 것이 좋습니다.IDE를 사용하면 코드를 깨끗하고 간단하게 유지할 수 있습니다.

R의 경우, 저는 "RStudio"(http://www.rstudio.com )라는 IDE를 사용하는데, 이 IDE는 Windows, Mac, Linux에서 사용할 수 있고 사용하기가 매우 쉽습니다.

2013년 10월경(0.98ish?) 이후 버전의 Rstudio는 스크립트와 함수에 중단점을 추가할 수 있습니다. 이를 수행하려면 파일의 왼쪽 여백을 클릭하여 중단점을 추가하기만 하면 됩니다.중단점을 설정한 다음 그 시점부터 단계적으로 진행할 수 있습니다.또한 해당 환경의 모든 데이터에 액세스할 수 있으므로 명령을 사용해 볼 수 있습니다.

자세한 내용은 http://www.rstudio.com/ide/docs/debugging/overview 을 참조하십시오.Rstudio가 이미 설치되어 있는 경우 업그레이드가 필요할 수 있습니다. 이 기능은 2013년 후반의 비교적 새로운 기능입니다.

비슷한 기능을 가진 다른 IDE도 찾을 수 있습니다.

물론, 기본 제공 기능이라면 이 토론에서 다른 사람들이 제안한 몇 가지 제안에 의존해야 할 수도 있습니다.그러나 수정이 필요한 코드가 자신의 코드인 경우 IDE 기반 솔루션이 필요할 수 있습니다.

인스턴스 참조 없이 참조 클래스 메서드를 디버그하려면 다음과 같이 하십시오.

ClassName$trace(methodName, browser)

저는 오류 라인 번호를 인쇄하지 않는 것이 - 가장 기본적인 요구 사항 - BY DEFAILT - 은 R/R 스튜디오에서 일종의 농담이라고 생각하기 시작했습니다.오류가 발생한 곳을 찾는 유일한 신뢰할 수 있는 방법은 calloing traceback()의 추가적인 노력과 상단 라인을 보는 것입니다.

언급URL : https://stackoverflow.com/questions/4442518/general-suggestions-for-debugging-in-r

반응형