10 R: Control flow tools
10.1 Code Blocks: R vs. Python
Different programming languages define code blocks differently:
- Python uses indentation to structure code.
- R uses curly braces
{}
to define code blocks.
You have learned indentation (spaces or tabs) determines the structure of code in Python.
10.1.1 Code blocks in R (Uses {}
)
In R, curly braces {}
define code blocks, and indentation is not required (but recommended for readability).
for (i in 1:5) {
print(i)
}
[1] 1
[1] 2
[1] 3
[1] 4
[1] 5
Another key difference in control flow syntax between Python and R is how conditions are written. In Python, conditions do not require parentheses, whereas in R, they must be enclosed in parentheses.
10.2 TryCatch
When running R code, errors can occur due to unexpected inputs, missing data, or issues with computations. Without proper error handling, an entire execution may be stopped due to an error. The tryCatch
function in R provides a mechanism to handle errors gracefully, allowing execution to continue and custom responses to be provided.
Basic Syntax
tryCatch({
# Code that may generate an error
error = function(e) {
}, # Code to handle errors
warning = function(w) {
}, # Code to handle warnings
finally = {
}, # Code that will always execute
})
NULL
- error: Handles errors that stop execution.
- warning: Handles warnings that don’t necessarily stop execution.
- finally: Executes code regardless of whether an error occurs.
Example: Input an integer from the user. If the user inputs a valid integer, print whether it is a multiple of 3. However, if the user does not input a valid integer, print a message saying that the input is invalid.
<- "3r"
num tryCatch({
<- as.integer(num)
num_int if (num_int %% 3 == 0) {
print("Number is a multiple of 3")
else {
} print("Number is not a multiple of 3")
}error = function(e) {
}, print("Error encountered")
warning = function(w) {
}, print("Warning encountered")
})
[1] "Warning encountered"
The warning block will be triggered, not the error block.
Why
as.integer("3r")
does not generate an error. Instead, it produces a warning and returns NA.- In R, an error occurs when an operation stops execution (e.g., division by zero in integer operations).
- A warning occurs when something unexpected happens, but execution continues (e.g., invalid conversion).
10.3 Control flow tools
Control flow in R relies on comparison operators and logical operators to make decisions based on conditions. These operators are commonly used in conditional statements like if, ifelse(), and loops.
- Comparison operators are used to compare values and return a logical value (
TRUE
orFALSE
). - Logical operators are used to combine multiple conditions in control flow statements.
Like Python, R provides if-else
, for
loops, while
loops, and switch/case
for decision-making and iteration. However, in Python, conditions do not require parentheses, whereas in R, parentheses must enclose the condition.
<- 5
x while (x > 0) { # Parentheses required
print(x)
<- x - 1
x }
[1] 5
[1] 4
[1] 3
[1] 2
[1] 1
10.4 Conditional statements
The if-else if-else
statements can check several conditions, and execute the code corresponding to the condition that is true. Note that there can be as many else if
statements as required.
Example: Assign letter grade based on a student’s final score
<- 75 # Change this value to test different cases
score
if (score >= 90) {
print("Grade: A")
else if (score >= 80) {
} print("Grade: B")
else if (score >= 70) {
} print("Grade: C")
else if (score >= 60) {
} print("Grade: D")
else {
} print("Grade: F")
}
[1] "Grade: C"
10.5 Loops
10.5.1 The :
operator
The :
operator in R is used to generate sequences of integers. It is similar to Python’s range()
function, but with some key differences.
Basic Syntax
start:end
- Generates a sequence of integers from
start
toend
. - Inclusive: Both
start
andend
are included.
Examples
1:5
[1] 1 2 3 4 5
In Python, the equivalent would be list(range(1, 6))
10.5.1.1 Reverse sequence
The :
operator also works in Reverse
# Counting down
5:1
[1] 5 4 3 2 1
10.5.1.2 Using :
with negative numbers
# Counting down
-3:3
[1] -3 -2 -1 0 1 2 3
10.5.1.3 Using :
with Non-integers
If the start or end value is not an integer, R coerces it to an integer.
# The decimal values are truncated to integers before generating the sequence
1.5:5.5
[1] 1.5 2.5 3.5 4.5 5.5
10.5.2 seq()
function
Difference: ``:
only creates sequences with a step size of 1, while seq()
allows custom increments.
# Counting by 2
seq(1, 10, by = 2)
[1] 1 3 5 7 9
Summary
Feature | R (: Operator) |
Python (range() ) |
R (seq() Function ) |
---|---|---|---|
Generates integers | ✅ Yes | ✅ Yes | ✅ Yes |
Inclusive of end? | ✅ Yes | ❌ No (excludes end) | ✅ Yes |
Works in reverse? | ✅ Yes (5:1 ) |
✅ Yes (range(5, 0, -1) ) |
✅ Yes (seq(5, 1, by = -1) ) |
Handles non-integers? | ✅ Converts to integer | ❌ Must be integer | ✅ Supports non-integer steps |
Custom step size? | ❌ No (always 1 ) |
✅ Yes (range(1, 10, 2) ) |
✅ Yes (seq(1, 10, by = 2) ) |
10.5.3 for
loop
The for
loop is used when you need to iterate over a sequence of numbers, vectors, lists, or other iterable objects.
10.5.3.1 Using :
in for
loops
Since :
creates integer sequences, it is commonly used in for
loops.
for (i in 1:5) {
print(i)
}
[1] 1
[1] 2
[1] 3
[1] 4
[1] 5
Example: Print the first \(n\) elements of the Fibonacci sequence, where \(n\) is an integer input by the user, such that \(n>2\). In a fibonacci sequence, each number is the sum of the preceding two numbers, and the sequence starts from \(0,1\). The sequence is as follows:
\(0,1,1,2,3,5,8,13,....\)
<- readline("Enter a number:") n
Enter a number:
<- 10 n
# Define the number of terms
if (n <= 0) {
stop("n must be a positive integer")
}
# Initialize the sequence with the first two Fibonacci numbers
<- 0
n1 <- 1
n2 <- c(n1, n2)
elements
# Generate the Fibonacci sequence iteratively
for (i in 3:n) {
<- n1 + n2 # Compute the next term
n3 <- c(elements, n3) # Append to the sequence
elements
# Shift values for the next iteration
<- n2
n1 <- n3
n2
}
# Print the Fibonacci sequence
print(elements)
[1] 0 1 1 2 3 5 8 13 21 34
cat("These are the first", n, "elements of the Fibonacci series.\n")
These are the first 10 elements of the Fibonacci series.
- The
stop()
function in R is used to terminate execution and display an error message when a certain condition is met. It is often used for error handling to prevent further execution of the script when an invalid input is detected. - The
c()
function in R is used to combine values into a vector. It is one of the most fundamental functions in R, as vectors are the primary data structure. You can think of vectors as being similar to Python lists.
10.5.4 while
loop
The while
loop executes as long as the specified condition evaluates to TRUE
.
Example: Print all the elements of the Fibonacci sequence less than n, where n is an integer input by the user, such that n>2. In a fibonacci sequence, each number is the sum of the preceding two numbers, and the sequence starts from 0,1. The sequence is as follows:
0,1,1,2,3,5,8,13,..
= readline("Enter a number:") n
Enter a number:
= 50 n
# Initialize the sequence with the first number
<- 0
n1 <- 1
n2
# Store the Fibonacci sequence
<- n1
elements
# Generate Fibonacci numbers less than n
while (n2 < n) {
<- c(elements, n2) # Append the next number
elements
# Compute the next Fibonacci number
<- n1 + n2
n3
# Shift values for the next iteration
<- n2
n1 <- n3
n2
}
# Print the Fibonacci sequence
print(elements)
[1] 0 1 1 2 3 5 8 13 21 34
cat("These are all the Fibonacci numbers less than", n, "\n")
These are all the Fibonacci numbers less than 50
10.6 Loop control statements
in R, there are two statements that are commonly used to control the execution of loops by altering their normal flow
10.6.1 break
statement (Loop Termination)
The break
statement is used to immediately exits the loop when certain condition is met. It will stop execution of the loop entirely
For example, suppose we need to keep asking the user to input year of birth and compute the corresponding age, until the user enters 1900 as the year of birth.
# Get current year dynamically
<- as.integer(format(Sys.Date(), "%Y"))
current_year
# Check if running in interactive mode
if (interactive()) {
while (TRUE) {
<- readline("Enter year of birth (1900-present) or 'q' to quit: ")
user_input
if (tolower(user_input) == "q") {
cat("Goodbye!\n")
break
}
<- suppressWarnings(as.integer(user_input))
year
if (is.na(year)) {
cat("Error: Please enter a valid year as a number.\n")
else if (year == 1900) {
} cat("Special year entered. Exiting program.\n")
break
else if (year < 1900) {
} cat("Error: Year must be 1900 or later.\n")
else if (year > current_year) {
} cat("Error: Year cannot be in the future.\n")
else {
} <- current_year - year
age cat(sprintf("Based on birth year %d, age in %d = %d years\n",
year, current_year, age))
}
}else {
} cat("Skipping user input section since Quarto is running in batch mode.\n")
}
10.6.2 next
statement (Skip Iteration, Similar to continue
in Python)
The next
statement is used to skip the current iteration and moves to the next one. It does not exit the loop but skips the rest of the current iteration.
For example, consider the following code:
for (i in 1:10) {
if (i == 5) {
next # Skip iteration when i is 5
}print(i)
}
[1] 1
[1] 2
[1] 3
[1] 4
[1] 6
[1] 7
[1] 8
[1] 9
[1] 10
When the control flow reads the statement next
, it goes back to the beginning of the for
loop, and ignores the lines of code below the statement.
10.6.3 Practice exercise
Write a program that asks the user the question, “How many stars are in the Milky Way (in billions)?”. If the user answers 100, the program should print correct, and stop. However, if the user answers incorrectly, the program should print “incorrect”, and ask them if they want to try again. The program should continue to run until the user answers correctly, or they want to stop trying.
while (TRUE) {
= readline("How many stars are there in the Milky Way (in billions)? ")
answer if (answer == '100') {
print("Correct")
break
else {
} print("Incorrect")
}= readline("Do you want to try again? (Y/N):")
try_again if (try_again == 'Y') {
next
else {
} break
} }
10.7 characters
in R
10.7.1 Basic Definitions
- In Python, strings are defined using either single (
'
) or double ("
) quotes. - In R, character values (strings) are always enclosed in double quotes (
" "
), though single quotes (' '
) also work, But single quotes are normally only used to delimit character constants containing double quotes.
10.7.2 String/Character Length
- In Python, len() is used to count the number of characters.
- In R, nchar() is used.
<- "Hello"
s print(nchar(s))
[1] 5
10.7.3 String Indexing and Slicing
- Python allows direct indexing and slicing using
[]
. - R does not support direct indexing for characters. Instead,
substr()
is used.
<- "Hello"
s print(substr(s, 2, 2)) # Output: "e" (1-based index)
[1] "e"
print(substr(s, 2, 4))
[1] "ell"
Key Difference: Python uses 0-based indexing, while R uses 1-based indexing.
10.7.4 String Concatenation
- Python: Uses
+
for concatenation. - R: Uses
paste()
orpaste0()
.
<- "Hello"
s1 <- "World"
s2 print(paste(s1, s2))
[1] "Hello World"
print(paste0(s1, s2))
[1] "HelloWorld"
10.7.5 Changing Case (Uppercase & Lowercase)
- Python:
s.upper()
ands.lower()
for conversion - R:
toupper(s)
andtolower(s)
<- "Hello"
s print(toupper(s))
[1] "HELLO"
print(tolower(s))
[1] "hello"
10.7.6 Finding Substrings
- Python: Uses
.find()
orin
to check for substrings. - R: Uses
grep()
orgrepl()
.
<- "Hello World"
s print(grepl("World", s))
[1] TRUE
print(grep("World", s))
[1] 1
10.7.7 String Replacement
- Python: Uses
.replace()
. - R: Uses
gsub()
.
10.7.8 String Splitting
- Python: Uses
split()
method in strings to break them into lists - R: Uses
strsplit()
function to split strings into a list of character vectors.
<- "Hello, how are you?"
sentence <- strsplit(sentence, " ") # Split by space
words print(words)
[[1]]
[1] "Hello," "how" "are" "you?"
strsplit()
returns a list, even if applied to a single string. The delimiter is treated as a regex, meaning special characters need to be escaped
# splitting using a comma
<- "apple,banana,grape,orange"
sentence <- strsplit(sentence, ",")
words print(words[[1]])
[1] "apple" "banana" "grape" "orange"
10.7.9 Summary table
Feature | Python (String) | R (Character) |
---|---|---|
Definition | 'Hello' or "Hello" |
"Hello" |
Data Type Check | type("Hello") → str |
class("Hello") → "character" |
Length | len(s) |
nchar(s) |
Indexing | s[1] (0-based) |
substr(s, 2, 2) (1-based) |
Concatenation | s1 + s2 |
paste(s1, s2) or paste0(s1, s2) |
Upper/Lower Case | s.upper(), s.lower() |
toupper(s), tolower(s) |
Finding Substrings | "World" in s , s.find("World") |
grepl("World", s) , grep("World", s) |
Replace Substring | s.replace("old", "new") |
gsub("old", "new", s) |
Splitting | s.split(" ") (default: whitespace) |
strsplit(s, " ") (default: whitespace) |
10.8 Practice exercises
10.8.1 Practice exercise 1
Try converting the following Python string operations into equivalent R code:
s = "Data Science"
print(len(s))
print(s[5:])
print(s.replace("Data", "AI"))
10.8.2 Practice exercise 2
Define a character
and count the number of ts.
<- 'Getting a tatto is not a nice experience'
char_vec #Initializing a variable 'count_t' which will store the number of 't's in the string
<- 0
count_t
#Iterating over the entire length of the string.
#The length of the string is given by the len() function
for (i in 1:nchar(char_vec)) {
if (substr(char_vec, i, i) == 't') {
<- count_t + 1
count_t
}
}print(paste("Number of 't's in the string = ", count_t))
[1] "Number of 't's in the string = 6"
Use strsplit()
to implement this function.
10.8.3 Practice exercise 3
Write a program that prints the number of ’the’s found in sentence
<- "She sells the sea shells on the sea shore during the summer"
sentence <- 0
count for (i in 1:(nchar(sentence) - nchar("the"))) {
if (substr(sentence, i, i + nchar("the") - 1) == "the") {
<- count + 1
count
}
}print(paste("Number of thes in the sentence = ", count))
[1] "Number of thes in the sentence = 3"
Use strsplit()
to implement this function
10.8.4 Practice exercise 4
10.8.4.1 Problem 1
<- "0" my_num
Using my_num
above:
- check if the number is numeric
- convert the number to numeric
10.8.4.2 Problem 2
Define a variable to be your name.
Define a variable to be your favorite number.
Define a variable to be your favorite color.
Print a sentence that reads: “My name is {} and my favorite number is {}”.
Store a variable that checks if your favorite number is less than 10. Print this variable.
Store a variable that checks if your favorite number is even. Print this variable.
Store a variable that checks if your favorite color is “red”. Print this variable.
Convert one of your stored Boolean to a numeric data type. What happens?
Print a statement that returns TRUE if your favorite number is less than 10 and favorite color is NOT red and returns FALSE otherwise.
Print a statement that return TRUE if your favorite number is even or less than 10.
10.8.5 Practice exercise 5
Create an interactive R code block that asks the user to enter their age and ensures the input is a valid integer. The code should handle incorrect inputs and guide the user until they provide a valid response.
Requirements
- The script should continuously prompt the user until they enter a valid integer.
- If the input is not an integer, the script should display an error message and ask again.
- Once a valid integer is entered:
- If the age is 18 or older, display:
"You are an adult."
- If the age is less than 18, display:
"You are a minor."
- If the age is 18 or older, display:
Guidelines & Hints
- Use
readline()
to collect user input. - Convert the input using
as.integer()
and check if it returnsNA
for invalid inputs. - Utilize a loop to ensure the user is repeatedly prompted until they enter a valid integer.
- Provide clear error messages to guide the user.
Example User Interaction
Input | Output |
---|---|
"abc" |
"Please enter a valid integer for age." |
"twenty" |
"Please enter a valid integer for age." |
"18" |
"You are an adult." |
"17" |
"You are a minor." |