Operators in R
Learn arithmetic, comparison, logical, and assignment operators in R, including vectorized operations and the pipe operator, with Docker-ready examples
Operators are the symbols R uses to combine and transform values: adding numbers, comparing quantities, testing logical conditions, and binding results to names. Understanding them is the foundation for writing any expression in R.
What sets R apart from most languages is that nearly every operator is vectorized. When you add two vectors, R adds them element by element and returns a new vector—no explicit loop required. This reflects R’s roots as an array-oriented language for statistics, where you routinely work with whole columns of data at once rather than individual scalars. A “single number” in R is really a numeric vector of length one, so the same operators that work on one value work on thousands.
This tutorial covers arithmetic, comparison, logical, and assignment operators, plus R-specific operators like the modulo (%%), integer division (%/%), sequence (:), membership (%in%), and the native pipe (|>). Each example is a complete script you can run with Docker.
Arithmetic Operators
R provides the standard arithmetic operators, plus a few that are especially handy for statistical work. Note that R uses %% for modulo and %/% for integer (floor) division, and ^ for exponentiation.
Create a file named operators_arithmetic.R:
| |
Unlike many languages, dividing two integers with / in R always produces a decimal result (3.4), never a truncated integer. When you specifically want the whole-number quotient, use %/%.
Vectorized Operators
This is where R shines. Operators apply to entire vectors element by element. When operands have different lengths, R recycles the shorter one—this is why multiplying a vector by a single number scales every element.
Create a file named operators_vectorized.R:
| |
There is no loop here. R handles the iteration internally, which is both more concise and far faster than writing an explicit loop in interpreted R code. This vectorized style is the idiomatic way to compute in R—reach for it before reaching for a for loop.
Comparison and Logical Operators
Comparison operators return logical values (TRUE/FALSE), and they are vectorized too. R distinguishes between the vectorized logical operators & and | (which compare element by element) and the scalar operators && and || (which expect a single value and short-circuit). In R 4.3 and later, using && or || on a vector of length greater than one is an error, so use &/| for vectors.
Create a file named operators_comparison.R:
| |
Logical vectors like these are the engine behind R’s filtering: you can use a result such as vec > 5 to subset data, count matches with sum(), or drive conditional logic across an entire dataset at once.
Assignment and the Pipe Operator
R is unusual in offering several assignment operators. The leftward arrow <- is the idiomatic choice and the one you’ll see in most R code. The equals sign = also assigns, and R even supports a rightward arrow ->. R 4.1 introduced the native pipe |>, which passes the result of the left expression as the first argument to the function on the right—making data transformations read top to bottom.
Create a file named operators_assignment.R:
| |
The pipe reads naturally: take nums, take the square root of each element (2, 3, 4, 5), sum them (14), then print. Without the pipe you would write the nested form print(sum(sqrt(nums))), which has to be read inside-out.
Operator Precedence and Special Operators
Operators follow a defined precedence, and R has a few special operators worth knowing. Exponentiation (^) is right-associative, the colon (:) builds integer sequences, and %in% tests membership.
Create a file named operators_precedence.R:
| |
When in doubt about precedence, add parentheses—they make intent explicit and cost nothing. The : and %in% operators are everywhere in real R code: : for generating index ranges and %in% for checking whether values belong to a set.
Running with Docker
Docker gives you a consistent R 4.4.2 environment without a local install. Pull the official image once, then run each script with Rscript.
| |
Expected Output
Running operators_arithmetic.R:
a + b = 22
a - b = 12
a * b = 85
a / b = 3.4
a %% b = 2
a %/% b = 3
a ^ b = 1419857
Running operators_vectorized.R:
[1] 11 22 33 44
[1] 2 4 6 8
[1] 10 10 10 10
[1] 1 4 9 16
Running operators_comparison.R:
[1] TRUE
[1] FALSE
[1] TRUE
[1] FALSE
[1] TRUE
[1] FALSE
[1] FALSE FALSE TRUE TRUE
[1] FALSE TRUE TRUE FALSE
Running operators_assignment.R:
z = 10
w = 20
result = 5
[1] 14
Running operators_precedence.R:
[1] 14
[1] 20
[1] 512
[1] 1 2 3 4 5
[1] TRUE
[1] FALSE
Key Concepts
- Operators are vectorized: arithmetic, comparison, and logical operators apply element by element across entire vectors—the idiomatic alternative to explicit loops in R.
- Recycling: when operands differ in length, R repeats the shorter one to match the longer, which is why
vec * 2scales every element. - Division vs. integer division:
/always returns a double, while%/%gives the floor quotient and%%gives the remainder. <-is the idiomatic assignment: though=and->also work, the leftward arrow is the R community standard.&/|vs.&&/||: the single-character forms are vectorized; the double forms expect a single value and short-circuit, and error on long vectors in modern R.^is right-associative:2 ^ 3 ^ 2evaluates as2 ^ (3 ^ 2), not(2 ^ 3) ^ 2.- Special operators:
:builds integer sequences and%in%tests set membership—both appear constantly in real R code. - The native pipe
|>(R 4.1+) chains operations left to right, replacing deeply nested function calls with a readable top-to-bottom flow.
Comments
Loading comments...
Leave a Comment