NB: R Control Structures

Programming for Data Science

Conditional Statements

R supports conditional statements in the standard way.

It provides the following statements:

if, else if, and else.

Here’s a skeletal control structure in R:

if (<condition>) {
        ## do something
} 

if (<condition>) {
        ## do something
} 
else {
        ## do something else
}

Here is a more compact way of writing it:

if (<condition1>) {
        ## do something
} else if (<condition2>)  {
        ## do something different
} else {
        ## do something different
}

Let’s look at some examples.

Here, we generate a uniform random number, using the function runif().

The first argument determines the number of results, and the second two define the upper and lower bound.

x <- runif(1, 0, 10)
x
6.29529620986432
if (x > 3) {
    y <- 10
} else {
    y <- 0
}
y
10

You can assign an if statement to a variable.

z <- if (x > 3) {10} else {0}
z
10

Note you can drop the braces when doing a one-liner.

z <- if (x > 3) 10 else 0
z
10

You do need to keep the parentheses around the comparison expression, though.

Of course, you can stack if blocks, too.

if (<condition1>) {
    
}

if (<condition2>) {

}

for Loops

For loops are straight-forward in R.

They take an iterator variable, e.g. i, and assign it successive values from a sequence or vector.

for (i in 1:10) {
  print(i)
}
[1] 1
[1] 2
[1] 3
[1] 4
[1] 5
[1] 6
[1] 7
[1] 8
[1] 9
[1] 10

seq_along()

The seq_along() function is commonly used in conjunction with for loops.

It generates an integer sequence based on the length of an object.

x <- c("a", "b", "c", "d")
for (i in seq_along(x)) {
  print(x[i])  
}
[1] "a"
[1] "b"
[1] "c"
[1] "d"

Note that it is not necessary to use an index-type variable to iterate through an iterable object.

for (letter in x) {
  print(letter)
}
[1] "a"
[1] "b"
[1] "c"
[1] "d"

For one line loops, the curly braces are not strictly necessary.

for (i in 1:4) print(x[i])
[1] "a"
[1] "b"
[1] "c"
[1] "d"

seq_len()

The seq_len() function is also used in conjunction with for loops.

It generates an integer sequence based a number.

for (i in seq_len(length(x))) {
  print(x[i])  
}
[1] "a"
[1] "b"
[1] "c"
[1] "d"

seq_len() is like seq(), but it doesn’t have the flexibility of the latter.

It handles the common case of beginning at \(1\) and stepping by \(1\).

seq(length(x))
seq_len(length(x))
  1. 1
  2. 2
  3. 3
  4. 4
  5. 5
  6. 6
  1. 1
  2. 2
  3. 3
  4. 4
  5. 5
  6. 6

Nested for loops

For loops can be nested inside of each other.

The number of levels you nest is often a function of the number of dimensions in your iterable.

Here we iterate through a \(2\)-D data structure.

x <- matrix(1:6, 2, 3)
for (i in seq_len(nrow(x))) {
  for (j in seq_len(ncol(x))) {
    print(x[i, j])
  }   
}
[1] 1
[1] 3
[1] 5
[1] 2
[1] 4
[1] 6

while Loops

As with Python, while loops start with a condition.

It iterates while the condition is TRUE and stops when it is FALSE.

Remember, while loops can go on forever is the truth condition is never met!

count <- 0
while (count < 10) {
  print(count)
  count <- count + 1
}
[1] 0
[1] 1
[1] 2
[1] 3
[1] 4
[1] 5
[1] 6
[1] 7
[1] 8
[1] 9

next and break

next is used to skip an iteration of a loop.

This is the same as continue in Python.

for (i in 1:100) {
  if (i <= 20) {
    # Skip the first 20 iterations
    next                
  }     
  # Do something here
}

break is used to exit a loop immediately.

for (i in 1:100) {
  print(i)
  if (i > 20) {
    # Stop loop after 20 iterations
    break  
  }     
}
[1] 1
[1] 2
[1] 3
[1] 4
[1] 5
[1] 6
[1] 7
[1] 8
[1] 9
[1] 10
[1] 11
[1] 12
[1] 13
[1] 14
[1] 15
[1] 16
[1] 17
[1] 18
[1] 19
[1] 20
[1] 21

repeat Loops

repeat loops are used by R.

They initiate an infinite loop right from the start.

The only way to exit a repeat loop is to call break on an internal condition.

Here’s an example of what one might look like:

x0 <- 1
tol <- 1e-8

repeat {
  x1 <- computeEstimate()
  if (abs(x1 - x0) < tol) {  ## Close enough?
    break
  } else {
    x0 <- x1
  } 
}