Many functions in R can be written as operators. An operator is a function that takes one or two arguments and can be written without parentheses.
One familiar set of operators is binary operators for arithmetic. R supports arithmetic operations:
> # addition > 1 + 19 [1] 20 > # multiplication > 5 * 4 [1] 20
R also includes notation for other mathematical operations, including moduli, exponents, and integer division:
> # modulus > 41 %% 21 [1] 20? > # exponents > 20 ^ 1 [1] 20 > # integer division > 21 %/% 2 [1] 10
You can define your own binary operators. User-defined binary
operators consist of a string of characters between two % characters. To
do this, create a function of two variables and assign it to an
appropriate symbol. For example, let’s define an operator %myop%
that doubles each operand and then adds
them together:
> `%myop%` <- function(a, b) {2*a + 2*b} > 1 %myop% 1 [1] 4 > 1 %myop% 2 [1] 6
Some language constructs are also binary operators. For example, assignment, indexing, and function calls are binary operators:[19]
> # assignment is a binary operator > # the left side is a symbol, the right is a value > x <- c(1, 2, 3, 4, 5) > # indexing is a binary operator too > # the left side is a symbol, the right is an index > x[3] [1] 3 > # a function call is also a binary operator > # the left side is a symbol pointing to the function argument > # the right side are the arguments > max(1, 2) [1] 2
There are also unary operators that take only one variable. Here are two familiar examples:
> # negation is a unary operator > -7 [1] -7 > # ? (for help) is also a unary operator > ?`?`
You may remember from high school math that you always evaluate mathematical expressions in a certain order. For example, when you evaluate the expression 1 + 2 • 5, you first multiply 2 and 5 and then add 1. The same thing is true in computer languages like R. When you enter an expression in R, the R interpreter will always evaluate some expressions first.
In order to resolve ambiguity, operators in R are always interpreted in the same order. Here is a summary of the precedence rules:
Function calls and grouping expressions
Index and lookup operators
Arithmetic
Comparison
Formulas
Assignment
Help
Table 6-1 shows a complete list of operators in R and their precedence.
Table 6-1. Operator precedence, from the help(syntax) file
Operators (in order of priority) | Description |
---|---|
( { | Function calls and grouping expressions (respectively) |
[ [[ | Indexing |
:: ::: | Access variables in a namespace |
$ @ | Component / slot extraction |
^ | Exponentiation (right to left) |
- + | Unary operators for minus and plus |
: | Sequence operator |
%any% | Special operators |
* / | Multiply, divide |
+ - | Binary operators for add, subtract |
| Ordering and comparison |
! | Negation |
&
&& | And |
| || | Or |
~ | As in formulas |
->
->> | Rightward assignment |
= | Assignment (right to left) |
<-
<<- | Assignment (right to left) |
? | Help (unary and binary) |
For a current list of built-in operators and their precedence, see
the help file for syntax
.
Most assignments that we’ve seen so far simply assign an object to a symbol. For example:
> x <- 1 > y <- list(shoes="loafers", hat="Yankees cap", shirt="white") > z <- function(a, b, c) {a ^ b / c} > v <- c(1, 2, 3, 4, 5, 6, 7, 8)
There is an alternative type of assignment statement in R that acts differently: assignments with a function on the left-hand side of the assignment operator. These statements replace an object with a new object that has slightly different properties. Here are a few examples:
> dim(v) <- c(2, 4) > v[2, 2] <- 10 > formals(z) <- alist(a=1, b=2, c=3)
There is a little bit of magic going on behind the scenes. An assignment statement of the form:
fun
(sym
) <-val
is really syntactic sugar for a function of the form:
`fun
<-`(sym
,val
)
Each of these functions replaces the object associated with
in the
current environment. By convention, sym
refers to a
property of the object represented by fun
. If you write a
method with the name sym
method_name
<-, then R
will allow you to place method_name
on the
left-hand side of an assignment statement.
[19] Don’t be confused by the closing bracket in an indexing
operation or the closing parenthesis in a function call; although this
syntax uses two symbols, both operations are still technically binary
operators. For example, a function call has the form
,
where f
(arguments
)
is a function and f
are the
arguments for the function.arguments