![](images/banner.png)
Chapter13 Conditional Programming
One of the main constructs of programming is conditional expressions. The simple idea behind this is to perform certain operations or execute operations in a particular way depending on certain conditions. Conditions are just expressions that always return a boolean value, that is, either TRUE
or FALSE
.
The classic example is the umbrella scenario: imagine you’re writing code for a video game and you’ve written a function to make your character take and open the umbrella. Clearly, to make everything believable, you should execute this operation only when needed, that is, when it’s raining. In programming terms, you must first check a certain condition (the rain) and then execute (or not execute) a series of operations accordingly.
13.1 Conditional Structures
There are several possibilities in R, but the logic of executing operations only when certain conditions are met is always the same. Figure 13.1 represents the general structure of a conditional control flow.
13.1.1 if
!['if' chart](images/if_chart.png)
Figure 13.1: ‘if’ chart
‘if’ Structure
Per scrivere la struttura condizionale della Figura 13.1 si usa la seguente sintassi in R:
Example
- Single ‘if’
my_function = function(value){
if(value > 0){
cat("The value is greater than 0\n")
}
cat("End of function\n")
}
my_function(5)
## The value is greater than 0
## End of function
my_function(-5)
## End of function
- Multiple ‘if’
my_function = function(value){
if(value > 0){
cat("The value is greater than 0\n")
}
if(value > 10){
cat("The value is greater than 10\n")
}
cat("End of function\n")
}
my_function(5)
## The value is greater than 0
## End of function
my_function(15)
## The value is greater than 0
## The value is greater than 10
## End of function
my_function(-5)
## End of function
13.1.2 if…else
Using a simple if
might not be sufficient in some situations. This is because an if
can be seen as a temporary deviation from the main script (clearly illustrated in Figure 13.1) that is taken only if a condition is true; otherwise, the script continues. If you want a more “symmetric” structure, you can execute some operations if the condition is true (if
) and others for all other scenarios (else
). Figure 13.2 clearly shows this different structure in the flow.
!['if...else' chart](images/ifelse_chart.png)
Figure 13.2: ‘if…else’ chart
Example
- single ‘if…else’
my_function = function(value){
if(value >= 0){
cat("The value is greater than or equal to 0\n")
} else {
cat("The value is less than 0\n")
}
cat("End of function\n")
}
my_function(5)
## The value is greater than or equal to 0
## End of function
my_function(-5)
## The value is less than 0
## End of function
- multiple ‘if…else’
my_function = function(value){
if(value > 0){
cat("The value is greater than 0\n")
} else if (value > 10){
cat("The value is greater than 10\n")
} else {
cat("The value is less than or equal to 0\n")
}
cat("End of function\n")
}
my_function(5)
## The value is greater than 0
## End of function
my_function(15)
## The value is greater than 0
## End of function
my_function(-5)
## The value is less than or equal to 0
## End of function
It is important to understand the difference between using multiple if
and else if
compared to using a simple else
. If you want to specify a finite set of alternatives, the best and clearest choice is to use else if
because, unlike else
, it requires you to specify the condition. If, on the other hand, you’re only interested in certain conditions while applying the same operation to everything else, you can conclude your flow with an else
.
13.1.3 Nested
In addition to chaining a series of if
and else if
, you can nest one or more if
inside another. This allows you to check conditions that depend on the previous check and thus cannot be executed in series.
![Nested 'if'](images/ifnested.png)
Figure 13.3: Nested ‘if’
Example
my_function = function(value){
if(value > 0){
if(value > 10) {
cat("The value is greater than 10\n")
} else {
cat("The value is greater than 0\n")
}
} else {
cat("The value is less than or equal to 0\n")
}
cat("End of function\n")
}
my_function(5)
## The value is greater than 0
## End of function
my_function(15)
## The value is greater than 10
## End of function
my_function(-5)
## The value is less than or equal to 0
## End of function
Exercises
Complete the following exercises:
- Define a function to assign a grade based on the percentage of correct answers (score) using the following criteria:
- score < .55 - insufficient
- .55 <= score < .65 - sufficient
- .65 <= score < .75 - good
- .75 <= score < .85 - very good
- .85 <= score - excellent
- Define a function that determines if a number is even or odd.
- Define a function that determines if a number is a multiple of 3, 4, or 5.
- Define a function to calculate the monthly salary considering overtime, which is paid 1.5 times the normal hourly wage. Use the parameters: hours worked in the month, hourly wage, and the work hour threshold beyond which overtime is counted.
13.2 Other Conditional Operators
13.2.1 switch
The switch
operator is a useful alternative when we want to execute a portion of code conditionally on input without using a series of if
.
switch
structure
In this case, if the input value (my_value
) matches one of the cases considered (for example case1
), the corresponding code (action1
) is executed.
There are a few rules to consider when using a switch
statement:
- If the input value is a string, R will look for a match like
input == argument
. - If more than one match is found, the first one is used.
- There’s no option to insert a default value.
- If no match is found,
NULL
is returned. However, by inserting acase
without a corresponding value, it will be used instead ofNULL
.
13.2.2 ifelse
The if
, else
, and else if
statements work only for a single value. In other words, you can’t test the same condition on a series of elements. In the next chapter, we will discuss iterative programming, which allows you to repeat a series of operations. However, using the ifelse()
function, you can implement a vectorized version of conditional operations. The structure is as follows:
Where:
test
is the condition to evaluate, corresponding to what was previously between parentheses inif(test){...}
.yes
is the code executed if the condition isTRUE
.no
is the code executed if the condition isFALSE
.
Example
Imagine we have a vector of numbers representing ages, and we want to execute something based on whether the age is greater than or less than 18 years, for example, simply displaying “adult” or “minor”. Using a simple if
, we see:
age = c(18, 19, 11, 10, 23, 55, 33, 26, 10)
if(age < 18){
print("Minor")
}else{
print("Adult")
}
## Error in if (age < 18) {: the condition has length > 1
An error is incurred because age
is not a single value, and therefore only the first value is used. This demonstrates that if
doesn’t work on a list of elements. Instead, using ifelse
:
age = c(18, 19, 11, 10, 23, 55, 33, 26, 10)
ifelse(age < 18, yes = print("Minor"), no = print("Adult"))
## [1] "Minor"
## [1] "Adult"
## [1] "Adult" "Adult" "Minor" "Minor" "Adult" "Adult" "Adult" "Adult" "Minor"
In this case, the idea is to execute the previous code for each value in our input vector. This is possible because the < operation is vectorized.