124 votes

Suggestions générales pour le débogage R?

J'obtiens une erreur de R lors de l'utilisation d'une fonction que j'ai écrit:

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

Ce que j'ai fait

  1. étape par le biais de la fonction,
  2. l'ajout d'impression pour savoir à quelle ligne l'erreur se produit suggère deux fonctions qui ne devraient pas utiliser les glm.ajustement: window ou save

Mon général, les approches incluent l'ajout d' print et stop commandes, et pas à pas au travers d'une fonction de ligne par ligne jusqu'à ce que je puisse les localiser l'exception.

Cependant, il n'est pas clair pour moi à l'aide de ces techniques d'où cela vient l'erreur dans le code. Je ne suis même pas certain des fonctions au sein du code dépend glm.fit. Comment dois-je aller sur le diagnostic de ce problème?

170voto

Shane Points 40885

Je dirais que le débogage est une forme d'art, donc il n'y a pas de clair de balle en argent. Il y a des bonnes stratégies pour le débogage dans n'importe quelle langue, et ils s'appliquent ici aussi (par exemple, de lire ce bel article d'IBM). Par exemple, la première chose est de reproduire le problème...si vous ne pouvez pas faire cela, alors vous avez besoin pour obtenir plus de renseignements (par exemple, avec l'exploitation forestière). Une fois que vous pouvez le reproduire, vous avez besoin pour réduire à la source.

Plutôt qu'un "truc", je dirais que j'ai un favori de débogage de routine:

  1. Lorsqu'une erreur se produit, la première chose que j'ai l'habitude de faire est de regarder la trace de la pile en appelant traceback(): qui vous montre où l'erreur s'est produite, ce qui est particulièrement utile si vous avez plusieurs fonctions imbriquées.
  2. La prochaine je mettrai options(error=recover); il passe immédiatement en mode navigateur où l'erreur se produit, de sorte que vous pouvez parcourir l'espace de travail à partir de là.
  3. Si je n'ai pas encore assez d'informations, j'ai l'habitude d'utiliser l' debug() de la fonction et de parcourir le script ligne par ligne.

Le meilleur nouveau truc dans la R 2.10 (lorsque vous travaillez avec des fichiers de script) est d'utiliser l' findLineNum() et setBreakpoint() fonctions.

Comme un dernier commentaire: en fonction de l'erreur, elle est également très utile de créer, try() ou tryCatch() états autour des appels de fonction externe (surtout lorsqu'il s'agit S4 classes). Qui va parfois encore plus d'informations, et il vous donne également plus de contrôle sur la manière dont les erreurs sont traitées au moment de l'exécution.

Ces questions ont beaucoup de suggestions:

39voto

Christopher DuBois Points 7589

La meilleure soluce que j'ai vu jusqu'à présent est:

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

Quelqu'un accord ou en désaccord?

33voto

Ari B. Friedman Points 24940

Comme il a été souligné à moi dans une autre question, Rprof() et summaryRprof() sont sympas outils pour trouver des parties lentes de votre programme qui pourraient bénéficier de l'accélération ou de passer à un C/C++ mise en œuvre. C'est probablement ce qui s'applique plus si vous faites un travail de simulation ou d'autres calculs ou des données d'activités intensives. L' profr package peut aider à visualiser les résultats.

Je suis sur un peu de savoir-sur-le débogage coup de pied, donc une autre suggestion à partir d' un autre thread:

  • Ensemble options(warn=2) pour traiter les avertissements comme des erreurs

Vous pouvez également utiliser options de vous déposer à droite dans le feu de l'action lorsqu'une erreur ou un avertissement se produit, à l'aide de votre favori de débogage de la fonction de choix. Par exemple:

  • Ensemble options(error=recover) pour exécuter recover() lorsqu'une erreur se produit, que Shane a noté (et comme il est démontré dans la R de débogage guide. Ou de toute autre fonction très pratique que vous trouverez utile d'avoir couru.

Et de l'autre des deux méthodes à partir de l'une de @Shane liens:

  • Envelopper intérieure d'un appel de fonction avec try() de rendement plus d'informations sur elle.
  • *Appliquer des fonctions, utilisez .inform=TRUE (à partir du package plyr) comme une option à la commande appliquer

@JoshuaUlrich également souligné une belle façon d'utiliser le conditionnel capacités de la classique browser() de commande pour activer/désactiver le débogage:

  • Mis à l'intérieur de la fonction que vous pourriez souhaitez déboguer browser(expr=isTRUE(getOption("myDebug")))
  • Et définissez l'option globale en options(myDebug=TRUE)
  • Vous pourriez même envelopper le navigateur d'appel: myBrowse <- browser(expr=isTRUE(getOption("myDebug"))) , puis appeler avec myBrowse() car il utilise des variables globales.

Puis il y a les nouvelles fonctions disponibles dans la R 2.10:

  • findLineNum() prend un nom de fichier source et le numéro de ligne et renvoie à la fonction et à l'environnement. Cela semble être utile lorsque vous source() une .R fichier et retourne une erreur à la ligne #n, mais vous avez besoin de savoir quelle fonction est situé sur la ligne n.
  • setBreakpoint() prend un nom de fichier source et le numéro de ligne et définit un point d'arrêt, il y

Les outils de code de package, et en particulier de ses checkUsage fonction peut être particulièrement utile dans vite ramasser sur la syntaxe et les erreurs stylistiques qu'un compilateur généralement de rapport (non utilisé habitants, pas défini les fonctions globales et les variables, partielle argument correspondant, et ainsi de suite).

setBreakpoint() est plus convivial front-end trace(). Les détails sur le fonctionnement interne de comment cela fonctionne sont disponibles dans une récente R un article de Journal.

Si vous essayez de déboguer un autre paquet, une fois que vous avez localisé le problème, vous pouvez écraser leurs fonctions avec fixInNamespace et assignInNamespace, mais ne pas l'utiliser dans le code de production.

Rien de tout cela il ne devrait pas essayé-et-vrai standard R des outils de débogage, certains sont au-dessus et d'autres qui ne le sont pas. En particulier, le post-mortem des outils de débogage sont à portée de main lorsque vous avez du temps tas de code que vous préférez ne pas exécuter de nouveau.

Enfin, pour résoudre les problèmes épineux qui ne semblent pas à jeter un message d'erreur, vous pouvez utiliser options(error=dump.frames) comme détaillé dans cette question: Erreur sans une erreur est générée

30voto

Gavin Simpson Points 72349

À un certain point, glm.fit . Cela signifie que l'une des fonctions de vous appeler ou de l'une de ces fonctions appelées par ces fonctions est en utilisant soit glm, glm.fit.

Aussi, comme je le mentionne dans mon commentaire ci-dessus, c'est un avertissement, pas une erreur, ce qui fait une grande différence. Vous ne pouvez pas déclencher R s outils de débogage à partir d'un avertissement (avec les options par défaut avant que quelqu'un me dit que je me trompe ;-).

Si nous changer les options pour activer les avertissements en erreurs, alors nous pouvons commencer à utiliser des R des outils de débogage. D' ?options nous avons:

 ‘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.

Donc, si vous exécutez

options(warn = 2)

puis exécutez votre code, R renvoie une erreur. À ce stade, vous pourriez exécuter

traceback()

pour voir la pile d'appel. Ici est un exemple.

> 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)

Ici, vous pouvez ignorer les images marquées 4: et plus. Nous voyons qu' foo appelés bar et bar a généré le message d'avertissement. Cela devrait vous montrer les fonctions d'appel glm.fit.

Maintenant, si vous souhaitez déboguer cela, nous pouvons nous tourner vers une autre option à dire R pour entrer dans le débogueur lorsqu'il rencontre une erreur, et comme nous l'avons fait avertissements d'erreurs, nous allons obtenir un débogueur, lorsque la première alerte est déclenchée. Pour cela, vous devez exécuter:

options(error = recover)

Voici un exemple:

> 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:

Vous pouvez ensuite étape dans l'une des images pour voir ce qui se passait lorsque l'alerte a été levée.

Pour réinitialiser les options ci-dessus à leur valeur par défaut, entrez

options(error = NULL, warn = 0)

Comme pour l'avertissement spécifique que vous citez, il est très probable que vous avez besoin pour permettre à plus d'itérations dans le code. Une fois que vous avez trouvé ce qu'est l'appel de glm.fit, travailler sur la façon de passer à l' control argument en utilisant glm.control - voir ?glm.control.

19voto

Joshua Ulrich Points 68776

Ma stratégie générale ressemble à:

  1. Exécutez traceback() voir regarder pour d'évidentes questions
  2. Ensemble options(warn=2) pour traiter les avertissements comme des erreurs
  3. Ensemble options(error=recover) à l'étape dans la pile d'appel en cas d'erreur

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X