R Operators
R groups its operators into a few broad categories: arithmetic operators (+, -, *, /, ^, %%, %/%) for math, relational operators (==, !=, <, >, <=, >=) for comparisons, logical operators (&, |, !, &&, ||) for combining boolean conditions, the assignment operator (<-) covered elsewhere, and special operators like %in% for membership testing and the native pipe |> for chaining calls. A defining trait of R is that most of these operators are vectorized by default, meaning they apply element-by-element across an entire vector without writing an explicit loop.
Cricket analogy: It's like an entire batting order facing the same delivery type simultaneously in a simulation rather than one batter at a time — R's vectorized + applies to every element of a run-total vector in one operation, no loop needed.
Arithmetic Operators
R's arithmetic operators cover the expected +, -, *, /, and ^ (exponentiation), plus two operators unfamiliar to programmers from other languages: %% for modulo (the remainder after division, e.g. 17 %% 5 returns 2) and %/% for integer division (e.g. 17 %/% 5 returns 3). Because arithmetic operators are vectorized, c(1, 2, 3) * 2 returns c(2, 4, 6) without a loop, and when two vectors of different lengths are combined, R applies 'recycling,' repeating the shorter vector to match the longer one, which is convenient but can silently mask a length mismatch bug.
Cricket analogy: %% is like calculating how many balls are left in the current over after bowling 17 deliveries in 6-ball overs — 17 %% 6 gives 5 balls into the next over, the exact remainder logic modulo captures.
Relational and Logical Operators
Relational operators (==, !=, <, >, <=, >=) compare values and return logical TRUE/FALSE, and like arithmetic operators they are vectorized: c(1, 5, 10) > 4 returns c(FALSE, TRUE, TRUE). Logical operators split into two families with a crucial difference: & and | are vectorized, comparing element-by-element across two vectors, while && and || evaluate only the first element of each side and short-circuit (stopping as soon as the result is determined) — which is why R's if() statements require && or || rather than & or |, since if() needs exactly one TRUE/FALSE value, not a vector of them.
Cricket analogy: Vectorized > is like checking every batter's individual score against 50 at once to flag every half-century in an innings simultaneously, returning a TRUE/FALSE for each — while && is like a single umpire's decision needing just one yes/no answer for a specific delivery.
Special Operators: %in% and the Pipe |>
The %in% operator tests membership, returning TRUE/FALSE for whether each element of the left vector appears anywhere in the right vector — 5 %in% c(1, 3, 5, 7) returns TRUE — and it's vectorized, so c(2, 5) %in% c(1, 3, 5, 7) returns c(FALSE, TRUE). Since R 4.1 (released 2021), base R also ships a native pipe operator |>, which takes the expression on its left and passes it as the first argument to the function on its right, letting you write x |> mean() |> round(2) instead of nesting calls as round(mean(x), 2), which becomes far more readable as a chain grows longer.
Cricket analogy: %in% is like checking whether a specific player's name appears anywhere on a squad list — "Bumrah" %in% squad returns TRUE if he's named, exactly like checking one value's membership in a set.
# Arithmetic (vectorized)
c(10, 20, 30) + 5 # 15 25 35
17 %% 5 # 2 (remainder)
17 %/% 5 # 3 (integer division)
# Relational (vectorized)
scores <- c(45, 82, 91, 38)
scores >= 60 # FALSE TRUE TRUE FALSE
# Logical: vectorized vs scalar short-circuit
c(TRUE, FALSE) & c(TRUE, TRUE) # TRUE FALSE (vectorized)
TRUE && FALSE # FALSE (scalar, for if())
# Membership and the native pipe
5 %in% c(1, 3, 5, 7) # TRUE
c(2, 5) %in% c(1, 3, 5, 7) # FALSE TRUE
c(4, 9, 16, 25) |> sqrt() |> sum() # pipe chain: 2+3+4+5 = 14R's native pipe |> (since R 4.1, 2021) is built into base R and requires no package, unlike the older %>% pipe from the magrittr package (used heavily by tidyverse code written before 2021). Both do essentially the same job, but new code is increasingly written with |> since it needs no library() call.
Using & or | inside an if() condition instead of && or || can cause an error ('the condition has length > 1') or, worse, silently use only the first element without warning in some R versions. Always use && and || for single TRUE/FALSE decisions in if() statements, and reserve & and | for vectorized filtering, e.g. df[df$age > 18 & df$active == TRUE, ].
- R operators fall into arithmetic, relational, logical, assignment, and special categories.
- Most operators are vectorized: they apply element-by-element across a whole vector automatically.
- %% gives the remainder (modulo) and %/% gives integer division — both are less common outside R-like languages.
- Shorter vectors are 'recycled' to match longer ones during vectorized operations, which can hide length-mismatch bugs.
- & and | are vectorized logical operators; && and || short-circuit and evaluate only a single TRUE/FALSE, required inside if().
- %in% tests membership of elements from one vector within another, returning a logical vector.
- The native pipe |> (R 4.1+) passes its left-hand expression as the first argument to the function on its right, avoiding deeply nested calls.
Practice what you learned
1. What does 17 %% 5 evaluate to in R?
2. Why does R require && or || instead of & or | inside an if() condition?
3. What does c(2, 5) %in% c(1, 3, 5, 7) return?
4. What does the native pipe operator |> do?
5. What is 'recycling' in the context of R vectorized operators?
Was this page helpful?
You May Also Like
R Variables and Data Types
How to create variables in R with the assignment operator, the core atomic data types, special values like NA and NULL, and how type coercion works.
Your First R Script
How to write, structure, and run a complete R script covering variables, a custom function, control flow, and output, both inside RStudio and from the command line.
What Is R?
An introduction to R as a statistical programming language: its history, design philosophy, real-world applications, and how it compares to other data tools.
Related Reading
Related Study Notes in Programming
Browse all study notesApache Spark Study Notes
Programming · 30 topics
ProgrammingApache Flink Study Notes
Programming · 30 topics
ProgrammingHadoop Study Notes
Programming · 30 topics
ProgrammingSnowflake Study Notes
Programming · 30 topics
ProgrammingApache Airflow Study Notes
Programming · 30 topics
Programmingdbt (Data Build Tool) Study Notes
Programming · 30 topics