100% Free Forever
AI-Powered Learning
Industry Expert Content
Certificates & Badges
Learn At Your Own Pace
Programming

R Operators

A tour of R's arithmetic, relational, logical, and special operators, including vectorized behavior and common pitfalls like && vs &.

FoundationsBeginner8 min readJul 10, 2026
Analogies

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.

r
# 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 = 14

R'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

Was this page helpful?

Topics covered

#Programming#RProgrammingStudyNotes#ROperators#Operators#Arithmetic#Relational#Logical#StudyNotes#SkillVeris#ExamPrep