R Loops — for, while, and repeat

R BasicsLoopsFree Lesson

Advertisement

R Loops — for, while, and repeat

Learning Objectives

By the end of this tutorial, you will be able to:

  • Use for loops to iterate over sequences and lists
  • Implement while and repeat loops with proper termination
  • Control loop flow with break and next
  • Understand when to use loops vs vectorized operations
  • Apply lapply, sapply, and vapply as loop alternatives

for Loop

The for loop iterates over a sequence:

# Basic syntax
for (i in 1:5) {
  cat("Iteration:", i, "\n")
}
# Iteration: 1
# Iteration: 2
# Iteration: 3
# Iteration: 4
# Iteration: 5

# Iterate over a vector
fruits <- c("apple", "banana", "cherry")
for (fruit in fruits) {
  cat("I like", fruit, "\n")
}
# I like apple
# I like banana
# I like cherry

# Iterate over a list
x <- list(1, "hello", TRUE, 3.14)
for (item in x) {
  cat(class(item), ":", item, "\n")
}
# numeric : 1
# character : hello
# logical : TRUE
# numeric : 3.14

Loop Patterns

# Sequence generation
for (i in seq(1, 10, by = 2)) {
  cat(i, " ")
}
# 1 3 5 7 9

# Reverse order
for (i in 5:1) {
  cat(i, " ")
}
# 5 4 3 2 1

# Using seq_along (index-based)
x <- c("a", "b", "c", "d")
for (i in seq_along(x)) {
  cat("Element", i, ":", x[i], "\n")
}
# Element 1 : a
# Element 2 : b
# Element 3 : c
# Element 4 : d

# Using seq_len
for (i in seq_len(5)) {
  cat(i, " ")
}
# 1 2 3 4 5

Accumulating Results

# Pre-allocate (fast)
result <- numeric(10)
for (i in 1:10) {
  result[i] <- i^2
}
result
# [1]   1   4   9  16  25  36  49  64  81 100

# Growing vector (slow — avoid)
result <- c()
for (i in 1:10) {
  result <- c(result, i^2)  # Creates new copy each time!
}

while Loop

The while loop continues while a condition is TRUE:

# Basic while
x <- 1
while (x <= 5) {
  cat(x, " ")
  x <- x + 1
}
# 1 2 3 4 5

# Counting
count <- 0
total <- 0
while (total < 100) {
  count <- count + 1
  total <- total + count
}
cat("Needed", count, "numbers to exceed 100\n")
# Needed 14 numbers to exceed 100

# With break
x <- 1
while (TRUE) {
  if (x > 10) break
  cat(x, " ")
  x <- x + 1
}
# 1 2 3 4 5 6 7 8 9 10

repeat Loop

The repeat loop runs indefinitely until break:

# Basic repeat
x <- 1
repeat {
  if (x > 5) break
  cat(x, " ")
  x <- x + 1
}
# 1 2 3 4 5

# User input simulation
set.seed(42)
attempt <- 0
repeat {
  attempt <- attempt + 1
  guess <- sample(1:10, 1)
  if (guess == 7) {
    cat("Found 7 on attempt", attempt, "\n")
    break
  }
}
# Found 7 on attempt X (varies)

break and next

break — Exit Loop

# Find first even number
x <- c(1, 3, 5, 8, 9, 12)
for (i in x) {
  if (i %% 2 == 0) {
    cat("First even:", i, "\n")
    break
  }
}
# First even: 8

# Nested loop break
for (i in 1:5) {
  for (j in 1:5) {
    if (i * j > 10) {
      cat("Breaking at i=", i, "j=", j, "\n")
      break
    }
  }
}

next — Skip Iteration

# Skip odd numbers
for (i in 1:10) {
  if (i %% 2 != 0) next
  cat(i, " ")
}
# 2 4 6 8 10

# Skip specific values
x <- c("a", "b", "skip", "d", "skip", "f")
for (item in x) {
  if (item == "skip") next
  cat(item, " ")
}
# a b d f

Vectorized Alternatives (Preferred)

R is vectorized — loops are often unnecessary:

# Slow: loop
x <- 1:1000000
result <- numeric(length(x))
for (i in seq_along(x)) {
  result[i] <- x[i]^2
}

# Fast: vectorized
result <- x^2

# Fast: apply family
result <- sapply(1:1000000, function(x) x^2)

lapply, sapply, vapply

# lapply — returns list
x <- list(1, 2, 3, 4, 5)
lapply(x, function(x) x^2)
# [[1]]
# [1] 1
# [[2]]
# [1] 4
# ...

# sapply — returns simplified result
x <- list(1, 2, 3, 4, 5)
sapply(x, function(x) x^2)
# [1]  1  4  9 16 25

# vapply — like sapply but with type safety
vapply(x, function(x) x^2, numeric(1))
# [1]  1  4  9 16 25

# With names
scores <- list(Alice = 95, Bob = 87, Charlie = 92)
sapply(scores, function(x) x * 1.1)  # 10% bonus
#   Alice     Bob Charlie
#  104.50   95.70  101.20

apply Family Summary

FunctionReturnsUse Case
lapply()ListAlways returns list
sapply()Vector/listSimplified result
vapply()Vector/listType-safe sapply
apply()Vector/arrayApply over margins
tapply()List/arrayApply by group
mapply()Vector/listMultivariate apply

Common Loop Patterns

Nested Loops

# Matrix creation
n <- 5
m <- matrix(0, nrow = n, ncol = n)
for (i in 1:n) {
  for (j in 1:n) {
    m[i, j] <- i + j
  }
}
m

# Or vectorized
m <- outer(1:5, 1:5, "+")

Loop with Counter

# Find convergence
x <- 1
iteration <- 0
repeat {
  iteration <- iteration + 1
  x <- x / 2 + 1/x
  if (abs(x - sqrt(2)) < 1e-10) break
}
cat("Converged to", x, "in", iteration, "iterations\n")

Parallel Loops

# Using parallel package
library(parallel)
cl <- makeCluster(4)
result <- parLapply(cl, 1:100, function(x) x^2)
stopCluster(cl)

Practice Exercises

Exercise 1: Fibonacci

Write a for loop that generates the first 20 Fibonacci numbers.

Solution

fib <- numeric(20)
fib[1] <- 1
fib[2] <- 1
for (i in 3:20) {
  fib[i] <- fib[i-1] + fib[i-2]
}
fib
# [1]    1    1    2    3    5    8   13   21   34   55   89  144  233
# [14]  377  610  987 1597 2584 4181 6765

Exercise 2: Prime Finder

Write a function that finds all prime numbers up to n using a for loop.

Solution

find_primes <- function(n) {
  primes <- c()
  for (i in 2:n) {
    is_prime <- TRUE
    for (j in 2:sqrt(i)) {
      if (i %% j == 0) {
        is_prime <- FALSE
        break
      }
    }
    if (is_prime) primes <- c(primes, i)
  }
  primes
}

find_primes(50)
# [1]  2  3  5  7 11 13 17 19 23 29 31 37 41 43 47

Exercise 3: Matrix Multiplication

Write nested for loops to multiply two 3x3 matrices (without using %*%).

Solution

A <- matrix(1:9, nrow = 3)
B <- matrix(9:1, nrow = 3)

C <- matrix(0, nrow = 3, ncol = 3)
for (i in 1:3) {
  for (j in 1:3) {
    for (k in 1:3) {
      C[i, j] <- C[i, j] + A[i, k] * B[k, j]
    }
  }
}
C

# Verify
all.equal(C, A %*% B)

Key Takeaways

  • for loops iterate over sequences — use seq_along() for index-based iteration
  • while loops continue while condition is TRUE — good for convergence
  • repeat loops run until break — always ensure you have a break condition
  • break exits the loop, next skips to the next iteration
  • Vectorized operations are faster — prefer sapply(), apply(), or native vectorization
  • Pre-allocate results before filling in loops
  • lapply() returns a list, sapply() simplifies to vector

Next: Learn about R Functions — creating reusable code.

Advertisement

Need Expert R Programming Help?

Get personalized tutoring, project support, or professional consulting.

Advertisement