For Next loop - Receiving error - r

I have tried the following simple for next loop in R programming:
for(i in 1:100) { if(i <= 20) { next } print(i) }
Below is the error message I am receiving:
Error: unexpected symbol in "for(i in 1:100) { if(i <= 20) {next} print"
Please help me understand why I am receiving the error.

Give this a shot:
for (i in 1:100) {
if (i<=20) {
next
};
print(i)
}
Looks like you missed your semi-colon. You need this to denote the end of a statement.

you need to break the line (enter) after {next} and have print(i)} in another line. :) Good Luck

Related

How to redo tryCatch after error in for loop

I am trying to implement tryCatch in a for loop.
The loop is built to download data from a remote server. Sometimes the server no more responds (when the query is big).
I have implemented tryCatch in order to make the loop keeping.
I also have added a sys.sleep() pause if an error occurs in order to wait some minutes before sending next query to the remote server (it works).
The problem is that I don't figure out how to ask the loop to redo the query that failed and lead to a tryCatch error (and to sys.sleep()).
for(i in 1:1000){
tmp <- tryCatch({download_data(list$tool[i])},
error = function(e) {Sys.sleep(800)})
}
Could you give me some hints?
You can do something like this:
for(i in 1:1000){
download_finished <- FALSE
while(!download_finished) {
tmp <- tryCatch({
download_data(list$tool[i])
download_finished <- TRUE
},
error = function(e) {Sys.sleep(800)})
}
}
If you are certain that waiting for 800 seconds always fixes the issue this change should do it.
for(i in 1:1000) {
tmp <- tryCatch({
download_data(list$tool[i])
},
error = function(e) {
Sys.sleep(800)
download_data(list$tool[i])
})
}
A more sophisticated approach could be, to collect the information of which request failed and then rerun the script until all requests succeed.
One way to do this is to use the possibly() function from the purrr package. It would look something like this:
todo <- rep(TRUE, length(list$tool))
res <- list()
while (any(todo)) {
res[todo] <- map(list$tool[todo],
possibly(download_data, otherwise = NA))
todo <- map_lgl(res, ~ is.na(.))
}

How to flush the print buffer in R?

I want to run a long-running simulation and have updates printed periodically. However, I am finding that my print statements are being buffered, even when I explicitly try to flush. Here, for example:
for (i in 1:10)
{
print(i)
flush(stdout())
Sys.sleep(1)
}
I would expect this to increment every 1sec, but it outputs everything at the end, after 10 seconds.
How would you force a flush of the print buffer?
I usually do it like this:
for (i in 1:10) {
message(i,"\r",appendLF=FALSE)
flush.console()
Sys.sleep(1)
}
You can also use cat():
for (i in 1:10) {
# Sleep for 1 second
Sys.sleep(1)
# Print the current iteration
cat(paste0("\r", i))
}

Command that allows re-checking TRUE/FALSE

How to write command (function) that would allow "endless loop" checking whether the internet connection is TRUE else wait and than check again and so on....
Here is attempt what I mean:
havingIP <- function() { if (.Platform$OS.type == "windows") {
ipmessage <- system("ipconfig", intern = TRUE) } else {
ipmessage <- system("ifconfig", intern = TRUE) }
validIP <- "((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)[.]){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)"
any(grep(validIP, ipmessage)) }
The source for the above solution and credit goes here:
How to determine if you have an internet connection in R
if(havingIP()){ source(....) } else { for(i in 1:5) { Sys.sleep(1); cat(i) }}
Something like this but this is not appropriate since I want to execute the command source only once.
while(TRUE){
if(havingIP()){ print("working") } else { for(i in 1:5) { Sys.sleep(1);
cat(i) }}
}
So how to run this without loop that would check every 5sec and if the internet connection is not on wait another 5sec and so on until the internet is on, then execute the source only once and that's it.
Sorry I tried to search for this solution, I'm sure someone has asked something similar but could not find anything since I'm not sure how to search for it anyway. Thanks!
It seems like you might be looking for break:
while (TRUE) {
if (havingIP()) {
print("working") # execute what you want here
break # and if we ever reach here, then exit the while loop
} else {
for (i in 1:5) {
Sys.sleep(1)
cat(i)
}
}
}
A simpler take on lee's answer:
while(!havingIP()) for(i in 1:5) {Sys.sleep(1); cat(i)}
source(...)
This will pause execution until havingIP returns TRUE.

Skip Error and Continue Function in R

I have a data set with p number of variables. I want a function that creates histograms of each variable, and when it encounters a problem it attempts to create a barplot instead. If it encounters a problem after attempting the barplot it skips that p, and continues to the next p.
What I'm thinking (pseudocode):
for (i in ncol(data)) {
try( hist(data[i])) {
if "error" try( barplot(data[i])) {
if "error" print ("Error") }
}
continue to i # code executes through all columns of data
}
}
I've tried using the try() and tryCatch() based on other stackoverflow posts, but I can't seem to figure out how to work it.
You probably want to use tryCatch for this. Something like the following should do the trick (though I can't test it since you don't provide any data).
for(i in 1:ncol(d)) {
tryCatch(hist(d[[i]], main=i), error=function(e) {
tryCatch(barplot(d[[i]], main=i), error=function(e) {
print('Error')
})
})
}

Why does R say no loop for break/next, jumping to top level

Why does R throw the error "Error in value[3L] : no loop for break/next, jumping to top level" instead of going to the next iteration of a loop? I'm on R version 2.13.1 (2011-07-08)
for (i in seq(10)) {
tryCatch(stop(), finally=print('whoops'), error=function(e) next)
}
This problem came up because I wanted to create a different image or no image at all when plot failed. The code, using joran's approach, would look like this:
for (i in c(1,2,Inf)) {
fname = paste(sep='', 'f', i, '.png')
png(fname, width=1024, height=768)
rs <- tryCatch(plot(i), error=function(e) NULL)
if (is.null(rs)){
print("I'll create a different picture because of the error.")
}
else{
print(paste('image', fname, 'created'))
dev.off()
next
}
}
Maybe you could try :
for (i in seq(10)) {
flag <- TRUE
tryCatch(stop(), finally=print('whoops'), error=function(e) flag<<-FALSE)
if (!flag) next
}
Unfortunately, once you get inside your error function you're no longer in a loop. There's a way you could hack around this:
for (i in seq(10)) {
delayedAssign("do.next", {next})
tryCatch(stop(), finally=print('whoops'),
error=function(e) force(do.next))
}
Though that is... well, hacky. Perhaps there is a less hacky way, but I don't see one right off.
(This works because delayedAssign happens every loop, canceling out the efforts of force)
EDIT
Or you could use continuations:
for (i in seq(10)) {
callCC(function(do.next) {
tryCatch(stop(), finally=print('whoops'),
error=function(e) do.next(NULL))
# Rest of loop goes here
print("Rest of loop")
})
}
EDIT
As Joris points out, you probably shouldn't actually use either of these, because they're confusing to read. But if you really want to call next in a loop, this is how :).
Wouldn't it make more sense to put the next outside the tryCatch based on an if check? Something like this:
for (i in c(1,2,Inf)) {
rs <- tryCatch(seq(i), finally=print('whoops'), error=function(e) NULL)
if (is.null(rs)){
print("I found an error!")
}
else{
next
}
}
although I'm not sure this is what you want, since I'm a little unclear on what you're trying to do.
EDIT
Based on the OP's revisions, this formulation works for me:
plotFn <- function(fname,i){
png(fname, width=400, height=200)
plot(i)
dev.off()
}
for (i in c(1,Inf,3)) {
fname = paste('f', i, '.png',sep="")
rs <- tryCatch(plotFn(fname,i), error=function(e){dev.off(); return(NULL)})
if (is.null(rs)){
print("I'll create a different picture because of the error.")
}
else{
print(paste('image', fname, 'created'))
next
}
}
I'm certain that not having a dev.off() call in the case of an error needed to be fixed. I'd have to dig a little deeper to figure out exactly why separating png and plot was causing problems. But I think it's probably cleaner to keep the png(); plot(); dev.off() sequence self contained anyway. Also note that I put a dev.off() in the error function.
I haven't tested what will happen if plotFn throws an error on png(), never creates the device and then reaches the error function and calls dev.off(). Behavior may depend on what else you have going on in your R session.

Resources