Maestría en Hidrología
Universidad de Cuenca
http://www.ucuenca.edu.ec/maestria-ecohidrologia/
Johanna Orellana-Alvear (MSc)
johanna.orellana@ucuenca.edu.ec
Curso completo en: http://rpubs.com/Johanna_Orellana_Alvear/MHidro_indice_2018
En esta lección aprenderás a:
- Utilizar el debug de Rstudio
- Insertar breakpoints e inspeccionarlos
- El uso de funciones apply para subconjuntos de datos
- El uso de la funcion aggregate
A- Debug
B- Aplicación de funciones en conjuntos
“Finding your bug is a process of confirming the many things that you believe are true — until you find one which is not true.” —Norm Matloff
Durante la ejecución de un programa es posible que existan tres tipos de alertas por parte de R.
Errores fatales que se derivan de la ejecución de stop() y obligan a R a terminar el programa.
Warnings o alertas que son generadas por warning() y son usados para despelagar potenciales problemas.Por ejemplo cuando los valores de un vector de entrada a una función son inválidos,como log(-1:2).
Mensajes que son generados por message() y son usados con un fin informativos.
El proceso de depuración en tres simples pasos:
Debug console
Debug traceback
Debug environment
Debug highligh
Nota: Normalemente en depuración se usa la estrategia de “Divide y vencerás”, es decir una búsqueda binaria. En ocasiones no se conoce donde está el error del código y en estos casos hacer una búsqueda exhaustiva del problema puede ser muy demorado. Por lo tanto, lo mejor es dividir el código en dos repetidamente hasta que se encuentre el problema. De esta manera se reduce radicalmente la cantidad de código fuente sobre la que se tiene que inspeccionar.
Para trabajar con el tema de hoy crearemos una función llamada potencias y guardaremos el código fuente en el script debug_example.R.
potencias <- function (unVector){
resultado <- c()
cont <- 0
for (i in unVector){
cont <- cont + 1
resultado[cont] <- i * (i^cont)
}
return(resultado)
}
sourcesource("debug_example.R")
debugonce(nombreFuncion)debugonce(potencias)
Hacer la llamada a la función con los argumentos.
Debug console
Una vez que se ha terminado la ejecución del debug, la función regresa a su forma normal de ejecución. Por ejemplo, al ejecutar la línea siguiente vemos que el resultado de la función se visualiza inmediatamente.
potencias(c(1,3,5,7,9))
## [1] "salida del bucle"
## [1] "segundo breakpoint"
## [1] 1 27 625 16807 531441
Ahora probemos utilizando el comando debug()
debug(potencias)
Al terminar la ejecución y hacer la llamada nuevamente a potencias(c(1,3,5,7,9)) vemos que la función se ejecuta nuevamente en modo “depuración”. Para correr nuevamente cualquier función o script es necesario salir del modo de depuración utilizando el comando undebug. En general se recomienda utilizar el comando debugonce
undebug(potencias)
El ejemplo ilustrado es muy corto y podemos correrlo paso a paso. Sin embargo, ¿Qué pasaría si el el vector tuviera 100 elementos o más?, o si el script tuviera dos bucles diferentes y estamos seguros de que el problema se encuentra en el segundo. Pues bien, la solución sería indicarle a R donde queremos que empiece la depuración (es decir que ejecute rápidamente las líneas que no son de interés).
Para ello, se señala a través de “breakpoints” (puntos rojos) donde se desea que R haga una pausa en la ejecución. Basta con colocarse en la línea deseada y hacer click al borde izquierdo de la numeración. Para desactivar el breakpoint haga click en el mismo lugar.
Debug breakpoint
Ahora, cuando entramos en modo depuración nuevamente el programa y presionamos el botón Continue,
Debug opciones
R ejecuta rápidamente las líneas previas al breakpoint y hace una pausa en este punto esperando una nueva indicación.
Debug breakpoint
Para terminar el modo de depuración, cortar la ejecución del proceso abruptamente puede hacer uso del botón stop o la letra Q. Nótese que los breakpoints se almacenan el momento de la llamada source. Además en caso de que el código mantenga breakpoints entrará automáticamente en modo de depuración. Si desea correr normalmente su programa debe asegurarse de borrar todos los breakpoints.
Existen mecanimos más eficientes de ejecutar ciertas funciones sobre fragmentos de una estructura (vector, matriz, data frame, etc) que a través de los bucles. De cierta manera estas funciones mismas incorporan una lógica de bucle de repetición. Es conveniente empezar respondiendo estas preguntas para identificar si la solución que se desea implementar se aplica a estos casos.
Existe una familia de comandos que permite aplicar funciones a varios elementos (subconjuntos de datos) de una estructura o clase simulando un proceso repetitivo más eficiente. Estos comandos son: apply, lapply , sapply, vapply, mapply, rapply, and tapply. En esta sesión ilustratemos algunos ejemplos de ellos y los que no se abordan aquí, se sugieren como revisión al lector.
La sintaxis que se describe a continuación se aplica a todas las funciones de la familia apply.
apply(X, MARGIN, FUN, ...)
donde:
X es un array o matriz;
MARGIN es una variable que determina si la función se aplica sobre filas (MARGIN=1), columnas (MARGIN=2), or ambas (MARGIN=c(1,2));
FUN es la función a ser aplicada.
m<-matrix(c(seq(from=-98,to=100,by=2)),nrow=10,ncol=10)
apply(m,1,prod)
## [1] -2.849130e+15 -5.344148e+15 -7.282577e+15 -8.510121e+15 -8.930250e+15
## [6] -8.510121e+15 -7.282577e+15 -5.344148e+15 -2.849130e+15 0.000000e+00
apply(m,2,sum)
## [1] -890 -690 -490 -290 -90 110 310 510 710 910
apply(m,c(1,2),function(x) x%%10)
## [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
## [1,] 2 2 2 2 2 2 2 2 2 2
## [2,] 4 4 4 4 4 4 4 4 4 4
## [3,] 6 6 6 6 6 6 6 6 6 6
## [4,] 8 8 8 8 8 8 8 8 8 8
## [5,] 0 0 0 0 0 0 0 0 0 0
## [6,] 2 2 2 2 2 2 2 2 2 2
## [7,] 4 4 4 4 4 4 4 4 4 4
## [8,] 6 6 6 6 6 6 6 6 6 6
## [9,] 8 8 8 8 8 8 8 8 8 8
## [10,] 0 0 0 0 0 0 0 0 0 0
Descripción: lapply retorna una lista de la misma longitud de X, donde cada elemento corresponde al resultado de aplicar FUN a su respectivo elemento de X.
A<-matrix(1:9, 3,3)
B<-matrix(4:15, 4,3)
C<-matrix(8:10, 3,2)
MyList<-list(A,B,C) # display the list
Para aplicar este ejemplo se usa el operador de selección “[”.
lapply(MyList,"[", , 2)
## [[1]]
## [1] 4 5 6
##
## [[2]]
## [1] 8 9 10 11
##
## [[3]]
## [1] 8 9 10
Descripción: sapply es una versión amigable de lapply que por defecto retorna un vector o matriz según el caso. Nótese que el primero devuelve una lista, y el segundo un vector.
lapply(MyList,"[", 2,1 )
## [[1]]
## [1] 2
##
## [[2]]
## [1] 5
##
## [[3]]
## [1] 9
sapply(MyList,"[", 2,1 )
## [1] 2 5 9
Ahora aplciaremos la función unlist. ¿Qué produce la aplicación de esta función sobre el resultado de lapply?
unlist(lapply(MyList,"[", 2,1 ))
## [1] 2 5 9
Esta función, a pesar de no pertenecer a la familia apply, mantiene una lógica similar de aplicación de una función a un subconjunto de datos. ¿Cuál es el objetivo y el resultado final del código, qué clase de objeto produce?
setwd("~/Documents/R_WORKSPACE/Maestria_Hidrologia_2018")
df.observaciones <- read.table("observaciones_2003.csv", header = TRUE, stringsAsFactors = FALSE)
sd_VALOR_monthly <- aggregate(VALOR ~ month, data = df.observaciones, sd)
sd_VALOR_monthly
## month VALOR
## 1 1 4.793814
## 2 2 7.401479
## 3 3 10.284249
## 4 4 8.289255
## 5 5 6.885316
## 6 6 4.416878
## 7 7 3.150891
## 8 8 2.220939
## 9 9 2.862725
## 10 10 3.130080
## 11 11 4.156379
## 12 12 6.350809