Recibo un error al usar una función R que escribí:
Warning messages:
1: glm.fit: algorithm did not converge
2: glm.fit: algorithm did not converge
Que he hecho:
- Paso a través de la función
- Agregar impresión para averiguar en qué línea se produce el error sugiere dos funciones que no deberían usarse
glm.fit
. Sonwindow()
ysave()
.
Mis enfoques generales incluyen agregar print
y stop
comandos, y recorrer una función línea por línea hasta que pueda localizar la excepción.
Sin embargo, no está claro para mí usar esas técnicas de dónde viene este error en el código. Ni siquiera estoy seguro de qué funciones dependen del código glm.fit
. ¿Cómo hago para diagnosticar este problema?
options(warn = 2)
. Entonces, en este caso, los detalles son esenciales para responder a su pregunta general. +1 de mi parteRespuestas:
Yo diría que la depuración es una forma de arte, por lo que no hay una bala de plata clara. Existen buenas estrategias para depurar en cualquier idioma, y también se aplican aquí (por ejemplo, lea este bonito artículo ). Por ejemplo, lo primero es reproducir el problema ... si no puede hacer eso, entonces necesita obtener más información (por ejemplo, con el registro). Una vez que pueda reproducirlo, debe reducirlo a la fuente.
En lugar de un "truco", diría que tengo una rutina de depuración favorita:
traceback()
: eso muestra dónde ocurrió el error, lo cual es especialmente útil si tiene varias funciones anidadas.options(error=recover)
; esto cambia inmediatamente al modo de navegador donde se produce el error, por lo que puede explorar el espacio de trabajo desde allí.debug()
función y paso por el script línea por línea.El mejor truco nuevo en R 2.10 (cuando se trabaja con archivos de script) es usar las funciones
findLineNum()
ysetBreakpoint()
.Como comentario final: dependiendo del error, también es muy útil establecer
try()
o hacertryCatch()
declaraciones en torno a llamadas a funciones externas (especialmente cuando se trata de clases S4). Eso a veces proporcionará aún más información, y también le da más control sobre cómo se manejan los errores en tiempo de ejecución.Estas preguntas relacionadas tienen muchas sugerencias:
fuente
browser()
para cuando hay errores que no activan advertencias / errores (crédito: Roman Luštrik en esta página). ¿Alguna otra herramienta comobrowser()
?El mejor tutorial que he visto hasta ahora es:
http://www.biostat.jhsph.edu/%7Erpeng/docs/R-debug-tools.pdf
Alguien está de acuerdo / en desacuerdo?
fuente
Como se me señaló en otra pregunta ,
Rprof()
ysummaryRprof()
son buenas herramientas para encontrar partes lentas de su programa que podrían beneficiarse de acelerar o pasar a una implementación de C / C ++. Esto probablemente se aplica más si está haciendo un trabajo de simulación u otras actividades intensivas en cómputo o datos. Elprofr
paquete puede ayudar a visualizar los resultados.Estoy en una patada para aprender a depurar, así que otra sugerencia de otro hilo :
options(warn=2)
para tratar las advertencias como erroresTambién puede usarlo
options
para dejarlo caer en el calor de la acción cuando ocurre un error o advertencia, utilizando su función de depuración favorita. Por ejemplo:options(error=recover)
para ejecutarserecover()
cuando ocurre un error, como lo observó Shane (y como está documentado en la guía de depuración de R.) O cualquier otra función útil que le resulte útil ejecutar.Y otros dos métodos de uno de los enlaces de @ Shane :
try()
para devolver más información sobre ella..inform=TRUE
(del paquete plyr) como una opción para el comando apply@JoshuaUlrich también señaló una forma ordenada de usar las habilidades condicionales del
browser()
comando clásico para activar / desactivar la depuración:browser(expr=isTRUE(getOption("myDebug")))
options(myDebug=TRUE)
myBrowse <- browser(expr=isTRUE(getOption("myDebug")))
y luego llamar con,myBrowse()
ya que usa globals.Luego están las nuevas funciones disponibles en R 2.10:
findLineNum()
toma un nombre de archivo de origen y un número de línea y devuelve la función y el entorno. Esto parece ser útil cuandosource()
utiliza un archivo .R y devuelve un error en la línea #n, pero necesita saber qué función se encuentra en la línea #n.setBreakpoint()
toma un nombre de archivo de origen y un número de línea y establece un punto de interrupción allíEl paquete codetools , y en particular su
checkUsage
función, puede ser particularmente útil para detectar rápidamente la sintaxis y los errores estilísticos que un compilador generalmente informaría (locales no utilizados, funciones y variables globales no definidas, coincidencia parcial de argumentos, etc.).setBreakpoint()
es un front-end más fácil de usar paratrace()
. Los detalles sobre los aspectos internos de cómo funciona esto están disponibles en un artículo reciente de R Journal .Si está intentando depurar el paquete de otra persona, una vez que haya localizado el problema, puede sobrescribir sus funciones con
fixInNamespace
yassignInNamespace
, pero no lo use en el código de producción.Nada de esto debería impedir las herramientas de depuración R estándar probadas y verdaderas , algunas de las cuales están arriba y otras no. En particular, las herramientas de depuración post-mortem son útiles cuando tiene un montón de código que consume mucho tiempo y que prefiere no volver a ejecutar.
Finalmente, para problemas difíciles que no parecen arrojar un mensaje de error, puede usar
options(error=dump.frames)
como se detalla en esta pregunta: Error sin arrojar un errorfuente
En algún momento,
glm.fit
se está llamando. Eso significa que una de las funciones que llamas o una de las funciones llamadas por esas funciones están usando o bienglm
,glm.fit
.Además, como mencioné en mi comentario anterior, es una advertencia, no un error , lo que hace una gran diferencia. No puede activar ninguna de las herramientas de depuración de R desde una advertencia (con opciones predeterminadas antes de que alguien me diga que estoy equivocado ;-).
Si cambiamos las opciones para convertir las advertencias en errores, entonces podemos comenzar a usar las herramientas de depuración de R. De
?options
tenemos:Entonces si corres
luego ejecute su código, R arrojará un error. En ese punto, podrías correr
para ver la pila de llamadas. Aquí hay un ejemplo.
Aquí puede ignorar los marcos marcados
4:
y superiores. Vemos quefoo
llamóbar
y quebar
generó la advertencia. Eso debería mostrarte qué funciones estaban llamandoglm.fit
.Si ahora desea depurar esto, podemos recurrir a otra opción para decirle a R que ingrese al depurador cuando encuentre un error, y como hemos cometido errores de advertencia, obtendremos un depurador cuando se active la advertencia original. Para eso debes ejecutar:
Aquí hay un ejemplo:
Luego puede ingresar a cualquiera de esos marcos para ver qué estaba sucediendo cuando se lanzó la advertencia.
Para restablecer las opciones anteriores a sus valores predeterminados, ingrese
En cuanto a la advertencia específica que cita, es muy probable que necesite permitir más iteraciones en el código. Una vez que hayas descubierto lo que está llamando
glm.fit
, averigua cómo pasar elcontrol
argumento usandoglm.control
- mira?glm.control
.fuente
Por lo tanto
browser()
,traceback()
ydebug()
entrar en un bar, perotrace()
espera afuera y mantiene el motor en marcha.Al insertar
browser
en algún lugar de su función, la ejecución se detendrá y esperará su entrada. Puede avanzar usando n(o Enter), ejecutar el fragmento completo (iteración) con c, finalizar el bucle / función actual con f, o salir con Q; ver?browser
.Con
debug
, obtienes el mismo efecto que con el navegador, pero esto detiene la ejecución de una función al principio. Se aplican los mismos atajos. Esta función estará en modo "depuración" hasta que la desactive usandoundebug
(es decir, después dedebug(foo)
ejecutar la funciónfoo
entrará en modo "depuración" cada vez hasta que la ejecuteundebug(foo)
).Una alternativa más transitoria es
debugonce
, que eliminará el modo "depuración" de la función después de la próxima vez que se evalúe.traceback
le dará el flujo de ejecución de funciones hasta donde algo salió mal (un error real).Puede insertar bits de código (es decir, funciones personalizadas) en funciones utilizando
trace
, por ejemplobrowser
. Esto es útil para funciones de paquetes y eres demasiado vago para obtener el código fuente bien plegado.fuente
Mi estrategia general se ve así:
traceback()
para ver buscar problemas obviosoptions(warn=2)
para tratar las advertencias como erroresoptions(error=recover)
para entrar en la pila de llamadas por errorfuente
Después de pasar por todos los pasos sugeridos aquí me acabo de enterar que el establecimiento
.verbose = TRUE
enforeach()
también me da un montón de información útil. En particular,foreach(.verbose=TRUE)
muestra exactamente dónde ocurre un error dentro del bucle foreach, mientrastraceback()
que no mira dentro del bucle foreach.fuente
El depurador de Mark Bravington que está disponible como paquete
debug
en CRAN es muy bueno y bastante sencillo.El código aparece en una ventana Tk resaltada para que pueda ver lo que está sucediendo y, por supuesto, puede llamar a otro
mtrace()
mientras está en una función diferente.HTH
fuente
Me gusta la respuesta de Gavin: no sabía acerca de las opciones (error = recuperar). También me gusta usar el paquete 'debug' que brinda una forma visual de recorrer su código.
En este punto, se abre una ventana de depuración separada que muestra su función, con una línea amarilla que muestra dónde se encuentra en el código. En la ventana principal, el código ingresa al modo de depuración, y puede seguir presionando Intro para avanzar por el código (y también hay otros comandos), y examinar valores variables, etc. La línea amarilla en la ventana de depuración sigue moviéndose para mostrar dónde Estás en el código. Cuando haya terminado con la depuración, puede desactivar el seguimiento con:
fuente
Según la respuesta que recibí aquí , definitivamente deberías revisar la
options(error=recover)
configuración. Cuando esto está configurado, al encontrar un error, verá un texto en la consola similar al siguiente (traceback
salida):En ese momento puede elegir qué "marco" para ingresar. Cuando realice una selección, se le pondrá en
browser()
modo:Y puede examinar el entorno tal como estaba en el momento del error. Cuando haya terminado, escriba
c
para volver al menú de selección de cuadros. Cuando haya terminado, como le indica, escriba0
para salir.fuente
Di esta respuesta a una pregunta más reciente, pero la agrego aquí para completarla.
Personalmente, tiendo a no utilizar funciones para depurar. A menudo encuentro que esto causa tantos problemas como resuelve. Además, viniendo de un fondo de Matlab, me gusta poder hacer esto en un entorno de desarrollo integrado (IDE) en lugar de hacerlo en el código. Usar un IDE mantiene su código limpio y simple.
Para R, utilizo un IDE llamado "RStudio" ( http://www.rstudio.com ), que está disponible para Windows, Mac y Linux y es bastante fácil de usar.
Las versiones de Rstudio desde aproximadamente octubre de 2013 (0.98ish?) Tienen la capacidad de agregar puntos de interrupción en scripts y funciones: para hacer esto, simplemente haga clic en el margen izquierdo del archivo para agregar un punto de interrupción. Puede establecer un punto de interrupción y luego avanzar a partir de ese punto. También tiene acceso a todos los datos en ese entorno, por lo que puede probar comandos.
Consulte http://www.rstudio.com/ide/docs/debugging/overview para más detalles. Si ya tiene instalado Rstudio, es posible que deba actualizar; esta es una característica relativamente nueva (finales de 2013).
También puede encontrar otros IDE que tengan una funcionalidad similar.
Es cierto que si se trata de una función incorporada, es posible que tenga que recurrir a algunas de las sugerencias hechas por otras personas en esta discusión. Pero, si es su propio código el que necesita ser reparado, una solución basada en IDE podría ser justo lo que necesita.
fuente
Para depurar métodos de clase de referencia sin referencia de instancia
fuente
Estoy empezando a pensar que no imprimir el número de línea de error, un requisito más básico, POR DEFECTO, es una especie de broma en R / Rstudio . El único método confiable que he encontrado para encontrar dónde se produjo un error es hacer el esfuerzo adicional de inmovilizar traceback () y ver la línea superior.
fuente