Λεωνίδας Μπαντής
2012-May-26 13:14 UTC
[R] avoid error within for loop, try, trycatch, while, move to next iteration, unlist
Hi there,
I would like to ask something about how to avoid a possible error message within
a for loop. I am running a simulation and in some repetitions there may be an
error that will cause a crash and stop the whole procedure, what I want is to
simply move on to the next iteration automatically and discard the
"bad" repetitions from my results. I used the "try" function
to do this and it partially works.
Here is the thing:
logitsboots <- function(x,y,Jbh) {
logitseb=0;logitspb=0;
for (j in 1:1) {
#some code here that has to do with random numbers that may or may not produce
an error and calculates the values of two scalar quantities: spboots and
seboots,
logitspb=log(spboots/(1-spboots))
logitseb=log(seboots/(1-seboots))
#assume that I only care about logitseb for the moment
}
list(lse=logitseb)
}
# Now the following works just fine:
res=0
for(bb in 1:100) {
res[bb] <- try(logitsboots(x,y,Jbh), TRUE)
}
az=unlist(res[sapply(res, function(x) !inherits(x, "try-error"))])
#So far, so good and everything is working fine with "az" having the
values of lse having also discarded the "bad" iterations.
However I would like to store (as an output) both values (logitse AND logitsp)
in the function logitsboots, that is the list would be as :
list(lse=logitseb,lsp=logitspb).
This way the quantity "res" would have two arguments: res$lse and
res$lsp each time it is called. However when an error occures I just cannot seem
to manage to "unlist" the "res" properly since typing
"res$lse" for example will warn me that the "$" operator
will not work (since it is not numeric anymore I guess). Something like the
following would fail, but I guess that clears what I want to do.
az1=unlist(res$lse[sapply(res$lse, function(x) !inherits(x,
"try-error"))])
az2=unlist(res$lsp[sapply(res$lsp, function(x) !inherits(x,
"try-error"))])
My final goal is to obtain 100 values of lse and 100 values of lsp. (Of course
since the iterations leading to an error would be discarded I will end up with
less than 100 iterations. Any ideas of also using the "while" here in
combination with the "try" to just discard the bad iterations and
replace them with new good ones would be great. This way I would actually get
exactly 100 values of lse and lsp).
Most important is to manage to keep both values in a two column matrix or
something. I hope I was clear enough..
Thanx in advance for any answers!
Leo.
[[alternative HTML version deleted]]
William Dunlap
2012-May-26 16:19 UTC
[R] avoid error within for loop, try, trycatch, while, move to next iteration, unlist
You could put the try() into a while loop, inside for for or lapply loop, as in:> f <- function(x){ stopifnot(x>0.5) ; x } > o <- numeric(100); for(i in seq_along(o)) { while(inherits(try(tmp <- f(runif(1)), silent=TRUE), "try-error")) {} ; o[[i]] <- tmp } > range(o)[1] 0.5000588 0.9991261 Bill Dunlap Spotfire, TIBCO Software wdunlap tibco.com> -----Original Message----- > From: r-help-bounces at r-project.org [mailto:r-help-bounces at r-project.org] On Behalf > Of ?e???da? ?pa?t?? > Sent: Saturday, May 26, 2012 6:15 AM > To: r-help at r-project.org > Subject: [R] avoid error within for loop, try, trycatch, while, move to next iteration, unlist > > > > > Hi there, > > I would like to ask something about how to avoid a possible error message within a for > loop. I am running a simulation and in some repetitions there may be an error that will > cause a crash and stop the whole procedure, what I want is to simply move on to the > next iteration automatically and discard the "bad" repetitions from my results. I used the > "try" function to do this and it partially works. > > Here is the thing: > > logitsboots <- function(x,y,Jbh) { > logitseb=0;logitspb=0; > for (j in 1:1) { > > > #some code here that has to do with random numbers that may or may not produce an > error and calculates the values of two scalar quantities: spboots? and seboots, > > > ? logitspb=log(spboots/(1-spboots)) > ? logitseb=log(seboots/(1-seboots)) > > #assume that I only care about logitseb for the moment > } > list(lse=logitseb) > > } > > > > # Now the following works just fine: > > > res=0 > for(bb in 1:100) { > res[bb] <- try(logitsboots(x,y,Jbh), TRUE) > ??? } > az=unlist(res[sapply(res, function(x) !inherits(x, "try-error"))]) > > > > > #So far, so good and everything is working fine with "az" having the values of lse having > also discarded the "bad" iterations. > > > However I would like to store (as an output) both values (logitse AND logitsp) in the > function logitsboots, that is the list would be as : > > > list(lse=logitseb,lsp=logitspb). > > This way the quantity "res" would have two arguments: res$lse and res$lsp each time it is > called. However when an error occures I just cannot seem to manage to "unlist" the "res" > properly since typing "res$lse" for example will warn me that the "$" operator will not > work (since it is not numeric anymore I guess). Something like the following would fail, > but I guess that clears what I want to do. > > > az1=unlist(res$lse[sapply(res$lse, function(x) !inherits(x, "try-error"))]) > > az2=unlist(res$lsp[sapply(res$lsp, function(x) !inherits(x, "try-error"))]) > > My final goal is to obtain 100 values of lse and 100 values of lsp. (Of course since the > iterations leading to an error would be discarded I will end up with less than 100 > iterations. Any ideas of also using the "while" here in combination with the "try" to just > discard the bad iterations and replace them with new good ones would be great. This > way I would actually get exactly 100 values of lse and lsp). > > Most important is to manage to keep both values in a two column matrix or something. I > hope I was clear enough.. > > > > Thanx in advance for any answers! > > Leo. > [[alternative HTML version deleted]]
William Dunlap
2012-May-26 17:10 UTC
[R] avoid error within for loop, try, trycatch, while, move to next iteration, unlist
You could encapsulate this idiom in a function:
untilOK <- function (expr, silent = TRUE, maxIter = 1000,
quotedExpr = substitute(expr), envir = parent.frame())
{
while ((maxIter <- maxIter - 1) >= 0 && inherits(tmp <-
try(eval(quotedExpr,
envir = envir), silent = silent), "try-error")) {
}
if (maxIter < 0) {
stop("reached maxIter iterations, last error message is ",
as.character(tmp))
}
tmp
}
E.g.,
> f <- function(x){ stopifnot(x>0.9) ; x } # fails 90% of time
> vapply(1:10, function(i)untilOK(f(runif(1))), FUN.VALUE=0.0)
[1] 0.9460461 0.9670447 0.9306208 0.9122009 0.9495725 0.9619204 0.9031418
0.9624259 0.9809273 0.9518705
> untilOK(stopifnot(1==2)) # maxIter=1000 protects against inappropriate
expressions.
Error in untilOK(stopifnot(1 == 2)) :
reached maxIter iterations, last error message is Error : 1 == 2 is not TRUE
Bill Dunlap
Spotfire, TIBCO Software
wdunlap tibco.com
> -----Original Message-----
> From: r-help-bounces at r-project.org [mailto:r-help-bounces at
r-project.org] On Behalf
> Of William Dunlap
> Sent: Saturday, May 26, 2012 9:20 AM
> To: ???????? ???????; r-help at r-project.org
> Subject: Re: [R] avoid error within for loop, try, trycatch, while, move to
next iteration,
> unlist
>
> You could put the try() into a while loop, inside for for or lapply loop,
> as in:
>
> > f <- function(x){ stopifnot(x>0.5) ; x }
> > o <- numeric(100); for(i in seq_along(o)) { while(inherits(try(tmp
<- f(runif(1)),
> silent=TRUE), "try-error")) {} ; o[[i]] <- tmp }
> > range(o)
> [1] 0.5000588 0.9991261
>
> Bill Dunlap
> Spotfire, TIBCO Software
> wdunlap tibco.com
>
>
> > -----Original Message-----
> > From: r-help-bounces at r-project.org [mailto:r-help-bounces at
r-project.org] On Behalf
> > Of ?e???da? ?pa?t??
> > Sent: Saturday, May 26, 2012 6:15 AM
> > To: r-help at r-project.org
> > Subject: [R] avoid error within for loop, try, trycatch, while, move
to next iteration,
> unlist
> >
> >
> >
> >
> > Hi there,
> >
> > I would like to ask something about how to avoid a possible error
message within a for
> > loop. I am running a simulation and in some repetitions there may be
an error that will
> > cause a crash and stop the whole procedure, what I want is to simply
move on to the
> > next iteration automatically and discard the "bad"
repetitions from my results. I used
> the
> > "try" function to do this and it partially works.
> >
> > Here is the thing:
> >
> > logitsboots <- function(x,y,Jbh) {
> > logitseb=0;logitspb=0;
> > for (j in 1:1) {
> >
> >
> > #some code here that has to do with random numbers that may or may not
produce an
> > error and calculates the values of two scalar quantities: spboots? and
seboots,
> >
> >
> > ? logitspb=log(spboots/(1-spboots))
> > ? logitseb=log(seboots/(1-seboots))
> >
> > #assume that I only care about logitseb for the moment
> > }
> > list(lse=logitseb)
> >
> > }
> >
> >
> >
> > # Now the following works just fine:
> >
> >
> > res=0
> > for(bb in 1:100) {
> > res[bb] <- try(logitsboots(x,y,Jbh), TRUE)
> > ??? }
> > az=unlist(res[sapply(res, function(x) !inherits(x,
"try-error"))])
> >
> >
> >
> >
> > #So far, so good and everything is working fine with "az"
having the values of lse having
> > also discarded the "bad" iterations.
> >
> >
> > However I would like to store (as an output) both values (logitse AND
logitsp) in the
> > function logitsboots, that is the list would be as :
> >
> >
> > list(lse=logitseb,lsp=logitspb).
> >
> > This way the quantity "res" would have two arguments:
res$lse and res$lsp each time it
> is
> > called. However when an error occures I just cannot seem to manage to
"unlist" the
> "res"
> > properly since typing "res$lse" for example will warn me
that the "$" operator will not
> > work (since it is not numeric anymore I guess). Something like the
following would fail,
> > but I guess that clears what I want to do.
> >
> >
> > az1=unlist(res$lse[sapply(res$lse, function(x) !inherits(x,
"try-error"))])
> >
> > az2=unlist(res$lsp[sapply(res$lsp, function(x) !inherits(x,
"try-error"))])
> >
> > My final goal is to obtain 100 values of lse and 100 values of lsp.
(Of course since the
> > iterations leading to an error would be discarded I will end up with
less than 100
> > iterations. Any ideas of also using the "while" here in
combination with the "try" to just
> > discard the bad iterations and replace them with new good ones would
be great. This
> > way I would actually get exactly 100 values of lse and lsp).
> >
> > Most important is to manage to keep both values in a two column matrix
or something.
> I
> > hope I was clear enough..
> >
> >
> >
> > Thanx in advance for any answers!
> >
> > Leo.
> > [[alternative HTML version deleted]]
>
> ______________________________________________
> R-help at r-project.org mailing list
> https://stat.ethz.ch/mailman/listinfo/r-help
> PLEASE do read the posting guide
http://www.R-project.org/posting-guide.html
> and provide commented, minimal, self-contained, reproducible code.