You can think of R as like a giant calculator. It has a great capacity for mathematical operations. In this article I’ll look at some of the more basic ones, to give a flavour of what basic arithmetic you can do.
Operators
In the main your arithmetic is going to involve adding up, dividing, subtracting and multiplication. These things are all carried out using basic operators that are familiar to everyone: + – * / and ().
The order of the operators is important. R will evaluate your maths in a set order. multiplication (*) and division (/) are evaluated first. Then addition (+) and subtraction (-). As well as this basic order, things inside parentheses () will be evaluated before anything “outside” the parentheses (still in the */+- order). So, remember this running order when you type your maths e.g.
7 + 4 * 11
[1] 51
(7 + 4) * 11
[1] 121
As well as the basic operators there are some “extras”.
Powers (i.e. exponents) are designated using the caret (^) character. These are evaluated before any of the other operators. For example:
2^2 ; 2^3 ; 2^4
[1] 4
[1] 8
[1] 16
3 * 2^3 + 1
[1] 25
If you want a fractional power, you enclose this in parentheses e.g.
64^(1/2)
[1] 8
64^(-2)
[1] 0.0002441406
A square root is simply a power of 0.5 e.g. x^0.5 but there is a special command sqrt() to deal with this.
x = c(9, 16, 25, 36, 49, 59)
sqrt(x)
[1] 3.000000 4.000000 5.000000 6.000000 7.000000 7.681146
You can use the % symbol to compute modulo (%%) and integer division (%/%) like so:
16 %/% 3
[1] 5
16 %% 3
[1] 1
So, you have 16 ÷ 3 giving 5 and 1 remainder.
Matrix operations
There are a bunch of commands associated with matrix math.
Matrix multiplication
Multiply two matrices using the %*% operator.
## Make some matrices
(x = cbind(1,1:3,c(2,0,1)))
[,1] [,2] [,3]
[1,] 1 1 2
[2,] 1 2 0
[3,] 1 3 1
(y = c(1, 3, 2))
[1] 1 3 2
(y1 = matrix(1:3, nrow = 1))
[,1] [,2] [,3]
[1,] 1 2 3
(z = matrix(3:1, ncol = 1))
[,1]
[1,] 3
[2,] 2
[3,] 1
## Various multiplications
> x %*% y
[,1]
[1,] 8
[2,] 7
[3,] 12
x %*% y1 # Order can be important
Error in x %*% y1 : non-conformable arguments
y1 %*% x
[,1] [,2] [,3]
[1,] 6 14 5
x %*% z
[,1]
[1,] 7
[2,] 7
[3,] 10
z %*% x # Order is important
Error in z %*% x : non-conformable arguments
y %*% y # Matrix multiplication of two vectors
[,1]
[1,] 14
Matrix Cross Products
You can compute the cross product using the %*% operator and the t() command. Alternatively the crossprod() and tcrossprod() commands can do the job:
(x = cbind(1,1:3,c(2,0,1)))
[,1] [,2] [,3]
[1,] 1 1 2
[2,] 1 2 0
[3,] 1 3 1
(y = c(1, 3, 2))
[1] 1 3 2
(y1 = matrix(1:3, nrow = 1))
[,1] [,2] [,3]
[1,] 1 2 3
## Cross products
> crossprod(x, y) # Same as t(x) %*% y
[,1]
[1,] 6
[2,] 13
[3,] 4
crossprod(x, y1) # Gives error as y1 wrong “shape”
Error in crossprod(x, y1) : non-conformable arguments
tcrossprod(x, y1) # Same as x %*% t(y1)
[,1]
[1,] 9
[2,] 5
[3,] 10
Other matrix maths
There are various other commands associated with matrix math. They are not really operators (except %o%) as such but I’ll list them here:
backsolve
forwardsolve |
These commands solve a system of linear equations where the coefficient matrix is upper (“right”, “R”) or lower (“left”, “L”) triangular. |
chol | This command computes the Choleski factorization of a real matrix. The matrix must be symmetric, positive definite. The result returned is the upper triangular factor of the Choleski decomposition, that is, the matrix R such that R’R = x. |
det
determinant |
The determinant command calculates the modulus of the determinant (optionally as a logarithm) and the sign of the determinant. The det command calculates the determinant of a matrix (it is a wrapper for the determinant command). |
diag | Matrix diagonals. This command has several uses; it can extract or replace the diagonal of a matrix. Alternatively, the command can construct a diagonal matrix. |
eigen | Computes eigenvalues and eigenvectors for matrix objects; that is, carries out spectral decomposition. The result is a list containing $values and $vectors. |
outer
%o% |
The outer command calculates the outer product of arrays and matrix objects. The %o% symbol is a convenience wrapper for outer(X, Y, FUN = “*”). |
qr | This command computes the QR decomposition of a matrix. It provides an interface to the techniques used in the LINPACK routine DQRDC or the LAPACK routines DGEQP3 and (for complex matrices) ZGEQP3. The result holds a class attribute “qr”. |
solve | Solves a system of equations. This command solves the equation a %*% x = b for x, where b can be either a vector or a matrix. |
svd | The svd command computes the singular value decomposition of a rectangular matrix. The result is a list containing $d, the singular values of x. If nu > 0 and nv > 0, the result also contains $u and $v, the left singular and right singular vectors of x. |
Logical Operators
Some operators are used to provide a logical result (i.e. TRUE or FALSE).
Logical AND
The & operator is used for the logical AND in an elementwise manner. If you double up the operator && you perform the operation on only the first element
Logical OR
The vertical bar | is used for the logical OR in an elementwise manner. If you double up the operator || you perform the operation on only the first element.
Logical NOT
The ! operator is used for the logical NOT.
Logical Exclusive OR
The command xor(x, y) acts as an exclusive OR operator.
The logical operators work in conjunction with other operators (comparisons) to produce results. So, look at the examples in the next section.
Comparisons
Comparison operators allow you to compare elements. These are often used in conjunction with the logical operators.
== | Equal to. Note that the single = denotes assignment so == is used as a comparison operator. |
!= | Not equal to. |
< | Less than. |
<= | Less than or equal to. |
>= | Greater than or equal to. |
> | Greater than. |
Here are some simple examples:
## Make some vectors
yy = c(2, 3, 6, 5, 3)
zz = c(4, 2, 4, 7, 4)
yy ; zz
[1] 2 3 6 5 3
[1] 4 2 4 7 4
yy > 4 # Elements greater than 4
[1] FALSE FALSE TRUE TRUE FALSE
zz != 4 # Elements not equal to 4
[1] FALSE TRUE FALSE TRUE FALSE
zz == 4 # Elements that are equal to 4
[1] TRUE FALSE TRUE FALSE TRUE
yy > 3 & zz > 4 # Two conditions AND
[1] FALSE FALSE FALSE TRUE FALSE
yy > 3 && zz > 4 # Test first element only
[1] FALSE
yy == 3 | zz == 4 # Two conditions OR
[1] TRUE TRUE TRUE FALSE TRUE
xor(yy > 3, zz > 4) # Exclusive OR
[1] FALSE FALSE TRUE FALSE FALSE
Selection and Matching
The comparison and logical operators are used to obtain TRUE/FALSE results. However, they are not always the best choice for selection. There are times when you are looking for a single logical result but using regular operators either fails, or produces more than one. In these cases, the selection commands are helpful. They aren’t strictly mathematical operators but it is helpful to be aware of them. Additionally the isTRUE() command can “force” a single logical as a result.
Match any item in an object
Use the any() command to return a single TRUE result if any element meets the specified criteria.
Match all items in an object
Use the all() command to return a single TRUE result if all elements meet the specified criteria.
Compare objects
The identical() command compares two items and returns a TRUE if they are exactly equal. The all.equal() command is similar but with a bit more tolerance.
(yy = c(2, 3, 6, 5, 3)) # Make a vector
[1] 2 3 6 5 3
any(yy > 5) # Are any elements > 5?
[1] TRUE
all(yy < 5) # Are all elements < 5?
[1] FALSE
all(yy >= 2) # Are all elements >= 2?
[1] TRUE
## Some simple values
x1 = 0.5 – 0.3
x2 = 0.3 – 0.1
## Are results the same?
x1 == x2
[1] FALSE
## Set tolerance to 0 to show actual difference
all.equal(x1, x2, tolerance = 0)
[1] “Mean relative difference: 1.387779e-16”
## Use default tolerance
all.equal(x1, x2)
[1] TRUE
# Wrap command in isTRUE() for logical
isTRUE(all.equal(x1, x2))
[1] TRUE
isTRUE(all.equal(x1, x2, tolerance = 0))
[1] FALSE
## Character vectors
pp = c(“a”, “f”, “h”, “q”, “r”)
qq = c(“d”, “e”, “x”, “c”, “s”)
rr = pp
# Test for equality
all.equal(pp, qq)
[1] “5 string mismatches”
identical(x1, x2)
[1] FALSE
identical(pp, qq)
[1] FALSE
identical(pp, rr)
[1] TRUE
Note that you can use identical(TRUE, x) in lieu of isTRUE(x), where x is the condition to test.
Selection with non-logical result
You can use the which() command to obtain an “index” instead of a logical result. The command works in conjunction with the comparison and logical operators but returns a result that indicates which elements match your criteria.
yy = c(2, 3, 6, 5, 3)
yy
[1] 2 3 6 5 3
which(yy > 3)
[1] 3 4
which(yy == 3)
[1] 2 5
Complex numbers
Complex numbers are those with “imaginary” parts. You can make complex numbers using the complex() and as.complex() commands, whilst the is.complex() command provides a quick logical test to see if an object has the class “complex”. R has several commands that can deal with complex numbers.
Arg | Returns the argument of an imaginary number. |
Conj | Displays the complex conjugate for a complex number. |
Im | Shows the imaginary part of a complex number. |
Mod | Shows the modulus of a complex number. |
Re | Shows the real part of complex numbers. |
Here are some simple examples:
## Make some complex numbers
z0 = complex(real = 1:8, imaginary = 8:1)
z1 = complex(real = 4, imaginary = 3)
z2 = complex(real = 4, imaginary = 3, argument = 2)
z3 = complex(real = 4, imaginary = 3, modulus = 4, argument = 2)
z0 ; z1 ; z2 ; z3
[1] 1+8i 2+7i 3+6i 4+5i 5+4i 6+3i 7+2i 8+1i
[1] 4+3i
[1] -0.4161468+0.9092974i
[1] -1.664587+3.63719i
## Get the real and imaginary parts of a complex object
Re(z0)
[1] 1 2 3 4 5 6 7 8
Im(z0)
[1] 8 7 6 5 4 3 2 1
## Get the Argument and Modulus
Arg(z1)
[1] 0.6435011
Mod(z1)
[1] 5
## Display the complex conjugate
Conj(z2)
[1] -0.4161468-0.9092974i
## Get the modulus and argument
Mod(z3)
[1] 4
Arg(z3)
[1] 2
Besides these special commands, the regular math operators work on complex numbers:
z0 + z1
[1] 5+11i 6+10i 7+ 9i 8+ 8i 9+ 7i 10+ 6i 11+ 5i 12+ 4i
z0 * z1
[1] -20+35i -13+34i -6+33i 1+32i 8+31i 15+30i 22+29i 29+28i
z2 / z3
[1] 0.25+0i
Rounding
There are various commands that deal generally with precision and rounding.
abs | This command returns the absolute magnitude of a numeric value (that is, ignores the sign). If it is used on a logical object the command produces 1 or 0 for TRUE or FALSE, respectively. |
sign | This command returns the sign of elements in a vector. If negative an item is assigned a value of –1; if positive, +1; and if zero, 0. |
floor | This command rounds values down to the nearest integer value. |
ceiling | This command rounds up a value to the nearest integer. |
trunc | Creates integer values by truncating items at the decimal point. |
round | Rounds numeric values to a specified number of decimal places. |
signif | This command returns a value rounded to the specified number of significant figures. |
These are all fairly obvious; here are some examples:
## Make some values
yy = log(2^(2:6))
yy
[1] 1.386294 2.079442 2.772589 3.465736 4.158883
floor(yy)
[1] 1 2 2 3 4
ceiling(yy)
[1] 2 3 3 4 5
trunc(yy)
[1] 1 2 2 3 4
round(yy, digits = 3)
[1] 1.386 2.079 2.773 3.466 4.159
signif(yy, digits = 3)
[1] 1.39 2.08 2.77 3.47 4.16
## Include negative numbers
xx = -3:3
xx
[1] -3 -2 -1 0 1 2 3
sign(xx)
[1] -1 -1 -1 0 1 1 1
abs(xx)
[1] 3 2 1 0 1 2 3
These commands work on most numeric objects (e.g. data.frame, vector, matrix, table). If you have logical objects, you’ll return 1 for a TRUE and 0 for a FALSE.
Scientific Format
You can enter numbers using an exponent to make it easier to deal with very large or very small values. The exponent is indicated by the letter e or E. You can use the – sign to indicate a negative exponent. The + sign can be omitted. You must not leave a space between the value and the exponent. You can only add an exponent to a numeric value and not to a named object.
1e3
[1] 1000
1E4
[1] 10000
1 e-2
Error: unexpected symbol in “1 e”
1e-2
[1] 0.01
Values are generally “printed” by R in regular format but sometimes they will appear in scientific format. This makes no difference to your calculations but sometimes you want the result to be displayed in scientific format and at other times not. There are two ways to achieve the result you want.
The simplest way to present your results objects in an appropriate format is to use the format() command. You simply set scientific = TRUE to prepare an object in that format (set FALSE to use regular format). The downside to this is that the object is prepared as a text result, which might be inconvenient.
The other way is to alter the options() and to set the scipen option. The default is 0. Negative values tend to produce scientific notation and positive values are less likely to do so.
## Make some values
yy = c(1, 10, 100, 1000, 10000, 100000)
zz = c(1, 12, 123, 1234, 12345, 123456)
yy ; zz
[1] 1e+00 1e+01 1e+02 1e+03 1e+04 1e+05
[1] 1 12 123 1234 12345 123456
## Use format() to force scientific or foxed format
format(yy, scientific = FALSE)
[1] ” 1″ ” 10″ ” 100″ ” 1000″ ” 10000″ “100000”
format(zz, scientific = TRUE, digits = 3)
[1] “1.00e+00” “1.20e+01” “1.23e+02” “1.23e+03” “1.23e+04” “1.23e+05”
## Check the scipen option
options(“scipen”)
$scipen
[1] 0
## Set scipen
options(scipen = 1)
> yy
[1] 1 10 100 1000 10000 100000
options(scipen = -6)
zz
[1] 1.00000e+00 1.20000e+01 1.23000e+02 1.23400e+03 1.23450e+04 1.23456e+05
print(zz, digits = 3)
[1] 1.00e+00 1.20e+01 1.23e+02 1.23e+03 1.23e+04 1.23e+05
options(scipen = 0) # Reset scipen
You may need to tweak the values of scipen but in general the number of digits in the result is your guideline.
Extremes
The largest and smallest items can be extracted using max() and min() commands respectively. These commands produce a single value as the result.
The range() command produces two values, the smallest and largest, in that order.
## Set random number generator
set.seed(99)
## Make some values
xx = runif(n = 10, max = 100, min = -100)
max(xx)
[1] 98.50176
min(xx)
[1] -77.24366
range(xx)
[1] -77.24366 98.50176
range(xx)[1] # Just the min value
[1] -77.24366
range(xx)[2:1] # Display max then min
[1] 98.50176 -77.24366
If you want the 2nd largest, or the 3rd smallest (for example) then you need to use the order() command to get an “index”. Set the sort order to decreasing = FALSE (the default) to get the smallest values, set decreasing = TRUE to get the largest values.
xx
[1] 16.942370 -77.243665 36.852949 98.501755 6.998717 93.322813 34.285512
[8] -41.084458 -28.327403 -64.937049
order(xx) # Index in ascending order
[1] 2 10 8 9 5 1 7 3 6 4
xx[order(xx)[1]] # 1st smallest (min)
[1] -77.24366
xx[order(xx)[2]] # 2nd smallest
[1] -64.93705
xx[order(xx, decreasing = TRUE)[1]] # 1st largest (max)
[1] 98.50176
xx[order(xx, decreasing = TRUE)[2]] # 2nd largest
[1] 93.32281
Logarithms
Logarithms and their reverse (anti-logs?) are dealt with using the log() and exp() commands respectively. The default base is the natural log (e) but you can specify the base explicitly. There are also several convenience commands:
log(x, base = exp(1)) | The basic log command. The default base is natural. Use base parameter to specify alternative (as long as it works out as a numeric). |
log10 | A convenience function computes log base 10. |
log2 | Computes log base 2. |
log1p | Computes log(x + 1). See also expm1(). |
exp | The antilog for base e. |
expm1 | The antilog for base e -1 i.e. exp(x) -1. See also log1p(). |
Using the commands is fairly simple.
log(1:4) # Natural log
[1] 0.0000000 0.6931472 1.0986123 1.3862944
log(1:4, base = 3) # Log base 3
[1] 0.0000000 0.6309298 1.0000000 1.2618595
log10(1:4) # Log base 10
[1] 0.0000000 0.3010300 0.4771213 0.6020600
log2(1:4) # Log base 2
[1] 0.000000 1.000000 1.584963 2.000000
log(0:3) # Regular log gives infinity for 0
[1] -Inf 0.0000000 0.6931472 1.0986123
log1p(0:3) # Add 1 to values then log
[1] 0.0000000 0.6931472 1.0986123 1.3862944
10^0.6 # The antilog (base 10) of 0.6
[1] 3.981072
3^0.63 # The antilog (base 3) of 0.63
[1] 1.997958
exp(1.098) # The natural antilog of 1.098
[1] 2.998164
expm1(1.098) # The natural antilog of 1.098 then minus 1
[1] 1.998164
Trigonometry
R has a suite of commands that carry out trigonometric functions.
Regular | Hyperbolic | |
Sine | sin() asin() | sinh() asinh() |
Cosine | cos() acos() | cosh() acosh() |
Tangent | tan() atan() | tanh() atanh() |
The commands work out the basic functions and also hyperbolic equivalents. Angles are in radians (a right angle is pi/2 radians).
Here are some simple examples using the cosine:
cos(45) # Angle in radians
[1] 0.525322
cos(45 * pi/180) # Convert 45 radians to degrees
[1] 0.7071068
acos(1/2) * 180/pi # To get result in degrees
[1] 60
acos(sqrt(3)/2) * 180/pi # To get result in degrees
[1] 30
cosh(0.5) # Hyperbolic function
[1] 1.127626
Summation
There are various commands associated with lists of values (that is list in a general sense, not an R list object).
Adding things
The sum() command returns the sum of all the numbers specified. This works for most R objects, including data.frame, matrix and vectors. Logical values are treated as 1 (TRUE) or 0 (FALSE). NA items are treated as 0. You can “ignore” NA items using na.rm = TRUE as a parameter in the command.
Multiplying things
The prod() command returns the product of all the numbers specified, that is each value multiplied by the “next”. This works for most R objects, including data.frame, matrix and vectors (items are taken columnwise for data.frame objects). Logical values are treated as 1 (TRUE) or 0 (FALSE). NA items are treated as 0. You can “ignore” NA items using na.rm = TRUE as a parameter in the command.
v = 1:9
m = matrix(1:9, ncol = 3)
d = data.frame(a = 1:3, b = 4:6, c = 7:9)
v ; m ; d
[1] 1 2 3 4 5 6 7 8 9
[,1] [,2] [,3]
[1,] 1 4 7
[2,] 2 5 8
[3,] 3 6 9
a b c
1 1 4 7
2 2 5 8
3 3 6 9
## sum for vector, matrix and data.frame
sum(v)
[1] 45
sum(m)
[1] 45
sum(d) # Reads data columnwise
[1] 45
## product for vector, matrix and data.frame
prod(v)
[1] 362880
prod(m)
[1] 362880
prod(d) # Reads data columnwise
[1] 362880
## Make a locical vector
z = c(TRUE, TRUE, FALSE, TRUE)
z
[1] TRUE TRUE FALSE TRUE
## Results for logicals
sum(z)
[1] 3
prod(z)
[1] 0
The factorial() command is similar to prod(). With prod() you specify prod(x:y) as a sequence, whilst in factorial() you specify factorial(y). If you provide more than one value, you end up with multiple results:
factorial(3) # i.e. 3 * 2 * 1
[1] 6
factorial(5) # i.e. 5 * 4 * 3 * 2 * 1
[1] 120
factorial(v)
[1] 1 2 6 24 120 720 5040 40320 362880
factorial(m)
[,1] [,2] [,3]
[1,] 1 24 5040
[2,] 2 120 40320
[3,] 6 720 362880
You can also use the gamma() command, which equates to factorial(x-1). Essentially prod(x:y) = gamma(y+1) = factorial(y).
Cumulative functions
There are several cumulative functions built-in to R. These determine sum, product, maximum and minimum.
cumsum | Determines the cumulative sum |
cumprod | Cumulative product |
cummax | Cumulative maximum |
cummin | Cumulative minimum |
The commands operate on numeric objects, usually vector or matrix objects. The commands work on data.frame objects but compute results per column. The commands do not work directly on lists (but you can use the lapply() command).
v = 1:9
m = matrix(1:9, ncol = 3)
d = data.frame(a = 1:3, b = 4:6, c = 7:9)
v ; m ; d
[1] 1 2 3 4 5 6 7 8 9
[,1] [,2] [,3]
[1,] 1 4 7
[2,] 2 5 8
[3,] 3 6 9
a b c
1 1 4 7
2 2 5 8
3 3 6 9
cumsum(v)
[1] 1 3 6 10 15 21 28 36 45
cumprod(m)
[1] 1 2 6 24 120 720 5040 40320 362880
cummax(d) # For data.frame calculations are carried out column by column
a b c
1 1 4 7
2 2 5 8
3 3 6 9
It is possible to make custom functions that calculate other cumulative results, but that is another story.
There are many other mathematical functions in R. This has been a brief overview of some of the “simpler” arithmetic (although the foray into logic may not count as math).
My Publications
I have written several books on ecology and data analysis
Register your interest for our Training Courses
We run training courses in data management, visualisation and analysis using Excel and R: The Statistical Programming Environment. Courses will be held at The Field Studies Council Field Centre at Slapton Ley in Devon. Alternatively we can come to you and provide the training at your workplace.
Get In Touch Now
for any information regarding our training courses, publications or help with a data project