R, warning sequencing in for loop - r

In R, a function inside for loop is not printing warnings in sequence.
for(i in sample(-2:2)){
cat(sprintf("running for %d\n", i))
j= sqrt(i)
}
#running for 0
#running for -2
#running for 1
#running for -1
#running for 2
#Warning messages:
#1: In sqrt(i) : NaNs produced
#2: In sqrt(i) : NaNs produced
The warning messages are printed at the end and it is not clear for which values we get warning. I am looking for warning massege sequence as
#running for 0
#running for -2
#Warning messages:
#1: In sqrt(i) : NaNs produced
#running for 1
#running for -1
#Warning messages:
#2: In sqrt(i) : NaNs produced
#running for 2
How can I force R to print warning in sequential way (or print warning immediately after the execution of code)?

There is a immediate. parameter in the warning function especially for that purpose, try setting in your function
if (i < 5) warning("A warning", immediate. = TRUE)
eg.
foo <- function(i){
if (i < 5) warning("A warning", immediate. = TRUE)
i }
for (i in 3:7){
cat(sprintf("running for %d\n", i))
foo(i)
}
# running for 3
# Warning in foo(i) : A warning
# running for 4
# Warning in foo(i) : A warning
# running for 5
# running for 6
# running for 7
Edit: Per your new update, you will probably need to wrap your function up into tryCatch, something like
set.seed(222)
for(i in sample(-2:2)){
cat(sprintf("running for %d\n", i))
tryCatch(sqrt(i), warning = function(w) message(paste(w, "\n")))
}
# running for 2
# running for -2
# simpleWarning in sqrt(i): NaNs produced
#
#
# running for -1
# simpleWarning in sqrt(i): NaNs produced
#
#
# running for 1
# running for 0

From ?options the option warn is listed to fill this role. It's not really the best option; tryCatch is most likely cleaner provided the warnings are being used correctly but it's useful for debugging.
warn: sets the handling of warning messages. If warn is negative all
warnings are ignored. If warn is zero (the default) warnings are
stored until the top–level function returns. If 10 or fewer warnings
were signalled they will be printed otherwise a message saying how
many were signalled. An object called last.warning is created and can
be printed through the function warnings. If warn is one, warnings are
printed as they occur. If warn is two or larger all warnings are
turned into errors.
options(warn=1)
for(i in sample(-2:2)){
cat(sprintf("running for %d\n", i))
j <- sqrt(i)
}
#running for -2
#Warning in sqrt(i) : NaNs produced
#running for 2
#running for 0
#running for 1
#running for -1
#Warning in sqrt(i) : NaNs produced
You could also use something like:
currentWarnLevel <- getOptions("warn")
# code that should print warn straight away
options(warn = currentWarnLevel)
If you're using a custom logger I found it best to override options(warning.expression) and using withCallingHandlers and then reset warning.expression.

Related

Setting `immediate.` to `TRUE` with condition object in R?

I am trying to signal a custom condition in R using a condition object. However, it seems that I cannot set the immediate. argument to TRUE, nor can I alter any other argument to the stop, warning, etc functions. Is there a way to use condition objects but still retain the other arguments of stop, warning, and message ?
MWE:
Warning in perhaps the "usual" way works as expected, meaning that the warnings occur at each iteration. This is what I desire.
# Works as expected
for(i in 1:20){warning("A warning", immediate.=T) ; Sys.sleep(.1)}
>Warning: A warning
>Warning: A warning
>Warning: A warning
>Warning: A warning
>Warning: A warning
... [truncated]
In contrast, when using a condition object below, the warnings are collected and then we're told that there are 20 of them at the end:
Attempt 1
# Does not signal warning immediately
cond = structure(list(message="A warning", call=NULL, immediate.=T), class=c("warning", "condition"))
for(i in 1:20){ warning(cond); Sys.sleep(.1) }
>There were 20 warnings (use warnings() to see them)
Attempt 2 -- Setting the argument manually
for(i in 1:20) {warning(cond, immediate.=T); Sys.sleep(.1)}
>additional arguments ignored in warning()
>additional arguments ignored in warning()
>...[truncated]
>There were 20 warnings (use warnings() to see them)
Attempt 3 -- Deleting the immediate.=T argument from the cond object, and retrying (2)
cond = structure(list(message="A warning", call=NULL), class=c("warning", "condition"))
for(i in 1:20) {warning(cond, immediate.=T); Sys.sleep(.1)}
>additional arguments ignored in warning()
>additional arguments ignored in warning()
>...[truncated]
>There were 20 warnings (use warnings() to see them)
Is there a way to use condition objects but still retain the other arguments of stop, warning, and message ?
Okay so I have found a workaround/solution that gets the job done, although it is somewhat inelegant. In any case, the solution that works consists of:
Wrapping the warning in a tryCatch block
Capture the warning condition object
Modify the captured object from (2) as needed
Re-warn using the modified object from (3)
# Set immediate. to false, collects warnings as expected
my.call = "A call"
for(i in 1:20){
tryCatch(warning("A warning", immediate.=F),
warning = function(w){w$call <- my.call; warning(w)}
)
Sys.sleep(.1)
}
>There were 20 warnings (use warnings() to see them)
# changing immediate. to true, warns at each iteration as desired
for(i in 1:20){
tryCatch(warning("A warning", immediate.=T),
warning = function(w){w$call <- my.call; warning(w)}
)
Sys.sleep(.1)
}
>Warning in "A call" : A warning
>Warning in "A call" : A warning
>Warning in "A call" : A warning
>...[truncated]

How to capture particular warning message and execute call

Lately when I run my code that uses coxph in the survival package
coxph(frml,data = data), I am now getting warning messages of the following type
1: In model.matrix.default(Terms, mf, contrasts = contrast.arg) :
partial argument match of 'contrasts' to 'contrasts.arg'
2: In seq.default(along = temp) :
partial argument match of 'along' to 'along.with'"
I'm not exactly sure why all of a sudden these partial argument match warnings started popping up, but I don't think they effect me.
However, when I get the following warning message, I want coxph(frml,data = data) = NA
3: In fitter(X, Y, strats, offset, init, control, weights = weights, :
Loglik converged before variable 2 ; beta may be infinite.
6: In coxph(frml, data = data) :
X matrix deemed to be singular; variable 1 3 4
I used tryCatch when I wasn't getting the partial argument match warning using this code where if the nested tryCatch got either a warning or error message it would return NA
coxphfit = tryCatch(tryCatch(coxph(frml,data = data), error=function(w) return(NA)), warning=function(w) return(NA))
However, now that I am getting the partial argument match warnings, I need to only return an NA if there is an error or if I get the above warning messages 3 and 4 . Any idea about how to capture these particular warning messages and return an NA in those instances?
It's actually interesting question, if you are looking for quick and dirty way of capturing warnings you could simply do:
withCallingHandlers({
warning("hello")
1 + 2
}, warning = function(w) {
w ->> w
}) -> res
In this example the object w created in parent environment would be:
>> w
<simpleWarning in withCallingHandlers({ warning("hello") 1 + 2}, warning = function(w) { w <<- w}): hello>
You could then interrogate it:
grepl(x = w$message, pattern = "hello")
# [1] TRUE
as
>> w$message
# [1] "hello"
Object res would contain your desired results:
>> res
[1] 3
It's not the super tidy way but I reckon you could always reference object w and check if the warning message has the phrase you are interested in.

Only receive unique warning messages

Warning messages are a good information i want to know. But i just want to know it one time!
So this function throws 2 different warnings and repeats it 20 times.
How can i tell R to only print unique warnings. Im looking for a gerenal solution.
Warning messages:
1: NAs introduced by coercion
2: In sqrt(-1) : NaNs produced
Here is my example:
foobar <- function(n=20) {
for (i in 1:n) {
as.numeric("b")
sqrt(-1)
}
}
foobar()
To return only unique warning strings, use
unique(warnings())
Now, a problem you may have is that your function has more than 50 warnings, in which case warnings() will not catch them all. To workaround this, you can increase nwarnings in options to e.g. 10000 as suggested in the help page of warnings.
options(nwarnings = 10000)
Example:
foobar <- function(n=20) {
warning("First warning")
for (i in 1:n) {
as.numeric("b")
sqrt(-1)
}
warning("Last warning")
}
foobar(60)
unique(warnings())
## Warning messages:
## 1: In foobar(60) : First warning
## 2: NAs introduced by coercion
## 3: In sqrt(-1) : NaNs produced
op <- options(nwarnings = 10000)
foobar(60)
unique(warnings())
## Warning messages:
## 1: In foobar(60) : First warning
## 2: NAs introduced by coercion
## 3: In sqrt(-1) : NaNs produced
## 4: In foobar(60) : Last warning
options(op)

Loop interruption when warning is encountered with TryCatch in R

I use tryCatch to handle warnings and errors in order to write a log file and secure my code. It write the log correctly with cat when tryCatch returns a success or an error but my problem is the loop execution is stopped when a warning is encountered.
Whitout the tryCatch the loop is not interrupted by warning() so it is not clear for me what's happening here because warning should not beaks loop.
Breaking loop when "warnings()" appear in R
Loop not interrupted :
>list <- c(1:10)
for(i in list){
warning(i)}
Warning: 1
Warning: 2
Warning: 3
Warning: 4
Warning: 5
Warning: 6
Warning: 7
Warning: 8
Warning: 9
Warning: 10
>
Loop interrupted :
>tryCatch(
{
list <- c(1:10)
for(i in list){
warning(i)
}
},
error=function(cond) {
message("ERROR: ", cond)
},
warning=function(cond) {
message("WARNING: ", cond)
}
)
WARNING: simpleWarning in doTryCatch(return(expr), name, parentenv, handler): 1
>
Thank you,

Error Handling in R when implementing association test

I am implementing a zero-inflated negative binomial in R. The code is here:
> ICHP<-read.table("ichip_data_recodeA.raw",header=TRUE)
ICHPdt<-data.table(ICHP)
covfile<-read.table("sorted.covfile.to.glm.out",header=TRUE)
covfiledt<-data.table(covfile)
library(pscl)
fhandle<-file("ichip_zi_nb_model_scoretest.csv","a")
for (i in seq(7, ncol(ICHPdt), 1)) {
notna<-which(!is.na(ICHPdt[[i]]))
string<-eval(parse(text = paste("ICHPdt$", colnames(ICHPdt)[i], sep="")))
nullglmmod<-zeroinfl(formula=OverllTot0[notna] ~ EurAdmix[notna] + Sex[notna] + DisDurMonths[notna] + BMI[notna] + Group[notna] + SmokingStatus[notna], data=covfiledt, dist="negbin")
nullsum<-coef(summary(nullglmmod))
glmmod<-zeroinfl(formula=OverllTot0[notna] ~ EurAdmix[notna] + Sex[notna] + DisDurMonths[notna] + BMI[notna] + Group[notna] + SmokingStatus[notna] + ICHPdt[[i]][notna], data=covfiledt, dist="negbin")
summ <- coef(summary(glmmod))
rownames(summ$zero)[8] <- paste0("ICHPdt$", colnames(ICHPdt)[i])
rownames(summ$count)[8] <- paste0("ICHPdt$", colnames(ICHPdt)[i])
writeLines("zero", con=fhandle)
writeLines(colnames(ICHPdt)[i], fhandle)
write.table(round(summ$zero, 4), file=fhandle)
writeLines("count", con=fhandle)
writeLines(colnames(ICHPdt)[i], fhandle)
write.table(round(summ$count, 4), file=fhandle)
}
The script errors when i=9246, and issues the following:
Error in solve.default(as.matrix(fit$hessian)) :
system is computationally singular: reciprocal condition number = 1.12288e-19
Overall, I need to go through ~100,000 markers, so I should expect ~11 such errors.
I would like to help implementing options, for instance with tryCatch() for catching such an error, skipping that marker, and moving on.
I recommend reading this page for a quick primer and this page for a more complete explanation of error handling, and you should eventually read ?conditions, but in short, there are two ways to handle errors. The first is with a try-catch, as in:
AS.NUMERIC <- function(x){
# for use in the warning handler
expectedWarning <- FALSE
result = tryCatch({
# a calculation that might raise an error or warning
as.numeric(x)
}, warning = function(w) {
# the typical way to identify the type of
# warning is via it's message attribure
if(grepl('^NAs introduced by coercion',w$message)){
cat('an expected warning was issued\n')
# assign the expected value using the scoping assignment
expectedWarning <<- TRUE
}else
cat('an unexpected warning was issued\n')
# reissue the warning
warning(w)
}, error = function(e) {
cat('an error occured\n')
# similar things go here but for handling errors
}, finally = {
# stuff goes here that should happen no matter what,
# such as closing connections or resetting global
# options such as par(ask), etc.
})
# you can handle errors similarly
if(expectedWarning)
result <- 5
return(result)
}
AS.NUMERIC('5')
#> [1] 5
AS.NUMERIC('five') # raises a warning
#> an expected warning was issued
#> [1] 5
#> Warning message:
#> In doTryCatch(return(expr), name, parentenv, handler) :
#> NAs introduced by coercion
The second way is to use try(), which is less nuanced:
x = try(stop('arbitrary error'),# raise an error
silent=TRUE)
# if there is an error, x will be an object with class 'try-error'
if(inherits(x,'try-error'))
# set the default value for x here
x = 5

Resources