Eu recebo um erro ao usar uma função R que escrevi:
Warning messages:
1: glm.fit: algorithm did not converge
2: glm.fit: algorithm did not converge
O que eu fiz:
- Percorrer a função
- Adicionar impressão para descobrir em que linha o erro ocorre sugere duas funções que não devem ser usadas
glm.fit
. Eles sãowindow()
esave()
.
Minhas abordagens gerais incluem adição print
e stop
comandos, e percorrendo uma função linha por linha até que eu possa localizar a exceção.
No entanto, não está claro para mim usando essas técnicas de onde esse erro vem no código. Nem tenho certeza de quais funções do código dependem glm.fit
. Como faço para diagnosticar esse problema?
options(warn = 2)
. Portanto, neste caso, os detalhes são essenciais para responder à sua pergunta geral. +1 de mim.Respostas:
Eu diria que a depuração é uma forma de arte, portanto não há uma bala de prata clara. Existem boas estratégias para depuração em qualquer idioma, e elas se aplicam aqui também (por exemplo, leia este belo artigo ). Por exemplo, a primeira coisa é reproduzir o problema ... se você não puder fazer isso, precisará obter mais informações (por exemplo, com o log). Depois de reproduzi-lo, é necessário reduzi -lo até a fonte.
Em vez de um "truque", eu diria que tenho uma rotina de depuração favorita:
traceback()
: que mostra onde ocorreu o erro, o que é especialmente útil se você tiver várias funções aninhadas.options(error=recover)
; isso muda imediatamente para o modo de navegador onde o erro ocorre, para que você possa navegar na área de trabalho a partir daí.debug()
função e passo o script linha por linha.O melhor novo truque no R 2.10 (ao trabalhar com arquivos de script) é usar as funções
findLineNum()
esetBreakpoint()
.Como comentário final: dependendo do erro, também é muito útil definir
try()
ou fazertryCatch()
declarações em torno de chamadas de funções externas (especialmente ao lidar com classes S4). Às vezes, isso fornece ainda mais informações e também oferece mais controle sobre como os erros são tratados no tempo de execução.Essas perguntas relacionadas têm muitas sugestões:
fonte
browser()
para quando houver erros que não acionem avisos / erros (crédito: Roman Luštrik nesta página). Alguma outra ferramenta comobrowser()
?A melhor explicação que eu vi até agora é:
http://www.biostat.jhsph.edu/%7Erpeng/docs/R-debug-tools.pdf
Alguém concorda / discorda?
fonte
Como foi apontado para mim em outra pergunta ,
Rprof()
esummaryRprof()
são agradáveis ferramentas para encontrar partes lentas do seu programa que benefício pode de acelerar ou mudar-se para a implementação de um C / C ++. Isso provavelmente se aplica mais se você estiver realizando um trabalho de simulação ou outras atividades intensivas em computação ou dados. Oprofr
pacote pode ajudar a visualizar os resultados.Estou em um pontapé de aprender sobre a depuração, então outra sugestão de outro segmento :
options(warn=2)
para tratar avisos como errosVocê também pode usá
options
-lo diretamente no calor da ação quando ocorrer um erro ou aviso, usando sua função de depuração favorita de sua escolha. Por exemplo:options(error=recover)
para executarrecover()
quando ocorrer um erro, como observou Shane (e conforme documentado no guia de depuração R.) Ou qualquer outra função útil que você ache útil executar.E outros dois métodos de um dos links de @ Shane :
try()
para retornar mais informações..inform=TRUE
(do pacote plyr) como uma opção para o comando applyO @JoshuaUlrich também apontou uma maneira elegante de usar as habilidades condicionais do
browser()
comando clássico para ativar / desativar a depuração:browser(expr=isTRUE(getOption("myDebug")))
options(myDebug=TRUE)
myBrowse <- browser(expr=isTRUE(getOption("myDebug")))
e depois ligar,myBrowse()
já que ela usa globais.Depois, há as novas funções disponíveis no R 2.10:
findLineNum()
pega um nome de arquivo de origem e número de linha e retorna a função e o ambiente. Isso parece ser útil quando vocêsource()
cria um arquivo .R e retorna um erro na linha #n, mas você precisa saber qual função está localizada na linha #n.setBreakpoint()
pega um nome de arquivo de origem e número de linha e define um ponto de interrupção láO pacote codetools , e particularmente sua
checkUsage
função, podem ser particularmente úteis para captar rapidamente erros de sintaxe e estilo que um compilador normalmente reportaria (locais não utilizados, funções e variáveis globais indefinidas, correspondência parcial de argumentos e assim por diante).setBreakpoint()
é um front-end mais fácil de usartrace()
. Detalhes sobre os aspectos internos de como isso funciona estão disponíveis em um artigo recente do R Journal .Se você estiver tentando depurar o pacote de outra pessoa, depois de localizar o problema, poderá sobrescrever suas funções com
fixInNamespace
eassignInNamespace
, mas não use isso no código de produção.Nada disso deve impedir as ferramentas de depuração padrão R comprovadas , algumas das quais estão acima e outras não. Em particular, as ferramentas de depuração post-mortem são úteis quando você tem um monte de código demorado que você prefere não executar novamente.
Por fim, para problemas complicados que parecem não gerar uma mensagem de erro, você pode usar
options(error=dump.frames)
conforme detalhado nesta pergunta: Erro sem que um erro seja geradofonte
Em algum momento,
glm.fit
está sendo chamado. Isso significa que uma das funções que você chama ou uma das funções chamadas por essas funções está usandoglm
,glm.fit
.Além disso, como mencionei no meu comentário acima, isso é um aviso, não um erro , o que faz uma grande diferença. Você não pode acionar nenhuma das ferramentas de depuração de R a partir de um aviso (com opções padrão antes que alguém me diga que estou errado ;-).
Se alterarmos as opções para transformar avisos em erros, poderemos começar a usar as ferramentas de depuração de R. De
?options
nós temos:Então, se você correr
Em seguida, execute seu código, R lançará um erro. Nesse ponto, você pode executar
para ver a pilha de chamadas. Aqui está um exemplo.
Aqui você pode ignorar os quadros marcados
4:
e mais altos. Vemos issofoo
chamadobar
e quebar
gerou o aviso. Isso deve mostrar quais funções estavam chamandoglm.fit
.Se você deseja agora depurar isso, podemos mudar para outra opção para solicitar ao R que entre no depurador quando encontrar um erro e, como cometemos erros de aviso, obteremos um depurador quando o aviso original for acionado. Para isso, você deve executar:
Aqui está um exemplo:
Você pode entrar em qualquer um desses quadros para ver o que estava acontecendo quando o aviso foi lançado.
Para redefinir as opções acima para o padrão, digite
Quanto ao aviso específico que você cita, é altamente provável que você precise permitir mais iterações no código. Depois de descobrir o que está chamando
glm.fit
, descubra como passar ocontrol
argumento usandoglm.control
- veja?glm.control
.fonte
Então
browser()
,traceback()
e entredebug()
em um bar, mastrace()
espera do lado de fora e mantém o motor ligado.Ao inserir
browser
em algum lugar da sua função, a execução será interrompida e aguardará sua entrada. Você pode avançar usando n(ou Enter), executar o bloco inteiro (iteração) com c, terminar o loop / função atual com fou sair com Q; veja?browser
.Com
debug
, você obtém o mesmo efeito do navegador, mas isso interrompe a execução de uma função no início. Os mesmos atalhos se aplicam. Esta função estará no modo "depuração" até você desativá-la usandoundebug
(ou seja, após adebug(foo)
execução, a funçãofoo
entrará no modo "depuração" toda vez que você executarundebug(foo)
).Uma alternativa mais transitória é
debugonce
, que removerá o modo "depuração" da função após a próxima avaliação.traceback
fornecerá o fluxo de execução de funções até o ponto em que algo deu errado (um erro real).Você pode inserir bits de código (ou seja, funções personalizadas) em funções usando
trace
, por exemplobrowser
. Isso é útil para funções de pacotes e você é muito preguiçoso para obter o código-fonte bem dobrado.fonte
Minha estratégia geral se parece com:
traceback()
para ver problemas óbviosoptions(warn=2)
para tratar avisos como errosoptions(error=recover)
para entrar na pilha de chamadas por errofonte
Depois de passar por todos os passos sugeridos aqui eu aprendi que a criação
.verbose = TRUE
deforeach()
também me dá toneladas de informações úteis. Em particular,foreach(.verbose=TRUE)
mostra exatamente onde ocorre um erro dentro do loop foreach, enquantotraceback()
não olha dentro do loop foreach.fonte
O depurador de Mark Bravington, que está disponível como pacote
debug
no CRAN, é muito bom e bastante direto.O código aparece em uma janela Tk destacada para que você possa ver o que está acontecendo e, é claro, pode chamar outro
mtrace()
enquanto estiver em uma função diferente.HTH
fonte
Eu gosto da resposta de Gavin: eu não sabia sobre opções (erro = recuperar). Também gosto de usar o pacote 'debug' que fornece uma maneira visual de percorrer seu código.
Nesse ponto, ele abre uma janela de depuração separada mostrando sua função, com uma linha amarela mostrando onde você está no código. Na janela principal, o código entra no modo de depuração, e você pode continuar pressionando enter para percorrer o código (e também existem outros comandos) e examinar valores de variáveis etc. A linha amarela na janela de depuração continua se movendo para mostrar onde você está no código. Quando terminar a depuração, você pode desativar o rastreamento com:
fonte
Com base na resposta que recebi aqui , você deve definitivamente conferir a
options(error=recover)
configuração. Quando isso estiver definido, ao encontrar um erro, você verá um texto no console semelhante ao seguinte (traceback
saída):Em que ponto você pode escolher em qual "quadro" entrar. Ao fazer uma seleção, você será colocado no
browser()
modo:E você pode examinar o ambiente como era no momento do erro. Quando terminar, digite
c
para retornar ao menu de seleção de quadro. Quando terminar, como ele diz, digite0
para sair.fonte
Dei essa resposta a uma pergunta mais recente, mas estou adicionando-a aqui para completar.
Pessoalmente, eu não costumo usar funções para depurar. Costumo achar que isso causa tantos problemas quanto resolve. Além disso, vindo de um background do Matlab, gosto de poder fazer isso em um ambiente de desenvolvimento integrado (IDE), em vez de fazer isso no código. O uso de um IDE mantém seu código limpo e simples.
Para o R, eu uso um IDE chamado "RStudio" ( http://www.rstudio.com ), que está disponível para Windows, Mac e Linux e é muito fácil de usar.
As versões do Rstudio desde outubro de 2013 (0.98ish?) Têm a capacidade de adicionar pontos de interrupção em scripts e funções: para isso, basta clicar na margem esquerda do arquivo para adicionar um ponto de interrupção. Você pode definir um ponto de interrupção e depois avançar a partir desse ponto. Você também tem acesso a todos os dados nesse ambiente, para poder experimentar os comandos.
Consulte http://www.rstudio.com/ide/docs/debugging/overview para obter detalhes. Se você já possui o Rstudio instalado, pode ser necessário atualizar - esse é um recurso relativamente novo (final de 2013).
Você também pode encontrar outros IDEs com funcionalidade semelhante.
É certo que, se for uma função interna, talvez você precise recorrer a algumas das sugestões feitas por outras pessoas nesta discussão. Mas, se é o seu próprio código que precisa ser corrigido, uma solução baseada em IDE pode ser exatamente o que você precisa.
fonte
Para depurar métodos da classe Reference sem referência à instância
fonte
Estou começando a pensar que não imprimir o número da linha de erro - um requisito mais básico - POR PADRÃO - é algum tipo de piada no R / Rstudio . O único método confiável que encontrei para descobrir onde ocorreu um erro é fazer um esforço adicional de chamar traceback () e ver a linha superior.
fonte