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 tosum(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 2
s 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
Find Out the Number of Days of a Month in R
How to Use Dplyr's Summarize and Which() to Lookup Min/Max Values
Add Text on Top of a Faceted Dodged Bar Chart
Merge Dataframes, Different Lengths
Combining S4 and S3 Methods in a Single Function
Edit Datatable in Shiny with Dropdown Selection for Factor Variables
Compute Monthly Averages from Daily Data
Pivot_Longer with Multiple Classes Causes Error ("No Common Type")
Adding Column If It Does Not Exist
How to Rbind Vectors Matching Their Column Names
Pad with Leading Zeros to Common Width
How to Strip Dollar Signs ($) from Data/ Escape Special Characters in R
Change Geom_Text's Default "A" Legend to Label String Itself
R: Replacing Na Values by Mean of Hour with Dplyr