<- runif(n=1, min=0, max=10)
x x
[1] 0.1601887
September 22, 2022
Material for this lecture was borrowed and adopted from
Control structures in R allow you to control the flow of execution of a series of R expressions.
Basically, control structures allow you to put some “logic” into your R code, rather than just always executing the same R code every time.
Control structures allow you to respond to inputs or to features of the data and execute different R expressions accordingly.
Commonly used control structures are
if
and else
: testing a condition and acting on it
for
: execute a loop a fixed number of times
while
: execute a loop while a condition is true
repeat
: execute an infinite loop (must break
out of it to stop)
break
: break the execution of a loop
next
: skip an interation of a loop
if
-else
The if
-else
combination is probably the most commonly used control structure in R (or perhaps any language). This structure allows you to test a condition and act on it depending on whether it’s true or false.
For starters, you can just use the if
statement.
The above code does nothing if the condition is false. If you have an action you want to execute when the condition is false, then you need an else
clause.
You can have a series of tests by following the initial if
with any number of else if
s.
if(<condition1>) {
## do something
} else if(<condition2>) {
## do something different
} else {
## do something different
}
Here is an example of a valid if/else structure.
Let’s use the runif(n, min=0, max=1)
function which draws a random value between a min and max value with the default being between 0 and 1.
Then, we can write and if
-else
statement that tests whethere x
is greater than 3 or not.
If x
is greater than 3, then the first condition occurs. If x
is not greater than 3, then the second condition occurs.
Finally, we can auto print y
to see what the value is.
This expression can also be written a different (but equivalent!) way in R.
Of course, the else
clause is not necessary. You could have a series of if clauses that always get executed if their respective conditions are true.
for
LoopsFor loops are pretty much the only looping construct that you will need in R. While you may occasionally find a need for other types of loops, in my experience doing data analysis, I’ve found very few situations where a for loop was not sufficient.
In R, for loops take an iterator variable and assign it successive values from a sequence or vector.
For loops are most commonly used for iterating over the elements of an object (list, vector, etc.)
This loop takes the i
variable and in each iteration of the loop gives it values 1, 2, 3, …, 10, then executes the code within the curly braces, and then the loop exits.
The following three loops all have the same behavior.
## define the loop to iterate over
x <- c("a", "b", "c", "d")
## create for loop
for(i in 1:4) {
## Print out each element of 'x'
print(x[i])
}
[1] "a"
[1] "b"
[1] "c"
[1] "d"
We can also print just the iteration value (i
) itself
## define the loop to iterate over
x <- c("a", "b", "c", "d")
## create for loop
for(i in 1:4) {
## Print out just 'i'
print(i)
}
[1] 1
[1] 2
[1] 3
[1] 4
seq_along()
The seq_along()
function is commonly used in conjunction with for
loops in order to generate an integer sequence based on the length of an object (or ncol()
of an R object) (in this case, the object x
).
The seq_along()
function takes in a vector and then returns a sequence of integers that is the same length as the input vector. It doesn’t matter what class the vector is.
Let’s put seq_along()
and for
loops together.
[1] "a"
[1] "b"
[1] "c"
[1] "d"
It is not necessary to use an index-type variable (i.e. i
).
You can use any character index you want (but not with symbols or numbers).
For one line loops, the curly braces are not strictly necessary.
However, I like to use curly braces even for one-line loops, because that way if you decide to expand the loop to multiple lines, you won’t be burned because you forgot to add curly braces (and you will be burned by this).
for
loopsfor
loops can be nested inside of each other.
[1] 1
[1] 3
[1] 5
[1] 2
[1] 4
[1] 6
Nested loops are commonly needed for multidimensional or hierarchical data structures (e.g. matrices, lists). Be careful with nesting though.
Nesting beyond 2 to 3 levels often makes it difficult to read/understand the code.
If you find yourself in need of a large number of nested loops, you may want to break up the loops by using functions (discussed later).
while
Loopswhile
loops begin by testing a condition.
If it is true, then they execute the loop body.
Once the loop body is executed, the condition is tested again, and so forth, until the condition is false, after which the loop exits.
[1] 0
[1] 1
[1] 2
[1] 3
[1] 4
[1] 5
[1] 6
[1] 7
[1] 8
[1] 9
while
loops can potentially result in infinite loops if not written properly. Use with care!
Sometimes there will be more than one condition in the test.
repeat
Loopsrepeat
initiates an infinite loop right from the start. These are not commonly used in statistical or data analysis applications, but they do have their uses.
One possible paradigm might be in an iterative algorithm where you may be searching for a solution and you do not want to stop until you are close enough to the solution.
In this kind of situation, you often don’t know in advance how many iterations it’s going to take to get “close enough” to the solution.
next
, break
next
is used to skip an iteration of a loop.
break
is used to exit a loop immediately, regardless of what iteration the loop may be on.
if
, while
, and for
allow you to control the flow of an R programHere are some post-lecture questions to help you think about the material discussed.