how to figure out which statement in lapply fails in R - r

I often have the situation like this:
result <- lapply(1:length(mylist), function(x){
doSomething(x)
})
However, if it fails, I have no idea which element in the list failed on doSomething().
So then I end up recoding it as a for loop:
for(i in 1: length(mylist)){
doSomething(mylist[[i]])
}
I can then see the last value of i and what happened. There must be a better way to do this right?? Thanks!

Notice how the error includes 5L
> lapply(1:10, function(i) if (i == 5) stop("oops"))
Error in FUN(1:10[[5L]], ...) : oops
indicating that the 5th iteration failed.

One simple option is to run the code:
options( error=recover )
before running lapply (see ?recover for details).
Then when/if an error occurs you will instantly be put into the recover mode that will let you examine which function you are in, what arguments were passed to that function, etc. so you can see which step you are on and what the possible reason for the error is.
You can also use try or tryCatch as mentioned in the comments to either skip elements that produce an error or print out information on where they occur.

Related

For loop vs Sapply in terms of fault step in R

I am facing with a problem when analysing errors in sapply in R.
Suppose I have a matrix as below,
B <- matrix( 
  c(2, 4, 3, 1, 5, 7), 
  nrow=3, 
  ncol=2)
Just to create some errors, I'am indexing out of the bounds of the matrix. (i in 1:5 part)
for (i in 1:5) {
x <- B[1,i]^2
if(i==1) {
result <- x
}else{
result <- rbind(result,x)
}
}
Of course it gives an error like this.
Error in B[1, i] : subscript out of bounds
However, it is not so hard to find at what step it gives an error.Since, if I call i;
> i
[1] 3
I can easily understand at what step I have faced with the error.In this case it is happening when i=3.
However, to take advantage of the speed of the sapply function in R (since the loops are not recommended because of the lack of speed) I used it as below;
sapply(1:5 ,function(j) {
y <- B[1,j]^2
})
Not surprisingly it gives the same error.
Error in B[1, j] : subscript out of bounds
However, now I cannot see at what step I failed. Since neither j nor y is recorded!
> j
Error: object 'j' not found
> y
Error: object 'y' not found
What Can you suggest about that? I know it is a simple example. But the things I am dealing with in reality are more complex and it becomes harder to find the error step.
Thanks in advance!
If you use RStudio, the easiest way is to activate in the Menu: Debug > On Error > Break in code.
This will open a browser on error and you will be able to see the value of j.
If you don't use RStudio, you can set options(error = recover) which will also open a browser on error. (In your specific case choose frame 3 and you will be able to see the value of j)

R: Creating a custom error message giving argument values for a function in a package

Suppose there is a set of functions, drawn from a package not written by me, that I want to assign to a special behavior on error. My current concern is with the _impl family of functions in dplyr. Take mutate_impl, for example. When I get an error from mutate, traceback almost always leads me to mutate_impl, but it is usually a ways up the call stack -- I have seen it be as many as 15 calls from the call to mutate. So what I want to know at that point is typically how the arguments to mutate_impl relate to the arguments I originally supplied to mutate (or think I did).
So, this code is probably wrong in too many ways to count -- certainly it does not work -- but I hope it at least helps to express my intent. The idea is that I could wrap it around mutate_impl, and if it produces an error, it saves the error message and a description of the arguments and returns them as a list
str_impl <- function(f){tryCatch(f, error = function(c) {
msg <- conditionMessage(c)
args <- capture.output(str(as.list(match.call(call(f)))))
list(message = msg, arguments = args)
}
assign(str_impl(mutate_impl), .GlobalEnv)
Although, this still falls short of what I really want, because even without the constraint of working code, I could not figure out how to produce a draft. What I really want is to be able to identify a function or list of functions that I want to have this behavior on error, and then have it occur on error whenever and wherever that function is called. I could not think of any way to even start to do that without rewriting functions in the dplyr package environment, which struck me as a really bad idea.
The final assignment to the global environment is supposed to get the error object back to somewhere I can find it, even if the call to mutate_impl happens somewhere inaccessible, like in an environment that ceases to exist after the error.
Probably the best way of achieving what you want is via the trace functionality. It's surely worth reading the help about trace, but here is a working example:
library(dplyr)
trace("mutate_impl", exit = quote({
if (class(returnValue())[1]=="NULL") {
cat("df\n")
print(head(df))
cat("\n\ndots\n")
print(dots)
} else {
# no problem, nothing to do
}
}), where = mutate, print = FALSE)
# ok
xx <- mtcars %>% mutate(gear = gear * 2)
# not ok, extra output
xx <- mtcars %>% mutate(gear = hi * 2)
It should be fairly simple to adjust this to your specific needs, e.g. if you want to log to a file instead:
trace("mutate_impl", exit = quote({
if (class(returnValue())[1]=="NULL") {
sink("error.log")
cat("df\n")
print(head(df))
cat("\n\ndots\n")
print(dots)
sink()
} else {
# no problem, nothing to do
}
}), where = mutate, print = FALSE)

R - Rstudio - make R play a sound if warning/error generated

I am running a script that loops over a list of stock pair combinations... occasionally the script stops running due to an error generated by differing data lengths between pair combo and I simply remove the mismatched stock from consideration):
Error in model.frame.default(formula = stckY ~ stckX + 0, drop.unused.levels = TRUE) :
variable lengths differ (found for 'stckX')
Is there any way I can make R / Rstudio play a sound when the error message occurs so that I can be alerted without having to keep my eyes on the screen while the script is looping along?
I can generate sounds linearly using:
beep <- function(n = 3){
for(i in seq(n)){
system("rundll32 user32.dll,MessageBeep -1")
Sys.sleep(.5)
}
}
beep()
but how can I do this conditional on an error message?
Building on #frankc answer and #hrbrmstr comment, a way to do this:
install.packages("beepr")
library(beepr)
options(error = beep)
try options(error = beep)
you would still need to define beep before you do this. Haven't verified this works but it should per ?options:
'error': either a function or an expression governing the handling
of non-catastrophic errors such as those generated by 'stop'
as well as by signals and internally detected errors. If the
option is a function, a call to that function, with no
arguments, is generated as the expression. The default value
is 'NULL': see 'stop' for the behaviour in that case. The
functions 'dump.frames' and 'recover' provide alternatives
that allow post-mortem debugging. Note that these need to
specified as e.g. 'options(error = utils::recover)' in
startup files such as '.Rprofile'.

If (something got printed) x=false, how to do this in R?

So I am using a function in R that uses compiled fortran code. While using this function, lsoda, in package deSolve. I get messages printed to the screen like
DLSODA- At current T (=R1), MXSTEP (=I1) steps
taken on this call before reaching TOUT
In above message, I =
[1] 5000
In above message, R =
[1] 21.31629
The problem is that the above is not a "warning" or an "error"; the is.null(warnings()) evaluates to TRUE after I see this message. If it were a warning I could just write x = is.null(warnings()) and that would do the trick. I could use tryCatch for errors, but what about messages that are neither errors or warnings?
The reason I ask, is that this function is called in a while loop, inside a for loop. I want the while loop to break if this message gets printed, and then for the outer for loop to move onto the next iteration. Normally you'd use tryCatch to do something like this but because there is no error, I have no idea how to do this
You can redirect the output and then check whether lsoda printed something:
out <- capture.output(lsoda(...))
if(length(grep("In above message", out))!=0) {
# error
}
We basically check whether any of the lines printed by lsoda contains the string In above message. If you need to use the result from lsoda, you can also run like this:
out <- capture.output(result <- lsoda(...))
As suggested, you can also use grepl:
if(any(grepl("In above message", out))) {
# error
}

tryCatch does not catch an error if called though RScript

I'm facing a strange issue in R.
Consider the following code (a really simplified version of the real code but still having the problem) :
library(timeSeries)
tryCatch(
{
specificWeekDay <- 2
currTs <- timeSeries(c(1,2),c('2012-01-01','2012-01-02'),
format='%Y-%m-%d',units='A')
# just 2 dates out of range
start <- time(currTs)[2]+100*24*3600
end <- time(currTs)[2]+110*24*3600
# this line returns an empty timeSeries
currTs <- window(currTs,start=start,end=end)
message("Up to now, everything is OK")
# this is the line with the uncatchable error
currTs[!(as.POSIXlt(time(currTs))$wday %in% specificWeekDay),] <- NA
message("I'm after the bugged line !")
},error=function(e){message(e)})
message("End")
When I run that code in RGui, I correctly get the following output:
Up to now, everything is OK
error in evaluating the argument 'i' in
selecting a method for function '[<-': Error in
as.POSIXlt.numeric(time(currTs)) : 'origin' must be supplied
End
Instead, when I run it through RScript (in windows) using the following line:
RScript.exe --vanilla "myscript.R"
I get this output:
Up to now, everything is OK
Execution interrupted
It seems like RScript crashes...
Any idea about the reason?
Is this a timeSeries package bug, or I'm doing something wrong ?
If the latter, what's the right way to be sure to catch all the errors ?
Thanks in advance.
EDIT :
Here's a smaller example reproducing the issue that doesn't use timeSeries package. To test it, just run it as described above:
library(methods)
# define a generic function
setGeneric("foo",
function(x, ...){standardGeneric("foo")})
# set a method for the generic function
setMethod("foo", signature("character"),
function(x) {x})
tryCatch(
{
foo("abc")
foo(notExisting)
},error=function(e)print(e))
It seems something related to generic method dispatching; when an argument of a method causes an error, the dispatcher cannot find the signature of the method and conseguently raises an exception that tryCatch function seems unable to handle when run through RScript.
Strangely, it doesn't happen for example with print(notExisting); in that case the exception is correctly handled.
Any idea about the reason and how to catch this kind of errors ?
Note:
I'm using R-2.14.2 on Windows 7
The issue is in the way the internal C code implementing S4 method dispatch tries to catch and handle some errors and how the non-interactive case is treated in this approach. A work-around should be in place in R-devel and R-patched soon.
Work-around now committed to R-devel and R-patched.
Information about tryCatch() [that the OP already knew and used but I didn't notice]
I think you are missing that your tryCatch() is not doing anything special with the error, hence you are raising an error in the normal fashion. In interactive use the error is thrown and handled in the usual fashion, but an error inside a script run in a non-interactive session (a la Rscript) will abort the running script.
tryCatch() is a complex function that allows the potential to trap and handle all sorts of events in R, not just errors. However by default it is set up to mimic the standard R error handling procedure; basically allow the error to be thrown and reported by R. If you want R to do anything other than the basic behaviour then you need to add a specific handler for the error:
> e <- simpleError("test error")
> tryCatch(foo, error = function(e) e,
+ finally = writeLines("There was a problem!"))
There was a problem!
<simpleError in doTryCatch(return(expr), name, parentenv, handler): object 'foo'
not found>
I suggest you read ?tryCatch in more detail to understand better what it does.
An alternative is to use try(). To modify your script I would just do:
# this is the line with the uncatchable error
tried <- try(currTs[!(as.POSIXlt(time(currTs))$wday %in% specificWeekDay),] <- NA,
silent = TRUE)
if(inherits(tried, "try-error")) {
writeLines("There was an error!")
} else {
writeLines("Everything worked fine!")
}
The key bit is to save the object returned from try() so you can test the class, and to have try() operate silently. Consider the difference:
> bar <- try(foo)
Error in try(foo) : object 'foo' not found
> bar <- try(foo, silent = TRUE)
> class(bar)
[1] "try-error"
Note that in the first call above, the error is caught and reported as a message. In the second, it is not reported. In both cases an object of class "try-error" is returned.
Internally, try() is written as a single call to tryCatch() which sets up a custom function for the error handler which reports the error as a message and sets up the returned object. You might wish to study the R code for try() as another example of using tryCatch().

Resources