functions - sapply en r studio
DepuraciĆ³n de llamadas lapply/sapply (7)
El código escrito con lapply y amigos suele ser más fácil para los ojos y más Rish que los bucles. Me encanta el lapping tanto como el siguiente tipo, pero ¿cómo lo depuro cuando las cosas van mal? Por ejemplo:
> ## a list composed of numeric elements
> x <- as.list(-2:2)
> ## turn one of the elements into characters
> x[[2]] <- "what?!?"
>
> ## using sapply
> sapply(x, function(x) 1/x)
Error in 1/x : non-numeric argument to binary operator
Si hubiera usado un bucle for:
> y <- rep(NA, length(x))
> for (i in 1:length(x)) {
+ y[i] <- 1/x[[i]]
+ }
Error in 1/x[[i]] : non-numeric argument to binary operator
Pero yo sabría donde ocurrió el error:
> i
[1] 2
¿Qué debo hacer cuando uso lapply / sapply?
Como dijo Geoffjentry:
> sapply(x, function(x) {
res <- tryCatch(1 / x,
error=function(e) {
cat("Failed on x = ", x, "/n", sep="") ## browser()
stop(e)
})
})
Además, su bucle for podría reescribirse para ser mucho más limpio (posiblemente un poco más lento):
> y <- NULL
> for (xi in x)
y <- c(y, 1 / xi)
Error in 1/xi : non-numeric argument to binary operator
Los bucles son lentos en R, pero a menos que realmente necesite la velocidad, iría con un enfoque iterativo simple sobre una comprensión confusa de la lista.
Si necesito averiguar algún código sobre la marcha, siempre iré:
sapply(x, function(x) {
browser()
...
})
Y escribe el código desde dentro de la función para que vea lo que estoy obteniendo.
- Dan
He enfrentado el mismo problema y he tendido a hacer que mis llamadas con (l) (m) (s) (t) se apliquen para ser funciones que puedo depurar ().
Entonces, en lugar de blah <-sapply (x, function (x) {x + 1})
Yo diría que,
myfn<-function(x){x+1}
blah<-sapply(x,function(x){myfn(x)})
y usar debug (myfn) con opciones (error = recuperar).
También me gustan los consejos sobre cómo pegar las líneas de impresión () aquí y allá para ver qué está sucediendo.
Aún mejor es diseñar una prueba de myfn (x) que tenga que pasar y asegurarse de que pasa dicha prueba antes de someterla a solicitud. Solo tengo paciencia para esto alrededor de la mitad del tiempo.
Puede depurar () la función, o poner un navegador () dentro del cuerpo. Esto solo es particularmente útil si no tienes unas iteraciones de gajillion para trabajar.
Además, no he hecho esto personalmente, pero sospecho que podría colocar un browser () como parte de tryCatch (), de modo que cuando se genere el error, pueda usar la interfaz del browser ().
Si envuelve su función interna con una declaración try (), obtendrá más información:
> sapply(x, function(x) try(1/x))
Error in 1/x : non-numeric argument to binary operator
[1] "-0.5"
[2] "Error in 1/x : non-numeric argument to binary operator/n"
[3] "Inf"
[4] "1"
[5] "0.5"
En este caso, puede ver qué índice falla.
Usar depuración o navegador no es una buena idea en este caso, porque detendrá su código con tanta frecuencia. En su lugar, use Try o TryCatch, y trate la situación cuando surja.
Utilice el paquete plyr, con .inform = TRUE
:
library(plyr)
laply(x, function(x) 1/x, .inform = TRUE)
Utilice las técnicas de depuración estándar de R para detener exactamente cuando se produce el error:
options(error = browser)
o
options(error = recover)
Cuando haya terminado, vuelva al comportamiento estándar:
options(error = NULL)