r tryCatch how to pass object to error function - r

myFunc <- function(x)
{
x <- timeSeries(x, charvec=as.Date(index(x)))
t<-tryCatch( doSomething(x), error=function(x) rep(0,ncol(x))
)
t
}
How do I pass x into the error function? When I run the above I get:
Error in rep(0, ncol(x)) : invalid 'times' argument

The error argument is a handler, documented (see ?tryCatch) to accept one argument (the error condition). The error handler has access to whatever variables were available at the time stop was invoked. So
f = function() {
tryCatch({
i = 1
stop("oops")
}, error=function(e) {
stop(conditionMessage(e), " when 'i' was ", i)
})
}
catches the error thrown by the code, discovers the value i, and emits a more informative message. So I'd guess
myFunc <- function(x)
{
tryCatch({
x <- timeSeries(x, charvec=as.Date(index(x)))
doSomething(x)
}, error=function(...) rep(0, ncol(x)))
}

Related

conbining two functions in r (using tryCatch)

I want to make a new function that has 3 skills
if an error occurs, print "error". Do not stop the whole process, make it keep going
if a warning occurs, print the warning message
if there is no error nor warning, print "Nothing".
For 1) I made a function as follows:
efunc <- function(error){
return(NA)
}
tryc <- function(x){tryCatch(x, error = efunc)}
for 2), 3) , I refer to this page( How do I save warnings and errors as output from a function?) and
adapted some code, making the following functions
myTryCatch <- function(expr) {
warn <- err <- NULL
value <- withCallingHandlers(
tryCatch(expr, error=function(e) {
err <<- e # <<- is not typo
print("error")
}), warning=function(w) {
warn <<- w # <<- is not typo
invokeRestart("muffleWarning")
})
if(is.null(warn)){
warn<-'Nothing'
}
if(is.null(err)){
err<-'Nothing'
}
warning=warn
paste(unlist(warning),collapse="")
}
However, thinking back, maybe it is possible to combine these two functions..
or, myTryCatch() already has a tryc()'s skill..
but I am not sure.

If observe warning, skip iteration in for loop [R]

I have some loop that computes a value. Sometimes that computation triggers a warning. How do I check if the warning is triggered, then skip that iteration? I am using R.
With help from the comments, I found tryCatch() and was able to amend my for loop as the following and work:
for (i in seq(1,100,1)){
x<-sample(1:length(df$values), 1)
input<-copy_df[x:x+5,]
val<-tryCatch(myfunc(input$colA), warning=function(w) w)
if (is(val,warning){
next
}
print(paste0(i))
}
The output of val should be a column of length 5.
Here's a complete example using a test function that randomly generates a warning
set.seed(101)
foo <- function() {
x <- runif(1)
if(x<.9) warning("low x")
x
}
for(i in 1:20) {
didwarn <- tryCatch({x <- foo(); FALSE}, warning = function(w) return(TRUE))
if(didwarn) {
next
}
print(paste("high x", x))
}
You wrap any code that might trigger a warning in a try catch. Here we have each block return TRUE or FALSE depending on whether or not an error was thrown. An easier way to do this without the next would be
for(i in 1:20) {
tryCatch({
x <- foo();
print(paste("high x", x))
},
warning = function(w) {
# do nothing
})
}
When the warning occurs, nothing else in the tryCatch expression will run

How to catch warning and still run the expression

I want to catch a warning and still run an expression.
Here is an example:
x <- 0
tryCatch({
x <- as.numeric("text") # this is NA and causes warning
}, warning = function(w) {
print("I am a message")
})
x
# x still 0
Previous code catches the warning and print the message, BUT the value of x is not NA afterwards, which means that the expression did not run because of the warning.
I could run the expression with suppressWarnings() and <<- as follows:
x <- 0
tryCatch({
x <- as.numeric("text")
}, warning = function(w) {
print("I am a message")
suppressWarnings(x <<- as.numeric("text"))
})
x
# now x is NA
Is there a more elegant way to do that? maybe one of following examples?
another function other than tryCatch()
or using some parameter of tryCatch()
or maybe another package other than base
...
From this answer follows that this code could work:
x <- 0
withCallingHandlers({
x <- as.numeric("text")
}, warning = function(w) {
print("I am a message")
invokeRestart("muffleWarning")
})
x
(I came across this post looking for a way to catch a warning and alter the return value of a function. I ended up with
which_nondefault_enc <- function(txt) {
ans <- rep(NA, length(txt))
for (i in seq(1, length(txt)))
ans[i] <- tryCatch(stringi::stri_enc_tonative(txt[i]), warning = function(w) return(NA))
return(which(is.na(ans)))
}
which returns those indices of the vector, where warnings like "unable to translate '<U+0001F41F>' to native encoding" are used as a selection criterion.)

When using doParallel in R, how can I get the line number where an error was thrown?

I am trying to figure out how to pinpoint the line where an error is thrown when using foreach and doParallel. Here's an example:
foreach.example <- function()
{
require("doParallel")
z <- foreach (i = 1:2) %do%
{
x <- i + 'a'
}
return(z)
}
So within the %do% there is a bug where i am adding a character to a numeric. (Everything I say here also applies to %dopar%,). When I run this I get:
> foreach.example()
Error in { (from test_foreach.R#3) : task 1 failed - "non-numeric argument to binary operator"
I can't tell from this where in the loop I had the error line 3 is the foreach line, not the offending line. When I run debugger() I get:
> debugger()
Message: Error in { (from test_foreach.R#3) : task 1 failed - "non-numeric argument to binary operator"
Available environments had calls:
1: foreach.example()
2: test_foreach.R#3: foreach(i = 1:2) %do% {
x <- i + "a"
}
3: e$fun(obj, substitute(ex), parent.frame(), e$data)
4: stop(simpleError(msg, call = expr))
Note that frame 2 will generally indicate the whole loop so I can't find the line where the error was actually thrown.
If instead I run this without the foreach, I get useful information:
regular.example <- function()
{
z <- list()
for (i in 1:2) {
x <- i + 'a'
z <- c(z, list(x))
}
return(z)
}
>regular.example()
Error in i + "a" (from test_foreach.R#12) : non-numeric argument to binary operator
and the debugger takes me to the line in code that threw the exception.
Any ideas on how to identify the line number with the excpetion when using foreach? Thanks.
Try modifying your foreach call to include .verbose = TRUE
z <- foreach (i = 1:2, .verbose = T) %do% ...

R warning message on recursive expression: If you fail, try, try again

I want to create a function that will retry an expression if it fails. Here's my working version:
retry <- function(.FUN, max.attempts=3, sleep.seconds=1) {
x <- NULL
if(max.attempts > 0) {
f <- substitute(.FUN)
x <- try(eval(f))
if(class(x) == "try-error") {
Sys.sleep(sleep.seconds)
return(suppressWarnings(retry(.FUN, max.attempts-1)))
}
}
x
}
retry(stop("I'm here"))
If I remove the suppressWarnings() function above, then I get a set of warnings on each recursive call. Does anyone know what I'm doing wrong that would cause that?
Here's an example that can be run repeatedly:
retry({ tmp <- function() { if(rnorm(1) < 0) stop("I'm here") else "success" }; tmp() })
I'm not sure if I can describe the cause exactly, but I've isolated the problem and can fix it. The basic problem is the recursion: retry(.FUN, max.attempts-1) - when the recursive call calls substitute(.FUN) it's going to have go up a level of the call stack to figure out what the value of .FUN is - it has to restart the evaluation of a promise (the delayed execution of function arguments) a level up.
A fix is to just do the substitution once:
retry <- function(.FUN, max.attempts = 3, sleep.seconds = 0.5) {
expr <- substitute(.FUN)
retry_expr(expr, max.attempts, sleep.seconds)
}
retry_expr <- function(expr, max.attempts = 3, sleep.seconds = 0.5) {
x <- try(eval(expr))
if(inherits(x, "try-error") && max.attempts > 0) {
Sys.sleep(sleep.seconds)
return(retry_expr(expr, max.attempts - 1))
}
x
}
f <- function() {
x <- runif(1)
if (x < 0.5) stop("Error!") else x
}
retry(f())
To create functions that you can use flexibly, I highly recommend minimising the use of substitute. In my experience, you're usually best off having one function that does the substitution, and another that does all the work. This makes it possible to use the function when called from another function:
g1 <- function(fun) {
message("Function starts")
x <- retry(fun)
message("Function ends")
x
}
g1(f())
# Function starts
# Error in eval(expr, envir, enclos) : object 'fun' not found
# Error in eval(expr, envir, enclos) : object 'fun' not found
# Error in eval(expr, envir, enclos) : object 'fun' not found
# Error in eval(expr, envir, enclos) : object 'fun' not found
# Function ends
g2 <- function(fun) {
message("Function starts")
expr <- substitute(fun)
x <- retry_expr(expr)
message("Function ends")
x
}
g2(f())
# Function starts
# Error in f() : Error!
# Function ends
# [1] 0.8079241
Not sure about why you get the warnings... but if use a for loop they disappear.
retry <- function(.FUN, max.attempts=3, sleep.seconds=1)
{
x <- NULL
for (i in 1:max.attempts)
{
f <- substitute(.FUN)
x <- try(eval(f))
if (class(x) == "try-error")
{
Sys.sleep(sleep.seconds)
}
else
{
return (x)
}
}
x
}

Resources