๐Ÿ“˜ Unit 1.3: Operations, Functions, and Flow Control


1. Operators in R

R supports a wide range of operators for performing calculations, comparisons, and logical operations. These are classified as follows:

1.1. Arithmetic Operators

Operator Description Example Result
+ Addition 5 + 3 8
- Subtraction 5 - 3 2
* Multiplication 5 * 3 15
/ Division 6 / 3 2
^ or ** Exponentiation 2^3 8
%% Modulo (remainder) 7 %% 3 1
%/% Integer division 7 %/% 3 2

๐Ÿ“Œ Practical example:

x <- 10
y <- 3
print(x + y)   # 13
print(x %% y)  # 1
print(x^y)     # 1000

1.2. Comparison Operators

Return logical values (TRUE or FALSE).

Operator Description Example Result
== Equal to 5 == 5 TRUE
!= Not equal to 5 != 3 TRUE
> Greater than 5 > 3 TRUE
< Less than 5 < 3 FALSE
>= Greater than or equal 5 >= 5 TRUE
<= Less than or equal 5 <= 3 FALSE

๐Ÿ“Œ Practical example:

a <- 7
b <- 4
print(a > b)   # TRUE
print(a == b)  # FALSE

1.3. Logical Operators

Operate on boolean values.

Operator Description Example Result
& AND (element-wise) c(TRUE, FALSE) & c(TRUE, TRUE) c(TRUE, FALSE)
&& AND (first element only) TRUE && FALSE FALSE
| OR (element-wise) c(TRUE, FALSE) \| c(FALSE, FALSE) c(TRUE, FALSE)
|| OR (first element only) TRUE \|\| FALSE TRUE
! NOT (negation) !TRUE FALSE

๐Ÿ“Œ Key difference:

  • & and | work vectorially (compare all elements).
  • && and || evaluate only the first element (useful in conditionals).

๐Ÿ“Œ Practical example:

vec1 <- c(TRUE, FALSE, TRUE)
vec2 <- c(FALSE, TRUE, TRUE)
print(vec1 & vec2)   # FALSE FALSE TRUE
print(vec1 && vec2)  # FALSE (evaluates only first element)

print(!vec1)         # FALSE TRUE FALSE

2. Indexing Data Structures

Allows you to access or modify specific elements of vectors, matrices, lists, or data frames.

2.1. Vector Indexing

numbers <- c(10, 20, 30, 40, 50)

# By position
numbers[1]        # 10
numbers[c(1,3)]   # 10 30
numbers[2:4]      # 20 30 40

# By logical condition
numbers[numbers > 25]       # 30 40 50
numbers[numbers %% 20 == 0] # 20 40

# By name (if named)
named_vec <- c("a"=10, "b"=20, "c"=30)
named_vec["b"]     # b: 20
named_vec[c("a","c")] # a:10, c:30

2.2. Matrix Indexing

mat <- matrix(1:9, nrow=3, ncol=3)
#     [,1] [,2] [,3]
# [1,]    1    4    7
# [2,]    2    5    8
# [3,]    3    6    9

mat[1, 2]        # 4 (row 1, column 2)
mat[1, ]         # 1 4 7 (entire row 1)
mat[, 2]         # 4 5 6 (entire column 2)
mat[c(1,3), 2:3] # rows 1 and 3, columns 2 and 3

2.3. List Indexing

my_list <- list(
  name = "Ana",
  age = 25,
  grades = c(8, 9, 7)
)

my_list[["name"]]   # "Ana" (returns the value)
my_list$name        # "Ana" (equivalent)
my_list[1]          # list containing one element: "Ana" (returns sublist)

my_list[["grades"]][2] # 9 (second grade)

2.4. Data Frame Indexing

df <- data.frame(
  name = c("Ana", "Luis", "Clara"),
  age = c(25, 30, 28),
  salary = c(30000, 45000, 38000)
)

df[1, 2]           # 25 (row 1, column 2)
df[ , "name"]      # Ana Luis Clara
df[df$age > 28, ]  # Rows where age > 28
df[c("name", "salary")] # Subset of columns

3. Control Structures

Allow you to control the programโ€™s execution flow.

3.1. Conditionals (if, else if, else)

Syntax:

if (condition) {
  # code if condition is TRUE
} else if (another_condition) {
  # code if another_condition is TRUE
} else {
  # code if no condition is met
}

๐Ÿ“Œ Example:

grade <- 85

if (grade >= 90) {
  print("Excellent")
} else if (grade >= 70) {
  print("Approved")
} else {
  print("Failed")
}
# Output: "Approved"

๐Ÿ“Œ Vectorized version (avoid loops):

grades <- c(95, 85, 60, 75)
categories <- ifelse(grades >= 90, "Excellent",
              ifelse(grades >= 70, "Approved", "Failed"))
print(categories)
# [1] "Excellent" "Approved"  "Failed" "Approved"

3.2. Loops

for Loop

Syntax:

for (variable in sequence) {
  # code to repeat
}

๐Ÿ“Œ Example:

for (i in 1:5) {
  print(paste("Iteration", i))
}

# Output:
# [1] "Iteration 1"
# [1] "Iteration 2"
# ... up to 5

๐Ÿ“Œ Iterating over a vector:

colors <- c("red", "green", "blue")
for (color in colors) {
  print(color)
}

while Loop

Syntax:

while (condition) {
  # code to repeat while condition is TRUE
}

๐Ÿ“Œ Example:

counter <- 1
while (counter <= 3) {
  print(paste("Counter:", counter))
  counter <- counter + 1
}

repeat Loop (and break)

Syntax:

repeat {
  # code to repeat indefinitely
  if (condition) break  # exit the loop
}

๐Ÿ“Œ Example:

counter <- 1
repeat {
  print(paste("Repetition", counter))
  counter <- counter + 1
  if (counter > 3) break
}

โš ๏ธ Warning: Avoid dynamically growing objects inside loops (inefficient). Pre-allocate memory.

# โŒ Inefficient
results <- c()
for (i in 1:1000) {
  results <- c(results, i^2)  # grows in each iteration
}

# โœ… Efficient
results <- numeric(1000)  # pre-allocated
for (i in 1:1000) {
  results[i] <- i^2
}

4. Functions in R

Functions allow you to encapsulate reusable code.

4.1. Function Definition

Syntax:

function_name <- function(arg1, arg2 = default_value, ...) {
  # function body
  return(value)  # optional; if omitted, returns last evaluated expression
}

๐Ÿ“Œ Basic example:

greet <- function(name) {
  return(paste("Hello", name))
}

print(greet("Carlos"))
# [1] "Hello Carlos"

๐Ÿ“Œ With default arguments:

power <- function(base, exponent = 2) {
  return(base^exponent)
}

print(power(3))     # 9 (uses exponent=2 by default)
print(power(3, 3))  # 27

๐Ÿ“Œ With variable arguments (...):

sum_all <- function(...) {
  args <- list(...)
  return(sum(unlist(args)))
}

print(sum_all(1, 2, 3, 4))  # 10

4.2. Anonymous Functions

Functions without a name, useful for quick operations.

๐Ÿ“Œ Example:

# Anonymous function to double
double <- function(x) x * 2

# Used in lapply
numbers <- c(1, 2, 3, 4)
results <- lapply(numbers, function(x) x * 2)
print(unlist(results))  # 2 4 6 8

4.3. Higher-Order Functions

Functions that take other functions as arguments.

lapply(): Applies a function to each element of a list or vector, returns a list.

numbers <- 1:5
squares <- lapply(numbers, function(x) x^2)
print(unlist(squares))  # 1 4 9 16 25

sapply(): Same as lapply(), but tries to simplify the result (vector or matrix).

squares <- sapply(numbers, function(x) x^2)
print(squares)  # 1 4 9 16 25 (vector, not list)

vapply(): Like sapply(), but with output type specification (safer and more efficient).

squares <- vapply(numbers, function(x) x^2, FUN.VALUE = numeric(1))
print(squares)  # 1 4 9 16 25

๐Ÿ“Œ Practical example with data frame:

df <- data.frame(a = 1:3, b = 4:6, c = 7:9)

# Apply mean to each column
means <- sapply(df, mean)
print(means)
# a b c 
# 2 5 8

5. Best Practices and Tips

โœ… Vectorization > Loops: Whenever possible, use vectorized operations or functions like *apply() instead of for loops.

โœ… Descriptive names: Use clear names for variables and functions (calculate_mean instead of cm).

โœ… Document functions: Use comments inside functions to explain what they do and what they expect.

โœ… Avoid unnecessary return(): In R, the last evaluated expression is automatically returned.

โœ… Use && and || in conditionals, & and | in vector operations.

โœ… Pre-allocate memory in loops to improve performance.

โœ… Test your functions with edge cases (NA values, empty vectors, etc.).


๐Ÿ“ Practical Exercises

  1. Create a vector with numbers from 1 to 20. Use indexing to extract:

    • Even numbers.
    • Numbers greater than 10.
    • Numbers at odd positions.
  2. Write a function is_even() that takes a number and returns TRUE if it is even, FALSE otherwise.

  3. Use ifelse() to create a vector that classifies ages as "child" (<13), "teenager" (13-19), "adult" (>=20).

  4. Write a for loop that prints the first 10 numbers of the Fibonacci series.

  5. Use sapply() to calculate the length of each word in a character vector: c("R", "programming", "data", "science").


โœ… You have completed Unit 1.3!
You now master operations, indexing, flow control, and functions in R. You are ready to write structured and efficient programs.

Course Info

Course: R-zero-to-hero

Language: EN

Lesson: Module03