Rtutorial
Rtutorial
Steven M. Ho an
Department of Geology, University of Georgia, Athens, GA 30602-250
24 August 2021
ll
d
Installing
R is open-source and freely available for macOS, Linux, and Windows. You can download
compiled versions of R (called binaries, or precompiled binary distributions) by going to the
home page for R (http://www.r-project.org), and following the link to CRAN (the Compre-
hensive R Archive Network). You will be asked to select a mirror; pick one that is geographi-
cally nearby. On the CRAN site, each operating system has a FAQ page, and there is also a
more general FAQ. Both are worth reading
To download R, macOS users should follow the macOS link from the CRAN page and select
the le corresponding to the most recent version of R. This will download a disk image; dou-
ble-click it to install R. R can be run from the R app, or from the command line in Terminal
and XQuartz
Linux users should follow the links for their distribution and version of Linux and download
the most recent version of R. There is a read-me le that explains the download and installa-
tion process
Windows users should follow the link for Windows and then the link for the base package. A
read-me le contains the installation instructions for the R app
Rstudio is alternative running R within a single window, which has a Matlab-like interface
that many prefer. It is available for macOS, Linux, and Windows at http://rstudio.com
For more details, follow the Manuals link on the left side of the R home page. R Insta ation
and Administration gives detailed instructions for installation on all operating systems
In addition to R, you should install a good text editor for writing and editing code; do not
used a word processor (like Word) for this. For macOS, BBEdit is an excellent text editor and
is available from Bare Bones Software; Atom is also good. For Windows, Notepad++ is highly
recommended, and it is free. Sublime Text is another highly regarded text editor, and it is
available for macOS, Linux, and Windows
Learning
There are an enormous number of books on R. Several I’ve read are listed below, starting with
the more basic and passing to the more advanced. The R Book is my favorite. If you have a
programming background or want to get serious about programming in R, I highly recom-
mend The Art of R Programming
Statistics : An Introduction using R, by Michael J. Crawley, 2014. John Wiley & Sons,
360 p. ISBN-13: 978-1118941096
Using R for Introductory Statistics, by John Verzani, 2014. Chapman & Hall/CRC,
518 p. ISBN-13: 978-1466590731
A Short R Tutoria 1
fi
fi
.
l
.
fi
.
ll
.
Data Analysis and Graphics Using R, by John Maindonald, 2010. Cambridge Univer-
sity Press, 549 p. ISBN-13: 978-0521762939
The manuals link on the R home page points to three important guides. The Introduction to R
is a basic source of information on R. R Data Import/Export is useful for understanding the
many ways in which data may be imported into or exported from R. The R Reference Index is a
gigantic pdf (3500 pages!) that comprehensively lists all help les in a standard R installation.
These help les are also freely accessible in every installation of R.
Every experienced R user likely has their favorite web sites for R, and these three are mine
Cookbook for R (http://www.cookbook-r.com) has recipes for working with data. This is a
good source for how to do common operations
Remember when you run into a problem that Google is your friend. So is DuckDuckGo, if
you’re not a fan of all that tracking
>
For every command in this tutorial, I will show the prompt, but you should not type it
R works with objects, and there are many types. Objects store data, and they have commands
that can operate on them, which depend the type of data. A single number or string of text is
the simplest object and is known as a scalar. [Note that a scalar in R is simply a vector of
length one; there is no distinct object type for a scalar, although that is not critical for what
follows.
A Short R Tutoria 2
ff
]
fi
fl
.
l
.
fl
.
fi
.
To give a value to an object, use one of the two assignment operators. Although the equals
sign may be more familiar to you now, the arrow (less-than sign, followed by a dash: <-) is
more common, and you should use it
> x = 3
> x <- 3
Read both of those as “assign the value of 3 to the variable x” or more simply, “assign 3 to x”.
To display the value of any object, type its name at the prompt
> x
Arithmetic operators follow standard symbols for addition, subtraction, multiplication, divi-
sion, and exponents
> x <- 3 + 4
> x <- 2 - 9
> x <- 12 * 8
> x <- 16 / 4
> x <- 2 ^ 3
Operators follow the standard order of operations: parentheses and brackets rst, followed in
order by exponents, multiplication and division, addition and subtraction. Within each of
these, operations proceed from left to right. Although you can always force an order of opera-
tions, learn this order so that you use the fewest parentheses. Excess parentheses make code
harder to read
Comments are always preceded by a pound sign (#), and what follows the pound sign on that
line will not be executed
Spaces are generally ignored, but include them to make code easier to read. Both of these
lines produce the same result
> x<-3+7/14
> x <- 3 + 7 / 14
> x <- 3
> x # correctly displays 3
> X # produces an error, as X doesn’t exist, but x does
Because capitalization matters, you should avoid giving objects names that di er only in their
capitalization, and you should use capitalization consistently. One common pattern is camel-
case, in which the rst letter is lower case, but subsequent words are capitalized (for example,
pacificOceanCarbon). Another common pattern is to separate words in an object’s name
with an underscore (pacific_ocean_carbon); this is called snake case. Pick one and be
A Short R Tutoria 3
.
fi
:
l
.
ff
fi
consistent. Moreover, avoid overly short or cryptic names; it’s better to have a longer name
that is easily read because it will make your code easier to understand and debug
You can use the up and down arrows to reuse old commands without retyping them. The up
arrow lets you access progressively older previously typed commands. If you go too far, use
the down arrow to return to more recent commands. These commands can be edited, so the
up and down arrows are good time-savers, even if you don’t need to use exactly the same
command as before
Function
R has a rich set of functions, which are called with their arguments in parentheses and which
generally return a value. Functions are also objects. The maximum of two values is calculated
with the max() function
> max(9, 5)
> max(x, 4) # objects can be arguments to functions
Some functions need no arguments, but the parentheses must still be included, otherwise R
will interpret what you type as the name of a non-function object, like a vector or matrix. For
example, the function objects(), which is used to display all R objects you have created,
does not require any arguments and is called like this
Neglecting the parentheses means that you are asking R to display the value of an object
called objects. Since objects is a function, R will show you the source code for the func-
tion
Functions commonly return a value. If the function is called without assigning the result to an
object, then the returned value will be displayed on the screen. If an assignment is made, the
value will be assigned to that object, but not displayed on the screen
Multiple functions can be called in a single line, and functions can be nested, so that the re-
sult of one function can be used as an argument for another function. Nesting functions too
deeply can make the command long, confusing, and hard to debug.
To get help with any function, use the help() function or the ? operator, along with the
name of the function
> help(max)
> ?max
> ? max
A Short R Tutoria 4
.
l
.
The help pages show useful options for a function, plus background on how the function
works, references to the primary literature, and examples that illustrate how the function
could be used. Use the help pages.
In time, you will write your own functions because they let you invoke multiple commands
with a single command. To illustrate how a simple function is created and used, consider the
pow() function shown below, which raises a base to an exponent. In parentheses after the
word function is a list of parameters to the function, that is, values that must be input into
the function. When you call a function, you supply arguments (values) for these parameters.
The commands the function performs are enclosed in curly braces. Indenting these state-
ments is not required, but it makes the function easier to read
Arguments can be assigned to a function’s parameters in two ways, by name and by position.
When you assign arguments by name, they can be listed in any order and the function will
give the same result
Assigning arguments by position involves less typing, but the arguments must in the correct
order
For pow(), the rst position is assumed to hold the rst parameter in the function de nition
(base) and the second position is assumed to hold the second parameter (exponent)
Calling arguments by position is faster, but calling arguments by name is less prone to errors,
and it makes the code self-explanatory
Some functions have default values for some parameters. For example, pow() could be writ-
ten a
which makes the default exponent equal to 2. If you write pow(5), you’ll get 25 in return (5 to
the default exponent of 2). If you want a di erent exponent, specify the exponent argu-
ment, such as pow(2, 4), which would produce 16 (2 to the fourth power). Refer to a func-
tion’s help page to see which function parameters have default assignments
A Short R Tutoria 5
s
fi
:
ff
fi
.
fi
.
Several functions are useful for manipulating objects in R. To show all current objects, use
objects() and ls(), which are identical
> objects()
> ls()
> remove(someObject)
You can remove all objects, but since this cannot be undone, be sure that this is what you
want to do. Even if you remove all objects, your command history is preserved, so you could
reconstruct your objects, but this is likely laborious. To remove all objects, you must combine
two commands, the ls() function and the remove() function
> remove(list=ls())
Vector
Data can be stored in several di erent types of objects, and a vector is the most common. A
vector is a series of values, where all values have the same type, such as numbers, characters
(strings), and logical (Boolean). Vectors are created most easily with the c() function (c as in
concatenate). Short vectors are easily entered this way, but long ones are more easily imported
(see Importing Larger Data Sets below)
> x <- c(3, 7, -8, 10, 15, -9, 8, 2, -5, 7, 8, 9, -2, -4, -1)
An element of a vector can be retrieved by using an index, which describes its position in the
vector, starting with 1 for the rst element. The element is placed in square brackets after the
name of the vector. To see the fth element of x, type
Multiple consecutive indices can be speci ed with a colon. For example, to retrieve elements
3 through 10, typ
To retrieve non-consecutive elements, create a vector of those indices using the c() func-
tion. Failing to use c()will cause an error
These two approaches can be combined in more complex ways. For example, if you wanted
elements 3 through 7, followed by elements 5 through 9, you would type
A Short R Tutoria 6
s
l
fi
fi
ff
.
fi
.
You can use conditional logic to select elements meeting certain criteria. The logical state-
ment inside the bracket produces a vector of boolean values (TRUE and FALSE), which tell
whether a particular vector element should be returned
Any Boolean vector can be negated with the ! operator, but this is operator is easily over-
looked when reading code. Except for !=, it is often better to use other operators that are
more direct, for example, x<2 rather than !x>=2.
Vectors can be sorted with the sort() function. Ascending order is the default
> sort(x)
Sorting can be done in descending order by changing one of the default arguments to de-
creasing = TRUE or by reversing the sorted vector with rev(). There are often multiple
ways to perform an operation in R, and you should choose the simplest one
R speeds calculations by using vectorized math. For example, suppose you wanted to multiply
all values in a vector by a constant. If you have programmed before, you might think of doing
this with a loop, in which you step through each value in a vector and multiply it by a con-
stant. Avoid doing this in R, as loops are slow, so much so that they won’t be presented until
near the end of this tutorial. Instead, simply multiply the vector by the constant in one line.
This example multiplies all of the values in a vector by 2
Likewise, you can use vector arithmetic on two vectors. For example, given two vectors of the
same length, it is easy to add the rst element of the one vector to the second element of the
second vector and so on, producing a third vector of the same length with all of the sums
A Short R Tutoria 7
l
fi
Factor
Factors are similar to vectors, but they have a xed number of levels and are ideal for express-
ing categorical variables. For example, if you have a series of sites, each representing a speci c
habitat type, store them as a factor rather than as a vector
Inspecting the habitats object shows that it is stored di erently than a vector
> habitats
[1] marsh grassland forest tundra grassland tundra
[7] forest marsh grassland
Levels: forest grassland marsh tundra
We can use the str() function to display the internal structure of any object
> str(habitats)
Factor w/ 4 levels "forest","grassland",..: 3 2 1 4 2 4 1 3 2
Although the names are displayed when we show the object, the data are actually saved as
values 1–4, with each value corresponding to a named factor. For example, the rst element is
saved as a 3, that is, the third level of the factor (marsh). The second element is saved as a 2,
the second level of the factor (grassland), and so on. This is not only a more compact way of
saving the data, it also allows e cient ways to use these categories, such as using
tapply()and by() to perform calculations on each category, split() to separate the data
by category, and table() to create tables of the data by category
List
Lists are another type of data structure, also closely related to vectors. Lists hold a series of
values, like vectors, but the values in a list can be of di erent types, unlike a vector. For exam-
ple, the rst element of a list might be a string giving the name of a locality ('Hueston
Woods'), the second element might be an integer expressing the number of beetle species
there (42), and the third element might be a boolean value stating whether the locality is old-
growth forest (TRUE). Lists are made with the list() function:
A Short R Tutoria 8
s
fi
s
l
ffi
fi
ff
:
ff
fi
.
fi
When the elements in a list are labelled, they can be accessed by their name. For example,
when you perform a linear regression, a linear regression lm object is returned, and it is a list
that contains twelve items, including the slope, the intercept, con dence limits, p values,
residuals, etc. If you ran a regression and assigned the result to forestRegression, you
could nd the names of all the elements in the forestRegression list with the names()
function
> names(forestRegression)
One of the elements of the list is called residuals, and you can use do ar-sign notation to
access it by name
> forestRegression$residuals
Because residuals is the second element in the list, you could also access it by position with
the double-brackets notation
> forestRegression[[2]]
In the example above, the residuals object is a vector, so you can access individual ele-
ments of it by adding brackets. For example, you could get the residual for the third data
point in two ways
Note that the rst command is more obvious. Although it requires more typing, accessing a
value by name is more readable and less error-prone
Matrice
Another type of R data structure is a matrix, which has multiple rows and columns of values,
all of the same type, like a vector. You can think of a matrix as a collection of vectors, all of
the same type and length
Small matrices are entered easily with the matrix() function, in which you specify the data
as a vector and the number of rows or columns.
This will generate a matrix of 3 rows and therefore 2 columns, since there are six elements in
the matrix. By default, the matrix is lled by columns, such that column 1 is lled rst from
top to bottom, then column 2, etc. Displaying the x matrix give
[,1] [,2]
[1,] 3 2
[2,] 1 5
[3,] 4 8
A Short R Tutoria 9
fi
.
fi
:
l
.
fi
fi
ll
fi
fi
The bracketed values along the right and the top give the row and column positions. For ex-
ample, the value in the third row and second column could be retrieved wit
Memorize this order: row rst, column second. This is standard across R
A matrix can alternatively be lled by rows, with row 1 lled rst, from left to right, then row
2, etc., by changing the default argument to be byrow=TRUE
This gives
[,1] [,2]
[1,] 3 1
[2,] 4 2
[3,] 5 8
Large matrices can also be entered this way, but importing them is much easier (see Import-
ing Larger Data Sets below)
The rows and columns can be swapped, such that the rows become the columns, and vice
versa by transposing the matrix with the the t() function
Data Frame
A data frame is like a matrix, but the columns can be of di erent types. For example, one col-
umn might be locality names (strings), other columns might have counts of di erent species
of beetles (numbers), and other columns might be Boolean values that describe properties of
the localities, such as whether it is old-growth forest or on protected land. In this way, data
frames are to matrices what lists are to vectors
Nearly always, columns of a matrix or data frame should be the measured variables, and the
rows should be cases (localities, samples, etc.).
One way to create a data frame is to combine several vectors, each of which is a di erent
measure of a set of samples. For example, suppose we had vectors for the locality name, the
abundance of four di erent beetle species, and whether the forest was old growth or not
A Short R Tutoria 10
l
ff
s
fi
.
fi
fi
ff
:
fi
:
ff
ff
:
These vectors can be combined into a data frame using the data.frame() command
It is usually good practice to clean up and remove those vectors after creating the data frame
When using a data frame, we often want to know the names of the columns (the variables),
which is given by the colnames() function
> colnames(forests)
Retrieving elements of a data frame is the same as for a matrix, with the rst index being the
row and the second being the column
Individual columns can be accessed by name with the $ operator. For example, this will return
the column named locality from the forests data frame
> forests$locality
Dollar-sign notation will not work for selecting multiple columns. To select multiple columns,
you will need to pass a vector of column names or column numbers
To access individual elements (cases) of column in a data frame, use dollar-sign notation plus-
brackets with indices, or specify the row and column numbers. Both of the following return
the rst four values (rows) of locality, which is in column 2 of the data frame
> forests$locality[1:4]
> forests[1:4, 1]
If the name of the data frame is long, dollar-sign notation can become cumbersome. To avoid
repeatedly typing the name of the data frame, you can use the attach() function, which
creates copies of all the vectors (columns) in the data frame that can be directly accessed. It is
good practice use the detach() function to delete these copies when you are done with
those data
> attach(forests)
> locality # locality can be accessed without $ notation
A Short R Tutoria 11
fi
.
l
.
fi
.
> detach(forests)
> locality # returns an error; detach() destroyed the copy
Because attach() creates copies, changes made to the attached data are not be saved in the
original data frame.
A danger in using attach() is that it may mask existing variables with the same name, mak-
ing it unclear which version is being used. attach() is best used when you are working with
a single data frame. If you must use it in more complicated situations, be alert for warnings
about masked variables, and call detach()as soon as possible. There are alternatives to at-
tach(), such as including the data parameter in some functions (such as regressions),
which lets you access variables of data frame directly. You can also use the with() function,
another safe alternative that can be used in many situations
Sorting a matrix or data frame is more complicated than sorting a vector. It is often best to
store the sorted matrix or data frame in another object in case something is typed wrong.
The following sorts the data frame A by the values in its third column and stores the result in
data frame B
To understand how this complex command or any complex command works, start at the in-
nermost set of parentheses and brackets, and work outwards. At the innermost level, A[ ,3]
returns all rows of column 3 from matrix A. Stepping out one level, order(A[ ,3]) returns
the order of the elements in that column as if they were sorted in ascending order. In other
words, the smallest value in column 3 would have a value of 1, the next smallest would have a
value of 2, and so on. Finally, these values specify the desired order of the rows in the A ma-
trix, and A[order(A[ ,3]), ] returns all the columns with the rows in that order
This technique of taking apart a complex function call is known as unpacking. You should do
this whenever a complex function call returns unexpected results or when you need to under-
stand how a complex function call works
In some cases, your data may be stored in a matrix, but a particular function may require it to
be in a data frame for some function (or vice versa). You can try to coerce it into the correct
type with the functions as.data.frame() and as.matrix()
A Short R Tutoria 12
.
fi
l
.
To preserve the readability of your data for many years, always save a copy of your data in a
text-only format. Binary le formats for programs like Excel change over time, and someday
you may not be able to read your old les. This will not happen with plain text les.
To read or write les in R, you need to know the current working directory for R, that is, the
directory in which R will look for les. To nd the current working directory, use getwd()
> getwd()
It is easiest to work with R by using a single working directory for any given session, and you
can set this with the setwd() function. This directory will hold most or all of the les you
will need to read, such as data and source code, and it will be where les are saved by default.
R will stay in this working directory unless you specify a di erent path to a le
Paths to les and directories are speci ed di erently in UNIX (macOS, Linux) and Windows
le systems. This is one of the few areas in which R works di erently on the two platforms. If
you share code across platforms, any command that accesses the le system will produce an
error, so avoid including paths in your code
Use the setwd() function to set the working directory of R, with the path as an argument.
Because the path is a string, you must wrap it in quotes, and this is true for any string in R.
Single-quotes and double-quotes both work; just be consistent. Inside the path, use single
forward slashes for UNIX systems
> setwd('/Users/myUserName/Documents/Rdata')
Remember to never include calls to setwd() in R code that you share with someone else.
That path will most likely not exist on their computer, and including it will produce errors
when they run your code. Likewise, avoid embedding le paths within other commands
IMPORTING A VECTOR
Once you have set your working directory, you can read a vector into R with the scan()
function. Remember to put your le name in quotes, and include the su x
A Short R Tutoria 13
fi
fi
fi
l
fi
.
fi
fi
:
fi
:
fi
fi
.
ff
s
fi
ff
ff
fi
fi
ffi
.
fi
fi
.
fi
fi
This simple version of this command assumes that the cases are on di erent lines, but if cases
are separated by commas, spaces, tabs, or other such characters, that can be set using the sep
argument for scan(). Likewise, if the variable name is included in the le, or if other infor-
mation is included at the beginning of the le, those lines can be skipped by setting the skip
argument
IMPORTING A DATA F R A M E
To read a table of values into R and save it as a data frame, use the read.table() function.
This function assumes that your data are in the correct format, with columns corresponding
to variables and rows corresponding to samples. All cells should contain a value; don’t leave
any empty. If a value is missing, enter NA in that cell. Variable names can be as long as you
need them to be, and you will want to strike a balance between readability and the amount of
typing needed. Variable names do not need to be single words, but any blank spaces will be
replaced with a period when you import the data into R
Of the many options for read.table(), you will routinely pay close attention to three,
which you can determine by examining the data le in a text editor. First, check to see if
there are column names for the variables, that is, whether a header is present. Second, check
to see if there are row names (that is, unique identi ers for each case, such as a locality num-
ber) and what column they are in. If row names are present, they are most most commonly in
the rst column. Third, check to see what separates the columns: tabs or commas are the
most common separators, also called delimiters
For example, suppose that your data table has the names of its variables in its rst row (that
is, it has a header), that your samples names are in the rst column of the table, and that your
values are separated by commas. Given this, you would import your data as follows
If there is no header, leave out the argument for the header parameter, because the default
is that there is no header. Likewise, if there are no row names, omit the argument for the
row.names parameter. If the values are separated by tabs, use sep='\t'. There are other
commands for opening les, like read.csv(), but you should become comfortable opening
any table le with read.table(); it is the Swiss-army knife of le openers
If additional explanatory lines about the data are included at the beginning of the le, they
can be skipped with the skip argument of read.table()
Always verify that an imported data le was read correctly. Although you could simply type
the name of the object you assigned the data to, this is not recommended as it can produce
voluminous output for large data sets. It is much better to use the head() and tail()
functions to examine the rst and last few lines of data
> head(myData)
> tail(myData)
A Short R Tutoria 14
fi
.
fi
l
fi
fi
fi
fi
.
fi
fi
fi
.
fi
ff
fi
.
fi
fi
:
Generating Number
Writing long, regular sequences of numbers is tedious and error-prone. R can generate these
quickly with the seq() function. If the increment (by) isn’t set, it defaults to 1
R can generate random numbers from many statistical distributions. A few common examples
include runif() for uniform or at distributions, rnorm() for normal distributions, and
rexp() for exponential distributions. For each, specify the number of random numbers (n)
and one or more parameters that describe the distribution. For example, this generates ten
random numbers from a uniform distribution that starts at 1 and ends at 6
This creates a hundred random numbers from a normal distribution with a mean of 5.2 and a
standard deviation of 0.7
This produces fty random numbers from an exponential distribution with a rate parameter
of 7
Basic Statistic
R has functions for calculating simple descriptive statistics from a vector of data, such as
A Short R Tutoria 15
:
fi
l
:
fl
s
The pnorm() function will nd the area under a standard normal curve, starting from the
left tail, and in the example below, going to a value of 1.96. Note that 1 minus this value would
correspond to the p value for a Z-test, where Z=1.96
> pnorm(q=1.96)
The qnorm() function can nd the critical value for a given probability. For example, in a
two-tailed test at a signi cance level of 0.05, the following gives the critical value on the right
tail
> qnorm(p=0.975)
Last, the dnorm() function gives the density or height of the distribution at a particular val-
ue (at 1.5 below). By calculating this over all values, you can plot the shape of the distribution
> dnorm(x=1.5)
Other distributions, such as the uniform, exponential, and binomial distributions follow a
similar syntax, with r corresponding to a random number, p for probability, q for critical val-
ue, and d for density (the height of function at a particular value)
One of the great strengths of R is the incredibly large number of available statistical analyses.
Many are built into the base package of R, and a mind-boggling number of them are freely
available in user-contributed packages. There’s a good chance that if you need to do an analy-
sis, it is already available in R. Installing packages is described under Customizing R below
E cient computatio
R’s vectorized math eliminates the need for looping through vectors and matrices to perform
many calculations. Such vectorized calculations are commonly orders of magnitude faster
than using loops
Another set of tools for e cient computation are the apply() family of functions. The
most basic of these is apply(), which is used when you want to perform a function on every
row or every column of a matrix or data frame and get the results as a vector. For example,
the following calculates the median for every column of a matrix and returns a vector with
those medians
A Short R Tutoria 16
ffi
.
fi
.
l
fi
ffi
fi
fi
.
fi
n
ff
.
Set MARGIN to 1 to calculate the median for every row instead. The easy way to remember
whether to use 1 or 2 is to think of how rows and columns are speci ed for matrices and data
frames: it is [row, column], so rows are 1, and columns are 2. The argument to FUN is the name
of the function to be applied; this could be a function that you create
The functions sapply() and lapply() are similar, but they are used when a function
needs to be applied to all elements of a vector or a list. lapply() returns a list, and sap-
ply() returns a vector or matrix. One possible use of both would be to have a series of simi-
lar data sets stored as elements of a list, then call lapply() or sapply() once to perform
some function on each of the data sets. This would be simpler than looping through the list
and performing the calculations separately on each data set. It is also better than storing the
data sets as separate objects and performing the calculations separately on each object. By
creating your own function as a wrapper around other functions, you could perform a com-
plex series of analyses, including making and saving plots for each data set in one command
Plot
A real strength of R is the quality of its plotting routines. Many types of plots are available,
and complex plots can be produced. R’s plots are far superior to those made in spreadsheets
like Excel, which are commonly saddled by unnecessary shading, grid lines, and 3-D e ects
When calling an R plotting function, the plot will automatically be generated in the active
plotting window, if one already exists. If no plot window exists, a new one will be created. Use
dev.new() to create a new plot window, as this command will work on any platform. Avoid
using the platform-speci c ways of creating new plot windows, such as quartz()for macOS,
X11() for Linux, and windows() for Windows, because these will generate errors if your
code is run on a di erent platform
The height and width (in inches) of a plot window can be speci ed, or they can be left o for
the default window
HISTOGRAMS
Histograms, also called frequency distributions, are generated with the hist() function.
Calling hist() with no arguments except the data generates a default histogram
> hist(x)
Histograms can be customized by changing the number of bars or divisions with the breaks
parameter. Oddly for R, this is only a suggestion, and it may not be honored
A Short R Tutoria 17
s
ff
.
l
fi
.
fi
fi
.
ff
ff
.
The divisions in the histogram can be forced by specifying the breaks as a vector
S C AT T E R P L O T S
Scatterplots (x-y plots) are generated with the plot() function, with x being the variable on
the horizontal axis and y being the variable on the vertical axis
It is common to call these arguments by position only, putting the x-axis variable rst and the
y-axis variable second
Labels for the x and y axes can be set with the xlab and ylab parameters, and the plot title
can be set with the main parameter. Remember to put strings in quotes
The pch parameter can be set in plot() to specify a particular type of symbol. The value of
16 is a lled circle, an easily visible symbol that you should use. For simplicity, I will just use x
and y for the following examples, but you should always use informative names for your ob-
jects
By changing the argument to type, you can control whether lines or points are plotted
Symbol colors can be set with the col parameter. To see the full list of 657 named colors in R,
use the colors() function. Colors can also be speci ed by RGB (red-green-blue) value, as
used in creating colors for web pages
A Short R Tutoria 18
.
fi
fi
l
.
fi
.
fi
.
Equations and special symbols can be used in gure labels and as text added to gures. See
the help page for plotmath() for more details. Adding equations and special symbols
commonly uses three functions. The function text() places additional text onto a gure,
expression() creates an object of type “expression”, and paste() is used to concatenate
items. The help pages for these functions are useful for seeing the basic ways for combining
these useful functions. The rst example puts the square root of x as the y-axis label, and the
second example shows the standard symbol for the oxygen isotope ratio ( 18O) on the y-axis
Special symbols can also be added using Unicode symbols in expression() and paste().
For example, to create a label with a per-mil symbol, such as 13C (‰ PDB), use the Unicode
character 2030; all Unicode character numbers must be preceded with \U. Symbols for thou-
sands of other characters can be found at https:\\home.unicode.org
ADDING TO PLOTS
Text annotations can be added with the text() function, where the x and y arguments de-
scribe the coordinates of the annotation, and labels speci es what text will be added. The
coordinates are identical to those used for placing points on the plot
Lines can be added to a plot with the abline() function. You can make horizontal and ver-
tical lines, as well as lines with a speci ed slope and intercept
Shapes can also be added to the plot, and these can be customized with particular line types
(dashed, dotted, etc.), colors of lines, and colors of lls. See lty in par() for customizing
line types. Become familiar with the help page for par(); it describes the many ways that
plots can be customized
The rect() function draws a box with the coordinates of the left, bottom, right, and top
edges
A Short R Tutoria 19
.
l
.
fi
fi
fi
fi
fi
𝛿
.
𝛿
fi
fi
.
The arrows() function draws an arrow, with the rst two arguments specifying the x and y
coordinate of the origin of the line, and the third and fourth arguments specifying the coor-
dinates of the arrowhead tip
The segments() function is identical to the arrows() function, except that no arrow-
head is drawn
Similarly, lines connecting data points can be added with lines(), and polygons can be
added with and polygon(). A box can be drawn around the entire plot with box()
This will produce a plot window with only the x and y axis names: no points, ticks, boxes, axis
labels, etc. Points can be added to the current plot with the points() function. Only those
points that are visible within the current limits of the axes will be shown. The limits of the
axes are based on the values used in the data supplied to the plot() function
> points(x, y)
The initial argument speci es the axis to be drawn, with 1 indicating the x axis and 2 indicat-
ing the y-axis. The at parameter speci es where the tick marks should be drawn, and the
labels parameter speci es the label to be displayed next to each tick mark. Values given to
labels must be in quotes, as they are strings
Here is an example of building a complex plot in parts. The commands that are shown were
preceded by a good bit of experimentation (not shown) with di erent parts of the plot to de-
termine the order in which these commands would be given. The data are read in, and at-
tach() is used to make the variables accessible without dollar-sign notation
A Short R Tutoria 20
.
l
fi
fi
.
fi
.
fi
.
ff
.
fi
.
Plotting begins by making a window with an aspect ratio appropriate for the data being plot-
ted. This is a time series, so we would like the plot to be relatively wide to emphasize the
changes over time
Because this is a scatterplot, the basic plot is built with the plot() command, specifying the
x and y data as the rst two arguments, the titles, the axis labels, and the limits of the y data
range (ylim). The type is set to n, because the data will be added subsequently
A light gray rectangle is added to emphasize a particular portion of the data. This is added
rst, so that the data will be added on top of the rectangle. If the data were drawn in the
plot() command, this rectangle would cover the data. The gray() command is used to set
the color to a shade of gray; with 0.0 being black and 1.0 being white
Two lines are added to emphasize divisions of the data along the x-axis. Note that a vector of
two values is passed as the v argument, which is simpler than drawing each line with a sepa-
rate call to abline()
Because there are so many data points, the data are added as a series of lines (type='l')
that connect individual values, rather than showing a symbol for each data point. Date (ju-
liandate) is plotted along the x-axis, and wave height (SwH) is plotted along the y-axis,
matching the arguments in the plot() call
The x-axis is built in two stages. Closely spaced short ticks are added rst, with tcl specify-
ing the tick length
Widely spaced longer ticks are added next, and these are labelled
Likewise, the y-axis is built in two stages, beginning with closely spaced short ticks
A Short R Tutoria 21
fi
.
fi
l
.
fi
.
These are followed with widely spaced long ticks and their labels
This is the nal plot. The advantage to making the plot this way, instead of making a simple
plot and adding to it in a program like Illustrator, is that if you make a mistake, you can x it,
re-run all the commands and you’ll have your nal plot, saving you the laborious steps of mak-
ing all the changes in Illustrator
6
Significant Wave Height (m)
5
4
2
1
M U LT I P L E PLOTS ON A PAGE
Multiple plots can be drawn on the same page by using the par() function and setting the
argument to mfrow. Each successive call to plot() will ll the panel from left to right, or
from the top to the bottom, starting in the upper left corner
This example will produce a page with areas for six plots in 3 rows and 2 columns. Each plot is
added subsequently. Note that once one plot is nished and another plot is started, the rst
plot can no longer be modi ed
COMMANDS
From the R console window, you can copy and paste the entire R session into a text le. This
will save a record of your commands and their displayed results. This is an easy and simple
way to save your work. Making a habit of this allows you to replicate your work, to build on it
subsequently, and to apply your analyses to other data sets.
You can edit this text le so that it consists of just the commands you need. First, delete all
the commands and their output that produced results you don’t want to keep. Next, delete all
A Short R Tutoria 22
fi
l
fi
fi
.
fi
fi
s
fi
fi
fi
fi
lines of results, leaving only lines of commands. Last, delete the > prompts at the beginning
of each line, and any + marks at the beginnings of lines. If you copy and paste this code into a
new R session, it should run without errors or warnings. If you get errors or warnings, edit the
code and repeat this process until it runs clean. Save this le for a permanent record of your
analysis
PLOTS
On macOS, graphics produced in R can be saved as pdf les by selecting the window contain-
ing the plot, and choosing Save or Save As from the File menu. In Windows, graphics can be
saved this way to meta le, postscript, pdf, png, bmp, and jpeg formats. The pdf format is rec-
ommended because it can be edited in Adobe Illustrator. Raster (bitmap) formats such as png,
bmp, and jpeg should be avoided because they cannot be edited and because they often su er
from compression artifacts that can make them look fuzzy
Graphics can also be built and saved to a le from the command line. Use the pdf() func-
tion to open a pdf le, just as you would open a plotting window with dev.new(). Run all of
your plotting commands, followed by dev.off() to close the pdf le. Note that your plot
will not be displayed while you do this, although it is being written to a le
A typical strategy is to rst develop a plot onscreen to re ne the order of the plot commands.
Once these are established, then open a pdf le with pdf(), rerun all of the plotting com-
mands, and close the pdf le with dev.off()
OBJECTS
Any objects generated in R, such as functions, vectors, lists, matrices, data frames, etc. can be
saved to a le by using the command save.image(). Although this will not save any graph-
ics or the command history, it is useful for saving the objects produced by your analyses so
they will not have to be regenerated in future R sessions. I recommend deleting unnecessary
objects before saving the image, particularly temporary or test objects generated when you
experiment with code. If your work involves long-running computations to build an object,
use save.image() so that it you don’t have to re-run those analyses the next time you
work. The image should have the su x .RData
When you resume your work, reload those objects with load(), allowing you to continue
where you left o
A Short R Tutoria 23
.
fi
ff
.
fi
l
fi
fi
fi
ffi
fi
fi
.
fi
fi
fi
.
fi
fi
.
ff
Programming in
If you have previous programming experience, get a copy of The Art of R Programming; it
will save you much time.
When coming from other programming languages, one of the largest conceptual hurdles is
learning to avoid loops, which can dramatically slow your calculations, especially when loops
or nested. Use vectorized operations and the apply() family of functions, as well as other
similar types of functions to avoid loops
R’s for loop is a generalized loop like the for loop in C or the do loop in FORTRAN. If you
have programmed before, the syntax is intuitive and this will likely be the most common loop
that you use. Note the use of curly braces if there is more than one statement inside the loop.
There are various styles as to where the curly braces may be placed to help readability of the
code, but their placement does not a ect the execution. Indenting the code inside the loop
helps to make the contents of the loop more apparent. Although indenting isn’t required, it is
good form to do it
Here is an example of calculating variance as you might in C or Fortran, that is, with loops
On an older test computer, this ran in 16.3 seconds. When vectorized math was used instead
of loops
it ran in a mere 0.23 seconds, a dramatic improvement (that is, 70 times faster). Using the
built-in var() function, which has additional optimizations, it took only 0.082 seconds (al-
most 200 times faster). Note, however, that on a newer computer these three times were 1.30,
1.24, and 3.31 seconds: the var() function was the slowest! This raises an important issue:
when optimizing your code, always measure the execution time (see Timing Your Code be-
low) to be sure that you are actually making the code run faster
A Short R Tutoria 24
,
ff
.
R has other typical ow-control statements, including if and if-else branching, while,
repeat, and for loops, break statements, and so on
The if test will let you run one or more statements if some condition is true. If there are
multiple statements, enclose them in curly braces
There is if-else test can let you act on a variety of conditions. Enclose the code for each
condition in curly braces
> if (x < 3) {
y <- a + b
z <- sqrt(x)
} else {
y <- a - b
z <- log(a + b)
}
Note that if this condition never becomes false, this will generate an in nite loop
Copy all of these commands (the line above, your code, the two lines above) into R in one
step. When your code executes, it will report how long it took
Always measure your code before you optimize it to understand the e ects of your optimiza-
tions. In some cases, code that seems like it ought to be faster might not be, and sometimes a
loop is faster than the alternative, as shown with variance above. Be aware that some R users
are dogmatic about avoiding loops. Instead of being dogmatic, measure your code and know
which solution is fastest
A Short R Tutoria 25
:
fl
l
.
ff
fi
.
Customizing
PACKAGES
A great advantage to the open-source nature of R is that users have contributed an astonish-
ing number of packages for solving a vast array of data analysis problems. For example, there
are packages speci cally directed to non-parametric statistics, signal processing, and ecologi-
cal analyses. Using these packages requires two steps.
First, they must be insta ed on your system, and this is a one-time step. Most packages can be
installed from the R site: http://CRAN.R-project.org/. On macOS, packages can be installed
through the package installer under the Packages & Data menu. To check which packages
have been installed and are available to be loaded, use the library() function
> library()
Second, once a package is installed, it must be loaded by calling the library() function
with the name of the library as an argument. The library is an object, not a string, so do not
enclose its name in quotes. For example, this is how you would load the vegan package, a use-
ful package for ecological analyses
> library(vegan)
A library must be loaded before any R session in which you would like to use its functions
Be aware that the correctness of code in these packages may not have been tested. Use trust-
ed packages rather than obscure ones, and verify your results
Packages are periodically updated, just as R is, so check to make sure that R and your pack-
ages are current. To check on the status of your packages, run packageStatus(), and to
update your packages, run update.packages() and follow the prompts
FUNCTION FILES
As you become familiar with R, you will write your own functions. To have easy access to
these, save your functions to a text le. These can be loaded into an R session with the
source() function. The r le su x can be lower-case or upper-case
> source('myfunctions.r')
I usually create one source le for each project, more for complex projects, and source()
lets these functions be loaded in one step, rather than copying and pasting the code
If you nd yourself typing the same commands at the beginning or end of every R session,
you can set up R to automatically execute those commands whenever it starts or quits by
editing your .First() and .Last() functions. Common commands to place in
your .First() function include loading any commonly used libraries or data sets, setting
A Short R Tutoria 26
fi
fi
l
ll
R
fi
fi
ffi
.
fi
the working directory, setting preferred graphics arguments, and loading any les of R func-
tions. Here is an example of a .First() function
This function loads a series of libraries routinely needed for analyses, sets the working direc-
tory, and loads a set of functions written by the user
On macOS and other UNIX/LINUX systems, the .First() and .Last() functions are
stored in a le called .Rpro le, which is an invisible le located at the root level of a user's
home directory (for example, /Users/username/). On Windows, these functions are stored in
Rpro le.site, which is kept in the C:\Program Files\R\R-n.n.n\etc directory. If the .Rpro le or
Rpro le.site le doesn’t exist on your system, you will need to create one as a plain text le
using a text editor. On macOS, Linux, and other UNIX-based systems, be sure to include the
period at the beginning of the le name.
A Short R Tutoria 27
fi
fi
fi
fi
l
fi
fi
:
fi
fi
fi
fi