Chapter 6 Control flow in R
In this chapter, we will cover basically the so-called Control flow in R with the following topics -
- Conditional execution
If-else
statements
- Loops
while
loopfor
loop
- User defined funstions in R
- Functions without
return
- Functions with
return
- Functions without
6.1 Conditional execution
6.1.1 If-else
statement
The very basic conditional execution is the if
and if-else
statements. Let’s think you have a condition of do something (i.e. choose from a set of data-points or perform a mathematical operation) using R, you use if(condition){do something}
. For example -
## [1] "x is equal to 10"
If you want to add more twist to the condition, you bring in else
statement - if(condition){do something} else{do the alternative}
. Like here -
## [1] "x is not equal to 10"
You are not quiet content with the arguments here, you want to add more twists to the conditions, you add an intermediate else if
condition -
x <- 11
if(x > 20){
print("x is greater than 20")
} else if(x <= 20 & x >= 10){
print("x is between 10 and 20")
} else{
print("x is less than 10")
}
## [1] "x is between 10 and 20"
6.1.2 Short exercise
You have a job to grade 20 math scripts (the score ranges from 0 to 10) from a class of yr 7 students according to the following scale -
grade A: 8-10
grade B: 6-7
grade C: 4-5
grade F: 0-3
If a student scored 5, what’s the allocated grade? Write a set of conditional if else
statements to answer the question.
6.2 Loops
Loops are efficient ways to perform some mathematical operation iteratively, like - keep walking until you reach your destination (using while loop) or read each element of a vector, add one to it and do the same to the next (using for loop).
6.2.1 while loop
The basic structure of while loop is while(condition){execute some action}
, like -
# Think logically before executing the following code snippet -
# a <- 10
# while(a < 20){
# print("a is less than 20")
# }
There are two ways to tackle this -
- you can increase the value of
a
(in each iteration) -
a <- 10
while(a < 20){
print("a is less than 20")
a <- a + 1
print(paste0("Because value of a is now ", a))
}
## [1] "a is less than 20"
## [1] "Because value of a is now 11"
## [1] "a is less than 20"
## [1] "Because value of a is now 12"
## [1] "a is less than 20"
## [1] "Because value of a is now 13"
## [1] "a is less than 20"
## [1] "Because value of a is now 14"
## [1] "a is less than 20"
## [1] "Because value of a is now 15"
## [1] "a is less than 20"
## [1] "Because value of a is now 16"
## [1] "a is less than 20"
## [1] "Because value of a is now 17"
## [1] "a is less than 20"
## [1] "Because value of a is now 18"
## [1] "a is less than 20"
## [1] "Because value of a is now 19"
## [1] "a is less than 20"
## [1] "Because value of a is now 20"
But, see, there’s a logical fault in the coding.
- Using
break
to break out of the loop
a <- 10
while(a < 20){
a <- a + 1
if(a < 20){
print("a is less than 20")
print(paste0("Because value of a is now ", a))
}else{
break
}
}
## [1] "a is less than 20"
## [1] "Because value of a is now 11"
## [1] "a is less than 20"
## [1] "Because value of a is now 12"
## [1] "a is less than 20"
## [1] "Because value of a is now 13"
## [1] "a is less than 20"
## [1] "Because value of a is now 14"
## [1] "a is less than 20"
## [1] "Because value of a is now 15"
## [1] "a is less than 20"
## [1] "Because value of a is now 16"
## [1] "a is less than 20"
## [1] "Because value of a is now 17"
## [1] "a is less than 20"
## [1] "Because value of a is now 18"
## [1] "a is less than 20"
## [1] "Because value of a is now 19"
Look carefully, though break
is applied in the if-else
statement, it affects on the loop that it is part of.
6.2.2 for loop
Say, you have a vector b <- c("a","b","c","d","e")
and you want to read the elements iteratively and then print them, what you can do is -
b <- c("a","b","c","d","e")
# looping through the contents of a vector directly
for(i in b){
print(i)
}
## [1] "a"
## [1] "b"
## [1] "c"
## [1] "d"
## [1] "e"
## [1] "a"
## [1] "b"
## [1] "c"
## [1] "d"
## [1] "e"
Looping through sequential numbers (in some programming language you have to define the initial value and the increment in this line) -
## [1] 1
## [1] 2
## [1] 3
## [1] 4
## [1] 5
For a bit better understanding -
## [1] "The current value of i is 1"
## [1] "The current value of i is 2"
## [1] "The current value of i is 3"
## [1] "The current value of i is 4"
## [1] "The current value of i is 5"
Look carefully at this piece of code to understand the nested loop and the change of the values of i
and j
## [1] "Now i is 1 and j is 6"
## [1] "Now i is 1 and j is 7"
## [1] "Now i is 1 and j is 8"
## [1] "Now i is 1 and j is 9"
## [1] "Now i is 1 and j is 10"
## [1] "Now i is 2 and j is 6"
## [1] "Now i is 2 and j is 7"
## [1] "Now i is 2 and j is 8"
## [1] "Now i is 2 and j is 9"
## [1] "Now i is 2 and j is 10"
## [1] "Now i is 3 and j is 6"
## [1] "Now i is 3 and j is 7"
## [1] "Now i is 3 and j is 8"
## [1] "Now i is 3 and j is 9"
## [1] "Now i is 3 and j is 10"
## [1] "Now i is 4 and j is 6"
## [1] "Now i is 4 and j is 7"
## [1] "Now i is 4 and j is 8"
## [1] "Now i is 4 and j is 9"
## [1] "Now i is 4 and j is 10"
## [1] "Now i is 5 and j is 6"
## [1] "Now i is 5 and j is 7"
## [1] "Now i is 5 and j is 8"
## [1] "Now i is 5 and j is 9"
## [1] "Now i is 5 and j is 10"
Or, the following code snippet -
## [1] 1
## [1] 7
## [1] 13
## [1] 2
## [1] 8
## [1] 14
## [1] 3
## [1] 9
## [1] 15
## [1] 4
## [1] 10
## [1] 16
## [1] 5
## [1] 11
## [1] 17
## [1] 6
## [1] 12
## [1] 18
6.3 User defined functions
By now, we have already seen some functions, like - print()
and mean()
that are built-in to your R environment. Sometimes they are not enough, you may need to perform some extra mathematical operations. Here comes the cool feature of R programming language, you can define your own functions. The basic structure of a fucntion is -
function_name <- function(input1, ..., inputN=default_value){
code to execute
return() # if any
}
6.3.1 Function without return()
Let’s first look at a very simple function. This does not take any input as prerequisit and will not return any value -
printOnly <- function(){
print("hi")
}
printOnly() # remember to put a parentheses afterwards to call the function.
## [1] "hi"
Now, define the same function with an input as argument (with a default value as well) -
## [1] "hi David"
6.3.2 Function with a return()
So far, we have been, basically, printing something with the function. We actually want is to return the result. Now we will look into a function that returns a result and you can use it for later usage if you save it in a variable. Say, we want to add two numbers by a user defined function called add
-
## [1] 35
Now, we can assign the output of the function to a variable (say, result
) -
Check that nothing is printed on the console as it returned some value and the value is now saved in the variable result
. If you type in result
in the console, now you can see the value.
6.3.3 Scoping
There is another interesting feature you should keep in mind while scripting and defining your own function(s) - The scoping. The value of a variable can change inside or outside of your function depending of it’s position of definition and under what scope (either global or local) you call it -
name <- "My name is David" # global scope
loc <- "I live in Edinburgh" # global scope
stay <- function(loc){
print(name)
loc <- "I live in London" # redefining locally and work within the scope of the function
print(loc)
}
stay(loc)
## [1] "My name is David"
## [1] "I live in London"
## [1] "I live in Edinburgh"