R for Loop Skip to Next Iteration Ifelse

R for loop skip to next iteration ifelse

for(n in 1:5) {
if(n==3) next # skip 3rd iteration and go to next iteration
cat(n)
}

How to skip iterations in a for loop using the next function in R

This question is difficult to understand. One important information is disclosed in a comment by the OP:

The desired final table will be longer than the len1 sample, it should
be equal to sum(len1)

If I understand correctly, the OP wants to copy a 1 to the output vector if the input is 1 and he wants to copy two subsequent 2s to the output vector if the input vector is 2.

If my understanding is correct, then this is what

rep(len1, times = len1)

does.

So, with a proper reproducible example

n_row <- 10L
set.seed(2L)
len1 <- sample(1:2, n_row , replace = TRUE)
len1
[1] 1 2 2 1 2 2 1 2 1 2
rep(len1, times = len1)

returns

[1] 1 2 2 2 2 1 2 2 2 2 1 2 2 1 2 2

Of course, sum(len1) == length(rep(len1, times = len1)) is TRUE.

Thus, the data.frame can be created by

data.frame(col1 = rep(len1, times = len1), col2 = seq_len(sum(len1)))

Fixing the for loop (not recommended)

If my understanding of OP's intenstions is correct, OP's for loop can be fixed by introducing a separate count j for the output vector:

df <- data.frame(col1 = seq_len(sum(len1)), col2 = seq_len(sum(len1)))
j <- 1L
for (i in 1:length(len1)) {
if (len1[i] == 1L) {
df$col1[j] <- len1[i]
j <- j + 1L
}
else if (len1[i] == 2L) {
df$col1[j] <- len1[i]
df$col1[j + 1L] <- 2L
j <- j + 2L
}
}
df
   col1 col2
1 1 1
2 2 2
3 2 3
4 2 4
5 2 5
6 1 6
7 2 7
8 2 8
9 2 9
10 2 10
11 1 11
12 2 12
13 2 13
14 1 14
15 2 15
16 2 16

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

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

R: Continue loop to next iteration if function used in loop has stop() clausule

When the function sondeprofile() throws an error, it will stop your whole loop. However, you can avoid that with try(), which attempts to try to run "an expression that might fail and allow the user's code to handle error-recovery." (From help("try")).

So, if you replace

sonde <- sondeprofile(date)

with

sonde <- try(sondeprofile(date), silent = TRUE)

you can avoid the problem of it stopping your loop. But then how do you deal with the if() condition?

Well, if a try() call encounters an error, what it returns will be of class try-error. So, you can just make sure that sonde isn't of that class, changing

if(exists("sonde")) {

to

if ( !inherits(sonde, "try-error") ) {

Skip iteration and return NA in nested for loop in R

You can use colSums to perform a check :

index <- colnames(test) %>% str_which("N.")

betas <- matrix(nrow=length(unique(test$IDcount)), ncol=2)
colnames(betas) <- c("Intercept", "beta")

for (j in colnames(test)[index]) {

for (i in 1:2) {
tmp <- test[test$IDcount==i, c("Otminus1", j)]
if(any(colSums(!is.na(tmp)) == 0)) next
betas[i,] <- coef(lm(Otminus1~., tmp))
}
betas <- data.frame(betas)
results[[j]] <- betas$beta
}

Skipping several iterations of for-loop based on condition

It's not just bad practice to increment the counter inside the loop in R. It simply will not work. That's not the way the language is built. If you want to get 1 and 4 printed then try:

for(i in seq(1,10,by=3) ){
if(i %in% c(1,2,3,4,5)){
print(i)
}
}

Do also note that for-loops actually return NULL. There would be a side-effect of printing to the console, but no values of variables would change. If you want values to change you need to do assignment inside the loop.

The is a next control statement:

for(i in seq(1,10) ){
if( !(i %in% c(1,4)) ){ next }
print(i)
}

How to skip iteration in for loop if condition is met

Your next is working fine to skip the current iteration of the loop.

You still get 0s in the final result because all values of df were initialized df to 0. When you skip the iteration, they are not changed, so they remain 0. If you change the initialization to be NA values, you'll see that no 0s are added.

df <- data.frame(FP1=rep(NA,length(t)),FP2=rep(NA,length(t)),tanimoto=rep(NA,length(t)))
for (i in 1:length(t)){
if (t[i]==0) next
else {
col_num <- floor(sqrt(2*i-7/4)+.5)
row_num <- i-(.5*col_num^2-.5*col_num+1)+1
df$FP1[i] <- row_num
df$FP2[i] <- col_num
df$tanimoto[i] <- v[row_num,col_num]
}
}
df
# FP1 FP2 tanimoto
# 1 1 1 1
# 2 1 2 1
# 3 2 2 1
# 4 1 3 1
# 5 2 3 1
# 6 3 3 1
# 7 NA NA NA
# 8 2 4 1
# 9 3 4 1
# 10 4 4 1
# 11 NA NA NA
# ...

A simple modification would be to filter your data frame as a last step: df = df[df$tanimoto != 0, ], or if you switch to NA, df = na.omit(df).

We could also create a non-looping solution:

v1 = v != 0 
df2 = data.frame(FP1 = row(v)[v1], FP2 = col(v)[v1], tanimoto = v[v1])
df2 = subset(df2, FP1 <= FP2)
df2
# FP1 FP2 tanimoto
# 1 1 1 1
# 7 1 2 1
# 8 2 2 1
# 13 1 3 1
# 14 2 3 1
# 15 3 3 1
# 20 2 4 1
# 21 3 4 1
# 22 4 4 1
# 27 3 5 1
# 28 4 5 1
# 29 5 5 1
# 33 1 6 1
# 34 4 6 1
# 35 5 6 1
# ...


Related Topics



Leave a reply



Submit