R Operators — Arithmetic, Comparison, Logical, and More

R BasicsOperatorsFree Lesson

Advertisement

R Operators

Learning Objectives

By the end of this tutorial, you will be able to:

  • Use all arithmetic operators including modulo and integer division
  • Apply comparison operators to create logical vectors
  • Combine conditions with logical operators
  • Master assignment operators including the pipe operator
  • Understand operator precedence in R
  • Apply element-wise vs. matrix operations correctly

Arithmetic Operators

OperatorDescriptionExampleResult
+Addition5 + 38
-Subtraction5 - 32
*Multiplication5 * 315
/Division10 / 33.333333
^ or **Exponentiation2^101024
%%Modulo (remainder)10 %% 31
%/%Integer division10 %/% 33
# Basic arithmetic
10 + 5        # [1] 15
10 - 5        # [1] 5
10 * 5        # [1] 50
10 / 5        # [1] 2

# Exponentiation
2^10          # [1] 1024
9^0.5         # [1] 3 (square root)

# Modulo (remainder)
10 %% 3       # [1] 1
15 %% 5       # [1] 0

# Integer division
10 %/% 3      # [1] 3
15 %/% 5      # [1] 3

Vectorized Arithmetic

R operations work element-wise on vectors:

x <- c(1, 2, 3, 4, 5)
y <- c(10, 20, 30, 40, 50)

x + y          # [1] 11 22 33 44 55
x * y          # [1] 10 40 90 160 250
x^2            # [1]  1  4  9 16 25

# Scalar recycling
x + 100        # [1] 101 102 103 104 105

# Element-wise vs matrix multiplication
a <- c(1, 2, 3)
b <- c(4, 5, 6)

a * b          # [1]  4 10 18 (element-wise)
a %*% b        # [1] 32 (matrix dot product)

Comparison Operators

OperatorDescriptionExampleResult
==Equal5 == 5TRUE
!=Not equal5 != 3TRUE
>Greater than5 > 3TRUE
<Less than5 < 3FALSE
>=Greater than or equal5 >= 5TRUE
<=Less than or equal5 <= 3FALSE
# Basic comparisons
5 == 5        # [1] TRUE
5 != 3        # [1] TRUE
5 > 3         # [1] TRUE
5 < 3         # [1] FALSE
5 >= 5        # [1] TRUE
5 <= 3        # [1] FALSE

# Vectorized comparisons
x <- c(1, 2, 3, 4, 5)
x > 3         # [1] FALSE FALSE FALSE  TRUE  TRUE
x == 3        # [1] FALSE FALSE  TRUE FALSE FALSE

# Comparing vectors
a <- c(1, 2, 3, 4, 5)
b <- c(5, 4, 3, 2, 1)
a == b        # [1] FALSE FALSE  TRUE FALSE FALSE
a > b         # [1] FALSE FALSE FALSE  TRUE  TRUE

Floating-Point Comparison

# Warning: floating-point precision issues
0.1 + 0.2 == 0.3
# [1] FALSE

# Solution: use all.equal()
all.equal(0.1 + 0.2, 0.3)
# [1] TRUE

# Or use tolerance
abs(0.1 + 0.2 - 0.3) < 1e-10
# [1] TRUE

Logical Operators

Element-Wise Operators

OperatorDescriptionExampleResult
&ANDTRUE & FALSEFALSE
|ORTRUE | FALSETRUE
!NOT!TRUEFALSE
xor()Exclusive ORxor(TRUE, FALSE)TRUE
# Logical operations
TRUE & FALSE    # [1] FALSE
TRUE | FALSE    # [1] TRUE
!TRUE           # [1] FALSE
xor(TRUE, FALSE)# [1] TRUE
xor(TRUE, TRUE) # [1] FALSE

# Vectorized logical operations
x <- c(TRUE, TRUE, FALSE, FALSE)
y <- c(TRUE, FALSE, TRUE, FALSE)

x & y           # [1]  TRUE FALSE FALSE FALSE
x | y           # [1]  TRUE  TRUE  TRUE FALSE
!x              # [1] FALSE FALSE  TRUE  TRUE

# Practical example
scores <- c(85, 92, 78, 95, 88)
passed <- scores >= 80
passed
# [1]  TRUE  TRUE FALSE  TRUE  TRUE

sum(passed)     # [1] 4 (count of TRUE)
mean(passed)    # [1] 0.8 (proportion TRUE)

Short-Circuit Operators

&& and || evaluate only the first element of each vector:

# && and || are scalar (short-circuit)
TRUE && FALSE   # [1] FALSE
TRUE || FALSE   # [1] TRUE

# Short-circuit evaluation
x <- NULL
# This would error: is.null(x) && length(x) == 0
# But short-circuit saves us:
is.null(x) && length(x) == 0  # [1] TRUE (doesn't evaluate second part)

# Useful for validation
validate <- function(x) {
  if (is.null(x) || length(x) == 0) {
    cat("Input is empty\n")
    return(invisible(NULL))
  }
  cat("Input has", length(x), "elements\n")
}

validate(NULL)   # Input is empty
validate(1:5)    # Input has 5 elements

Which, Any, All

x <- c(1, 5, 3, 8, 2, 9, 4)

# which() — indices where condition is TRUE
which(x > 5)
# [1] 4 6

# any() — is at least one TRUE?
any(x > 5)      # [1] TRUE
any(x > 10)     # [1] FALSE

# all() — are all TRUE?
all(x > 0)      # [1] TRUE
all(x > 5)      # [1] FALSE

Assignment Operators

OperatorDescriptionExample
<-Left assignment (preferred)x <- 5
->Right assignment5 -> x
=Assignment (less common)x = 5
<<-Global assignmentx <<- 5
= (in call)Named argumentmean(x = c(1,2,3))
# Standard assignment
x <- 10

# Right assignment (rare)
10 -> x

# Global assignment (modifies parent environment)
f <- function() {
  x <<- 99  # Modifies global x
}
f()
x  # [1] 99

Pipe Operators

Base Pipe |> (R 4.1+)

# Without pipe
round(sqrt(mean(c(1, 2, 3, 4, 5))), 2)

# With pipe
c(1, 2, 3, 4, 5) |>
  mean() |>
  sqrt() |>
  round(2)

# Pipe with placeholder
"hello world" |>
  toupper() |>
  paste("!", sep = "")

# Using _ as placeholder (R 4.2+)
1:10 |>
  mean() |>
  round(_, 2)

Magrittr Pipe %>% (tidyverse)

library(magrittr)

# Same as |> but available in older R versions
c(1, 2, 3, 4, 5) %>%
  mean() %>%
  sqrt() %>%
  round(2)

# With placeholder .
"hello world" %>%
  toupper() %>%
  paste("!", sep = "")

Pipe Comparison

Feature|>%>%
Base RYes (4.1+)No (needs magrittr)
Placeholder_ (4.2+).
Function extraction\(x) x + 1list(..1)
SpeedSlightly fasterSlightly slower

Matrix Operators

OperatorDescriptionExample
%*%Matrix multiplicationA %*% B
t()Transposet(A)
solve()Inversesolve(A)
%o%Outer productx %o% y
%in%Match operator"a" %in% c("a","b")
# Matrix multiplication
A <- matrix(1:4, nrow = 2)
B <- matrix(5:8, nrow = 2)

A %*% B
#      [,1] [,2]
# [1,]   19   22
# [2,]   43   50

# Transpose
t(A)
#      [,1] [,2]
# [1,]    1    3
# [2,]    2    4

# Inverse
M <- matrix(c(1, 2, 3, 4), nrow = 2)
solve(M)
#      [,1] [,2]
# [1,]   -2  1.5
# [2,]    1 -0.5

# Outer product
x <- 1:3
y <- 1:4
x %o% y
#      [,1] [,2] [,3] [,4]
# [1,]    1    2    3    4
# [2,]    2    4    6    8
# [3,]    3    6    9   12

# Membership
"a" %in% c("a", "b", "c")  # [1] TRUE
"z" %in% c("a", "b", "c")  # [1] FALSE

Operator Precedence

R evaluates operators in a specific order (highest to lowest):

PrecedenceOperatorDescription
1$, @, [, [[Component extraction
2^Exponentiation
3-, +Unary minus/plus
4:Sequence generation
5%%, %/%Modulo, integer division
6*, /Multiplication, division
7+, -Addition, subtraction
8<, >, <=, >=, ==, !=Comparison
9!Logical NOT
10&, &&AND
11|, ||OR
12~Formula
13->, ->>Right assignment
14<-, <<-Left assignment
15=Assignment
# Precedence matters
2 + 3 * 4      # [1] 14 (not 20)
(2 + 3) * 4    # [1] 20

# Exponentiation is right-associative
2^3^2           # [1] 512 (2^(3^2) = 2^9)
(2^3)^2         # [1] 64

# Use parentheses for clarity
result <- (x + y) * (a - b)

Type Conversion in Operations

# Logical → Numeric
TRUE + TRUE     # [1] 2
TRUE * 10       # [1] 10

# Numeric → Character
"Value: " + 42
# Warning: argument is not interpretable as numeric
# [1] NA

# Better approach
paste("Value:", 42)  # [1] "Value: 42"

# Character → Numeric (with warning)
as.numeric("42")     # [1] 42
as.numeric("hello")  # [1] NA with warning

# Integer vs Double
x <- 42L
y <- 42
typeof(x + y)  # [1] "double" (promoted)

Practice Exercises

Exercise 1: Vector Operations

Given x <- c(1, 2, 3, 4, 5, 6, 7, 8, 9, 10):

  1. Find all elements greater than 5
  2. Count how many elements are even
  3. Calculate the sum of elements between 3 and 7 (inclusive)
  4. Find indices of elements divisible by 3

Solution

x <- c(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)

# 1. Elements greater than 5
x[x > 5]
# [1]  6  7  8  9 10

# 2. Count even elements
sum(x %% 2 == 0)
# [1] 5

# 3. Sum of elements between 3 and 7
sum(x[x >= 3 & x <= 7])
# [1] 25

# 4. Indices divisible by 3
which(x %% 3 == 0)
# [1] 3 6 9

Exercise 2: Logical Conditions

Write expressions that check if a number is:

  1. Positive
  2. Between 0 and 100 (inclusive)
  3. Divisible by both 3 and 5

Solution

is_positive <- function(x) {
  x > 0
}

in_range <- function(x) {
  x >= 0 & x <= 100
}

divisible_by_3_and_5 <- function(x) {
  x %% 3 == 0 & x %% 5 == 0
}

# Test
is_positive(5)           # [1] TRUE
in_range(50)             # [1] TRUE
divisible_by_3_and_5(15) # [1] TRUE
divisible_by_3_and_5(10) # [1] FALSE

Key Takeaways

  • R is vectorized — operators work element-wise on vectors
  • Use %% for modulo, %/% for integer division
  • Comparison operators return logical vectors (TRUE/FALSE)
  • &/| are element-wise, &&/|| are scalar (short-circuit)
  • %in% is the membership operator — check if value is in a vector
  • %*% is matrix multiplication — not * which is element-wise
  • |> is the base pipe — chain operations cleanly
  • Operator precedence matters — use parentheses for clarity
  • Floating-point comparison — use all.equal() instead of ==

Next: Learn about R Strings — text manipulation in R.

Advertisement

Need Expert R Programming Help?

Get personalized tutoring, project support, or professional consulting.

Advertisement