[r] R에서 디버깅을위한 일반적인 제안
내가 작성한 R 함수를 사용할 때 오류가 발생합니다.
Warning messages:
1: glm.fit: algorithm did not converge
2: glm.fit: algorithm did not converge
내가 뭘 한거지:
- 기능 살펴보기
- 어떤 줄에서 오류가 발생하는지 확인하기 위해 print를 추가하면
glm.fit
. 그들은window()
및save()
입니다.
내 일반적인 접근 방식에는 추가 print
및 stop
명령, 예외를 찾을 수있을 때까지 기능을 한 줄씩 단계별로 실행하는 것이 포함됩니다.
그러나이 오류가 코드에서 발생하는 기술을 사용하는 것은 분명하지 않습니다. 코드 내에서 어떤 기능이에 의존하는지조차 확실하지 않습니다 glm.fit
. 이 문제를 진단하려면 어떻게해야합니까?
답변
디버깅은 예술 형식이므로 명확한 은색 총알이 없습니다. 모든 언어로 디버깅 할 수있는 좋은 전략이 있으며 여기에서도 적용됩니다 (예 : 이 멋진 기사 읽기 ). 예를 들어, 첫 번째 일은 문제 를 재현하는 것입니다 … 그렇게 할 수 없다면 더 많은 정보를 얻어야합니다 (예 : 로깅). 재현 할 수 있으면 소스 로 줄여야 합니다.
“속임수”라기보다는 내가 좋아하는 디버깅 루틴이 있다고 말하고 싶습니다.
- 오류가 발생하면 일반적으로 가장 먼저 수행하는 작업은 다음을 호출하여 스택 추적을 보는
traceback()
것입니다. 이는 오류가 발생한 위치를 보여줍니다. 여러 중첩 함수가있는 경우 특히 유용합니다. - 다음으로 설정하겠습니다
options(error=recover)
. 이렇게하면 오류가 발생한 브라우저 모드로 즉시 전환되므로 거기에서 작업 공간을 탐색 할 수 있습니다. - 그래도 정보가 충분하지 않으면 일반적으로
debug()
함수를 사용 하고 스크립트를 한 줄씩 단계별로 실행합니다.
R 2.10의 가장 새로운 트릭 (스크립트 파일 작업시)은 findLineNum()
및 setBreakpoint()
함수 를 사용하는 것입니다.
마지막으로, 오류에 따라 외부 함수 호출 (특히 S4 클래스를 다룰 때)에 대한 설정 try()
또는 tryCatch()
명령문이 매우 유용합니다 . 이는 때로 더 많은 정보를 제공하고 런타임에 오류를 처리하는 방법을 더 잘 제어 할 수 있도록합니다.
이러한 관련 질문에는 많은 제안이 있습니다.
답변
지금까지 본 최고의 연습은 다음과 같습니다.
http://www.biostat.jhsph.edu/%7Erpeng/docs/R-debug-tools.pdf
동의 / 동의하지 않는 사람이 있습니까?
답변
으로는 나에게 지적 된 또 다른 질문 , Rprof()
그리고 summaryRprof()
수있는 좋은 도구 프로그램의 느린 부분을 찾을 수는 그 속도를 향상 또는 C / C ++ 구현에 이동에서 힘 혜택은. 이는 시뮬레이션 작업이나 기타 컴퓨팅 또는 데이터 집약적 인 활동을 수행하는 경우 더 많이 적용될 수 있습니다. profr
패키지 는 결과를 시각화하는 데 도움 이 될 수 있습니다.
나는 디버깅에 대해 약간 배우고 있으므로 다른 스레드의 또 다른 제안 :
options(warn=2)
경고를 오류처럼 처리하도록 설정
또한 options
선호하는 디버깅 기능을 사용하여 오류 또는 경고가 발생할 때 행동의 열기에 바로 빠져들 수 있습니다. 예를 들면 :
- Shane이 언급 한대로 오류가 발생
options(error=recover)
하면 실행되도록 설정 합니다recover()
(그리고 R 디버깅 가이드에 설명되어 있습니다. 또는 실행하면 유용하다고 생각되는 기타 편리한 기능).
@Shane의 링크 중 하나에서 또 다른 두 가지 방법 :
- 내부 함수 호출을
try()
로 래핑하여 더 많은 정보를 반환합니다. - * apply 기능의 경우
.inform=TRUE
(plyr 패키지에서) apply 명령에 대한 옵션으로 사용하십시오.
@JoshuaUlrich 는 또한 클래식 browser()
명령 의 조건부 기능을 사용하여 디버깅을 켜거나 끄는 깔끔한 방법을 지적했습니다 .
- 디버그하려는 함수 안에 넣으십시오.
browser(expr=isTRUE(getOption("myDebug")))
- 다음으로 글로벌 옵션을 설정하십시오.
options(myDebug=TRUE)
- 브라우저 호출을 래핑
myBrowse <- browser(expr=isTRUE(getOption("myDebug")))
한 다음myBrowse()
전역을 사용하므로 with를 호출 할 수도 있습니다.
그런 다음 R 2.10에서 사용할 수있는 새로운 기능이 있습니다.
findLineNum()
소스 파일 이름과 줄 번호를 받아 함수와 환경을 반환합니다. 이것은source()
.R 파일이고 #n 줄에 오류를 반환 할 때 도움이되는 것 같지만 , #n 줄에 어떤 함수가 있는지 알아야합니다.setBreakpoint()
소스 파일 이름과 줄 번호를 가져와 거기에 중단 점을 설정합니다.
codetools의 패키지, 특히 그 checkUsage
기능은 빠르게 구문과 컴파일러는 일반적으로보고 할 것이라고 문체 오류 따기에 (사용되지 않는 지역 주민, 글로벌 함수와 변수, 부분 인수 매칭을 정의되지 않은, 등)에 특히 도움이 될 수 있습니다.
setBreakpoint()
는보다 사용자 친화적 인 trace()
. 이것이 작동하는 방식의 내부에 대한 자세한 내용은 최근 R Journal 기사 에서 확인할 수 있습니다 .
다른 사람의 패키지를 디버깅하려는 경우 문제를 찾으면 해당 함수 를 fixInNamespace
및로 덮어 쓸 수assignInNamespace
있지만 프로덕션 코드에서는 사용하지 마십시오.
이 중 일부는 위에 있고 일부는 그렇지 않은 검증 된 표준 R 디버깅 도구를 배제해서는 안됩니다. 특히, 사후 디버깅 도구 는 시간이 많이 걸리는 코드를 다시 실행하지 않으려는 경우에 유용합니다.
마지막으로 오류 메시지를 표시하지 않는 것처럼 보이는 까다로운 문제의 경우 options(error=dump.frames)
다음 질문에 자세히 설명 된대로
사용할 수 있습니다 . 오류가 발생하지 않는 오류
답변
어느 시점에서 glm.fit
호출되고 있습니다. 즉, 호출하는 함수 중 하나 또는 해당 함수에서 호출하는 함수 중 하나가 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
, 그것에게 전달하는 방법을 해결 control
하여 인수를 glm.control
– 참조 ?glm.control
.
답변
그래서 browser()
, traceback()
그리고 debug()
술집으로 걸어 있지만, trace()
대기 외부 모터 실행을 유지합니다.
browser
함수 어딘가에 삽입 하면 실행이 중지되고 입력을 기다립니다. 를 사용하여 n(또는 Enter) 앞으로 이동 하거나를 사용 하여 전체 청크 (반복)를 실행 c하거나을 사용하여 현재 루프 / 함수를 완료 f하거나으로 종료 할 수 있습니다 Q. 참조하십시오 ?browser
.
를 사용하면 debug
브라우저와 동일한 효과를 얻을 수 있지만 처음에 함수 실행이 중지됩니다. 동일한 단축키가 적용됩니다. 이 함수는를 사용하여 끌 때까지 “디버그”모드에 있습니다 undebug
(즉, 이후 debug(foo)
에 함수 foo
를 실행하면 실행할 때까지 매번 “디버그”모드로 들어갑니다 undebug(foo)
).
좀 더 일시적인 대안은 debugonce
다음 번에 평가 될 때 함수에서 “디버그”모드를 제거합니다.
traceback
문제가 발생한 곳 (실제 오류)까지 함수 실행 흐름을 제공합니다.
trace
예를 들어를 사용하여 함수에 코드 비트 (예 : 사용자 정의 함수)를 삽입 할 수 있습니다 browser
. 이것은 패키지의 함수에 유용하며 멋지게 접힌 소스 코드를 얻기에는 너무 게으르다.
답변
내 일반적인 전략은 다음과 같습니다.
traceback()
명백한 문제를 찾기 위해 실행options(warn=2)
경고를 오류처럼 처리하도록 설정options(error=recover)
오류 발생시 호출 스택에 들어가도록 설정
답변
여기에 제안 된 모든 단계를 수행 한 후, 설정 하면 유용한 정보 .verbose = TRUE
가 foreach()
많이 제공 된다는 사실을 방금 알게 되었습니다 . 특히 foreach(.verbose=TRUE)
foreach 루프 내부에서 오류가 발생하는 위치를 정확히 보여 주지만 foreach 루프 내부를 traceback()
보지 않습니다.