Learning Objectives
- Explain what R and RStudio are, what they are used for, and how they relate to each other.
- Describe the purpose of the RStudio script, console, environment, and plots plane.
- Organize files and directories for a set of analyses as an R Project, and understand the purpose of a working directory.
- Use Google Drive and Google Desktop to access and modify files from multiple locations.
- Use the built in RStudio interface and online resources for more information on R functions.
- Create objects and assign them values in R.
- Save code in a script file for later use.
- Use comments to annotate script.
- Call functions and use arguments to change their default options.
- Inspect the content of vectors and manipulate their content.
- Subset and extract values from vectors.
R is a programming language. The term R is typically used to refer to the programming language but can also refer to the software that interprets scripts written using it. RStudio is an Integrated Development Environment (IDE) software program. It is a very popular way to interact with R because it organizes your scripts, environment, and output in an easy-to-use way. In the early days, we used simple command line interfaces to interact with R…which was no good, very bad, don’t do it. You can still see what this looks like by launching R (rather than RStudio) from your desktop. Then you can close it, and we can never speak of it again.
The learning curve on R is admittedly steeper than on almost any statistical software, but it is worth learning because the visualizations and analyses you create are free, endlessly customizable, and most importantly reproducible.
Most forms of statistical software (including ArcGIS) involve a lot of pointing and clicking. This makes them relatively user friendly for simple tasks. Here’s the problem: Think back to the last time you used software (e.g., Excel, Matlab, JMP, SigmaPlot, ArcGIS). How many clicks did it take to produce a single graph? Do you remember every click? (really though?) When you wrote a methods section for your lab report or paper, did you detail every click involved in running your analyses and generating your graphs? If I read your paper and tried to rerun your analysis, would I get every click correct? If you collected more data and needed to rerun your analysis, would you remember every click? Of course not!
R does not involve lots of pointing and clicking, and that’s a good thing!
Reproducibility is when someone else (including your future self) can obtain the same results from the same data using the same analysis. R stores your analysis as a series of written commands. So, if you want to redo your analysis because you collected more data, you don’t have to remember which button you clicked in which order to obtain your results. With a stored series of commands (in your script), you can repeat running them, and R will process the new data exactly the same way as before.
An increasing number of journals and funding agencies expect analyses to be reproducible, so knowing R will give you an edge with these requirements.
Working with scripts makes the steps you used in your analysis clear, and the code you write can be inspected by someone else who can give you feedback and spot mistakes.
Working with scripts forces you to have a deeper understanding of what you are doing, and facilitates your learning and comprehension of the methods you use.
Anyone can inspect the source code to see how R works. Because of this transparency, there is less chance for mistakes, and if you (or someone else) find some, you can report and fix bugs.
With 10,000+ packages that can be installed to extend its capabilities, R provides a framework that allows you to combine statistical approaches from many scientific disciplines to best suit the analytical framework you need to analyze your data. For instance, R has packages for image analysis, GIS, time series, population genetics, and a lot more.
The skills you learn with R scale easily with the size of your dataset. Whether your dataset has hundreds or millions of lines, it won’t make much difference to you. R is designed for data analysis. It comes with special data structures and data types that make handling of missing data and statistical factors convenient.
R can connect to spreadsheets, databases, and many other data formats, on your computer or on the web.
We will take a tour of the RStudio window, but first, let’s set up your project folder in Google Drive Desktop.
For this course, we will use your SUNY Plattsburgh Google Drive to save and back-up files. We will create one project folder for weekly course work, and you will set up a separate project folder later for your individual or group class project.
When you log into any school computer, you should see the pop-up window below. If not, you can double click the Google Drive icon on the desktop to launch it. Click “Sign in with browser.”
Sign in to Google Drive pop-up window
This will unfortunately launch Microsoft Edge, which is the default
browser on these computers. You can change the settings, but they will
change back overnight, so there’s really no point. Uncheck all the
boxes, select “Continue without data” and then Continue. Type your
Plattsburgh email address into the login screen, and choose next.
Entering your Plattsburgh email address will redirect you to the campus
login. Enter your net ID and password, and complete login using DUO
two-factor authentication. I generally choose not to “Trust Browser” if
I am working on a public computer.
At this point, the browser will remind you to make sure you have
installed the Google Drive app, which we have. So select “Sign in” to
complete the process. If you plan on working from your home computer,
you should make sure you download the Google Drive app to access your
files in R.
G:\ DriveAt this point, you can close the Browser, and click the Drive icon on
the desktop to open your Google Drive folder. This G:\
drive gives you access to all the files stored on your Google Drive, and
any shared Drives that you have access to. We will set up your class
project folder in your My Drive.
(Note that the Shared drives folder will be a powerful
tool for collaboration when working on your group project or with your
research advisor in the future!)
Google Drive (G:) in File Explorer
Open your My Drive and create a new folder called
“Environmental Data Analysis”
Now that you have created a project folder, let’s open RStudio and create a new project.
It is good practice to keep data, analyses, images, and text in a single folder, called the working directory. Any scripts you write and save in this folder can then use relative paths to files that indicate where inside the project folder a file is located (as opposed to absolute paths, which point to where a file is on a specific computer). This allows you to move your project folder around on your computer, or to other computers (e.g., work and home) and share it with others without worrying about whether or not your code will still work.
Setting up a project file, and opening your project file each time you code in R is absolutely critical because it will ensure that R looks for your files, and saves files, in the right place!
Open RStudio. Under the File menu, choose
New Project. This will launch the pop-up menu below.
Because you already have a folder on your G:\ that you
want to use, we will choose the second option,
Existing Directory. This will launch the following
pop-up:
Click Browse and navigate to your
Environmental Data Analysis folder. Then click
Create Project.
For this workshop, we will need a data_raw/ folder to
store our raw data, and we will use data/ for when we learn
how to export data as CSV files, and a fig/ folder for the
figures that we will save. You can create folders directly from RStudio
by clicking in the File panel on the
bottom right corner of your screen. Use this to create three folders
named
data_raw, data, and
fig.
When you open your GoogleDrive folder on the Desktop, you should see
that those three folders and your project file now exist in your
Environmental Data Analysis folder. Note that you could
also create folders and save files directly in your Google Drive. As you
move forward in this class, you may decide that you want to create
additional folders like workshops to save the html workshop
files like the one you’re using right now.
Now that we’ve set up your project folder, let’s take a step back and
look at the RStudio environment that you’re going to be working in.
Click on the icon and select
R Script. This will provide you with a workspace where you
can type and save code. You can also open a new script by typing
Ctrl + Shift + N. Once you have
opened a new script, you should see four main panels in your RStudio
window:
The basis of programming is that we write down instructions for the computer to follow, and then we tell the computer to follow those instructions. We write, or code, instructions in R because it is a common language that both the computer and we can understand (most of the time). We call the instructions commands and we tell the computer to follow the instructions by executing, or running those commands.
There are two main ways of interacting with R: by using the console or by using script files (plain text files that contain your code). Because we want our code and workflow to be reproducible, it is better to type the commands we want in the script editor, and save the script. This way, there is a complete record of what we did, and anyone (including our future selves!) can easily replicate the results on their computer.
You can think of the script as your work space. Here, you can enter, run, and save code. I recommend you never delete any code that works from your script. You can always copy and paste code and then make changes.
It is good practice to leave space between code chunks and tag lines
using a #. R will skip lines that begin with #
when running code. You can run any line of code by placing your cursor
on the line and typing Ctrl + Enter.
# I have tagged this line of code so that I can remember what I was doing when I come back to this project later!
Go ahead and save your script now. Hit
Ctrl + s. You will notice that this opens your
project folder. Save your script as something sensible, e.g.,
“A01 Intro to R”. This will save your script as a .R file, which you can
save and reopen at any time. Notice that if you have unsaved changes in
your script, the title on the tab will appear in red with a * at the end
of the file name. When you save changes (Ctrl +
s), the title will appear black again. It’s good practice
to save your changes at the end of a code block or every ~15 min.
The console pane (in RStudio, the bottom left panel) is the place where commands written in the R language can be typed and executed immediately by the computer. It is also where the results will be shown for commands that have been executed. You can type commands directly into the console and press Enter to execute those commands, but they will be forgotten when you close the session.
When you run code from a script, you will see the code and the output appear in the console. Code that has run will show up in blue (default). Warnings, errors, and messages will show up in red. Output will show up in black.
The environment will show a list of any objects or functions that you
create (more on this in a bit). In R, we create objects by giving them a
name, and then using <- to assign something to that
name. For example, in the code below, I create an object named
mary and assign the number 135 (my office number in Hudson)
to the object.
mary <- 135
mary
## [1] 135
Once I have created this object, it shows up in my Environment panel
as object mary. I can call that object by typing the object
name mary, and hitting Ctrl +
Enter. When you run this code, you should see the output
135 appear in the console.
The Files panel shows you all of the folders and
files in your project. The Plots panel shows plots that
you create. You can use the arrow buttons to revisit previous plots. The
Packages panel shows a list of packages that you have
installed. Packages contain additional functions programmers have
written that can help you to tidy your data, make pretty graphs, or run
more complicated analyses. You can install and update packages here, or
attach and detach packages from your project. However, it is best
practice to install and load packages from your script so that
you will have a record of packages that you need to run your code. We
will cover how to install and load a package later in this course. The
Help panel will display help files. This tool is very
useful for exploring options for functions that you use, or for help in
interpreting output. Type ?c() into your script and run it
to pull up the help file for the concatenate function, which we will use
later in this workshop.
You can get output from R simply by typing math in the script and running it:
3 + 5
12 / 7
However, to do useful and interesting things, we need to assign
values to objects. To create an object, we need to give
it a name followed by the assignment operator <-, and
the value we want to give it:
weight_kg <- 55
<- is the assignment operator. It assigns values on
the right to objects on the left. So, after executing
x <- 3, the value of x is 3.
For historical reasons, you can also use = for assignments,
but not in every context. Because of the slight differences in syntax,
it is good practice to always use <- for
assignments.
In RStudio, typing Alt + - will write
<- in a single keystroke in a PC, while typing
Option + - does the same in a Mac.
Objects can be given almost any name such as x,
current_temperature, or subject_id. Here are
some further guidelines on naming objects:
2x is not valid, but
x2 is).weight_kg is
different from Weight_kg.if,
else, for). In general, even if it’s allowed,
it’s best to not use other function names (e.g.,
c, T, mean, data,
df, weights). If in doubt, check the help to
see if the name is already in use..) within names. Many function
names in R itself have them and dots also have a special meaning in R
and other programming languages. To avoid confusion, don’t include dots
in names.When assigning a value to an object, R does not print anything. You can make R print the value by typing the object name:
weight_kg <- 55 # doesn't print anything to console
weight_kg # prints value of `weight_kg`
Now that R has weight_kg in memory, we can do math with
it. For instance, we may want to convert this weight into pounds (weight
in pounds is 2.2 times the weight in kg):
2.2 * weight_kg
We can also change an object’s value by assigning it a new one:
weight_kg <- 57.5
2.2 * weight_kg
This means that assigning a value to one object does not change the
values of other objects. For example, let’s store the animal’s weight in
pounds in a new object, weight_lb:
weight_lb <- 2.2 * weight_kg
and then change weight_kg to 100.
weight_kg <- 100
What do you think is the current content of the object weight_lb?
126.5 or 220? What happens if you run the
weight_lb <- 2.2 * weight_kg line of code again?
Functions are “canned scripts” that automate more
complicated sets of commands including mathematical operations, variable
assignments, etc. Many functions are predefined, or can be made
available by importing R packages (more on that later). A function
usually takes one or more inputs called arguments,
separated by commas. Functions often (but not always) return a value. A
typical example would be the function sqrt(). The input
(the argument) must be a number, and the return value (in fact, the
output) is the square root of that number. Executing a function
(‘running it’) is called calling the function. An
example of a function call is:
weight_kg <- sqrt(10)
Here, the value of 10 is given to the sqrt() function,
the sqrt() function calculates the square root, and returns
the value which is then assigned to the object weight_kg.
This function takes one argument, other functions might take
several.
The return ‘value’ of a function need not be numerical (like that of
sqrt()), and it also does not need to be a single item. It
can be a set of things, or even a dataset. We’ll see that when we read
data files into R.
Arguments can be anything, not only numbers or filenames, but also other objects. Exactly what each argument means differs from function to function, and must be looked up in the documentation (see below). Some functions take arguments which may either be specified by the user, or, if left out, take on a default value: these are called options. Options are typically used to alter the way the function operates, such as whether it ignores ‘bad values’, or what symbol to use in a plot. However, if you want something specific, you can specify a value of your choice which will be used instead of the default.
Let’s try a function that can take multiple arguments:
round().
round(3.14159)
## [1] 3
Here, we’ve called round() with just one argument,
3.14159, and it has returned the value 3.
That’s because the default is to round to the nearest whole number. If
we want more digits we can see how to do that by getting information
about the round function. We can use args(round) to find
what arguments it takes, or look at the help for this function using
?round.
args(round)
?round
We see that if we want a different number of digits, we can type
digits = 2 or however many we want.
round(3.14159, digits = 2)
## [1] 3.14
If you provide the arguments in the exact same order as they are defined you don’t have to name them:
round(3.14159, 2)
This practice is more typical for functions you use so often that you remember the order of the arguments. If you do name the arguments, you can switch their order, and the function still works fine.
round(digits = 2, x = 3.14159)
It’s good practice to put the non-optional arguments (like the number you’re rounding) first in your function call, and to then specify the names of all optional arguments. If you don’t, someone reading your code might have to look up the definition of a function with unfamiliar arguments to understand what you’re doing.
A vector is the most common and basic data type in
R, and is pretty much the workhorse of R. A vector is composed of a
series of values, which can be either numbers or characters. We can
assign a series of values to a vector using the concatenate function
c(). For example we can create a vector of animal weights
and assign it to a new object weight_g:
weight_g <- c(50, 60, 65, 82)
weight_g
A vector can also contain characters:
animals <- c("mouse", "rat", "dog")
animals
The quotes around “mouse”, “rat”, etc. are essential here.
Without the quotes R will assume objects have been created called
mouse, rat and dog. As these
objects don’t exist in R’s memory, there will be an error message.
There are many functions that allow you to inspect the content of a
vector. length() tells you how many elements are in a
particular vector:
length(weight_g)
length(animals)
An important feature of a vector, is that all of the elements are the
same type of data. The function class() indicates what kind
of object you are working with:
class(weight_g)
class(animals)
The function str() provides an overview of the structure
of an object and its elements. It is a useful function when working with
large and complex objects:
str(weight_g)
str(animals)
You can use the c() function to add other elements to
your vector:
weight_g <- c(weight_g, 90) # add to the end of the vector
weight_g <- c(30, weight_g) # add to the beginning of the vector
weight_g
In the first line, we take the original vector weight_g,
add the value 90 to the end of it, and save the result back
into weight_g. Then we add the value 30 to the
beginning, again saving the result back into weight_g.
We can do this over and over again to grow a vector, or assemble a dataset. As we program, this may be useful to add results that we are collecting or calculating.
An atomic vector is the simplest R data type and is
a linear vector of a single type. Above, we saw 2 of the 6 main atomic
vector types that R uses: "character" and
"numeric". These are the basic building blocks that all R
objects are built from. The other 4 atomic vector types are:
"logical" for TRUE and FALSE (the boolean data
type)"integer" for integer numbers (e.g., 2L, the L
indicates to R that it’s an integer)"complex" to represent complex numbers with real and
imaginary parts (e.g., 1 + 4i) and that’s all we’re going to
say about that (doesn’t come up a lot in data analysis with real
data)"raw" for bitstreams that we won’t discuss furtherYou can check the type of your vector using the typeof()
function and inputting your vector as the argument.
Vectors are one of the many data structures that R
uses. Other important ones are lists (list), matrices
(matrix), data frames (data.frame), factors
(factor) and arrays (array).
If we want to extract one or several values from a vector, we must provide one or several indices in square brackets. For instance:
animals <- c("mouse", "rat", "dog", "cat")
# Extract the second value from the animals vector
animals[2]
## [1] "rat"
# Extract the third and second values from the animals vector
animals[c(3, 2)]
## [1] "dog" "rat"
R indices start at 1. Programming languages like Fortran, MATLAB, Julia, and R start counting at 1, because that’s what human beings typically do. Languages in the C family (including C++, Java, Perl, and Python) count from 0 because that’s simpler for computers to do.
Another common way of subsetting is by using a logical vector.
TRUE will select the element with the same index, while
FALSE will not:
weight_g <- c(21, 34, 39, 54, 55)
weight_g[c(TRUE, FALSE, FALSE, TRUE, TRUE)]
## [1] 21 54 55
Typically, these logical vectors are not typed by hand, but are the output of other functions or logical tests. For instance, if you wanted to select only the values above 50:
# will return logicals with TRUE for the indices that meet the condition
weight_g > 50
## [1] FALSE FALSE FALSE TRUE TRUE
# so we can use this to select only the values above 50
weight_g[weight_g > 50]
## [1] 54 55
You can combine multiple tests using & (both
conditions are true, AND) or | (at least one of the
conditions is true, OR):
weight_g[weight_g > 30 & weight_g < 50]
## [1] 34 39
weight_g[weight_g <= 30 | weight_g == 55]
## [1] 21 55
weight_g[weight_g >= 30 & weight_g == 21]
## numeric(0)
Here, > stands for “greater than”, <
for “less than”, <= for “less than or equal to”, and
== for “equal to”. The double equal sign == is
a test for numerical equality between the left and right hand sides, and
should not be confused with the single = sign, which
performs variable assignment (similar to <-).
A common task is to search for certain strings in a vector. One could
use the “or” operator | to test for equality to multiple
values, but this can quickly become tedious. The function
%in% allows you to test if any of the elements of a search
vector are found:
animals <- c("mouse", "rat", "dog", "cat", "cat")
# return both rat and cat
animals[animals == "cat" | animals == "rat"]
## [1] "rat" "cat" "cat"
# return a logical vector that is TRUE for the elements within animals
# that are found in the character vector and FALSE for those that are not
animals %in% c("rat", "cat", "dog", "duck", "goat", "bird", "fish")
## [1] FALSE TRUE TRUE TRUE TRUE
# use the logical vector created by %in% to return elements from animals
# that are found in the character vector
animals[animals %in% c("rat", "cat", "dog", "duck", "goat", "bird", "fish")]
## [1] "rat" "dog" "cat" "cat"
As R was designed to analyze datasets, it includes the concept of
missing data (which is uncommon in other programming languages). Missing
data are represented in vectors as NA.
When doing operations on numbers, most functions will return
NA if the data you are working with include missing values.
This feature makes it harder to overlook the cases where you are dealing
with missing data. You can add the argument na.rm = TRUE to
calculate the result as if the missing values were removed
(rm stands for ReMoved) first. Try each of the following
operations for vector heights that includes a missing
value, and note the differences in output:
heights <- c(2, 4, 4, NA, 6)
mean(heights)
max(heights)
mean(heights, na.rm = TRUE)
max(heights, na.rm = TRUE)
If your data include missing values, which data nearly always do, you
may want to become familiar with the functions is.na(),
na.omit(), and complete.cases(). See below for
examples.
## Extract those elements which are not missing values.
heights[!is.na(heights)]
## Returns the object with incomplete cases removed.
#The returned object is an atomic vector of type `"numeric"`.
na.omit(heights)
## Extract those elements which are complete cases.
#The returned object is an atomic vector of type `"numeric"`.
heights[complete.cases(heights)]
Now that we have learned how to write scripts, and the basics of R’s data structures, we are ready to start working with real datasets. In the next unit, we will use the Portal dataset to apply these concepts to data frames.
The assignment this week contains two parts. Part one reviews the statistical tests that we covered in our first meeting. Part two reviews the concepts from this R workshop. The best way to complete part two is to try running the code in R. If you have time, I recommend you complete part two before leaving the workshop today!
For each of the following questions/objectives, select the best statistical test to analyze the data. (For now, assume that the data will meet the assumptions of the tests.)
The following questions will review basic vocabulary and functionality of the programming language R. We will be using this vocabulary throughout the semester.
3
to an object named three?
3 <- threethree <- 33 <- "three""three" <- 3mass_index
after executing the following lines of code?mass <- 30age <- 3mass <- mass * 2age <- age + 1mass_index <- mass/agemean(mass, na.rm = T)mean(mass)round(3.14159, digits = 2)round(3.14159)c(2, 3)vec <- c(1, 2, 3, 4)vec <- c(1, 2, 3, "red")vec <- c("red", "orange", "yellow", "green")vec <- c(T, F, T, F)vec <- c(T, F, T, "F")"cat" from the vector animals (below)? (More
than one answer may be true.)animals <- c("dog", "cat", "mouse", "rat", "platypus")
animals[2]animals(2)animals["cat"]animals[animals == "cat"]animals(animals == "cat")heights_no_na, that excludes any missing values from the
vector heights (below). (More than one answer may be
true.)heights <- c(63, 69, 60, 65, NA, 68, 61, 70, 61, 59, 64, 69, 63, 63, NA, 72, 65, 64, 70, 63, 65)
heights_no_na <- heights[!is.na(heights)]heights_no_na <- heights[complete.cases(heights)]heights_no_na <- !is.na(heights)heights_no_na <- complete.cases(heights)heights_no_na <- na.omit(heights)
Comments
At this point, I want to reemphasize the importance of annotating your code using comments. The comment character in R is
#. Anything to the right of a#in a script will be ignored by R. It is useful to leave notes and explanations in your scripts. This is a great tool for keeping notes as you work through this class! It is also good practice to keep notes so that you can remember what you were doing when you return to your code in the future, and so collaborators can understand what your code is doing (and help you fix it if it’s not doing that thing).Commenting can also be useful if you want to save code that you need to run once, but you don’t want to accidentally re-run it (e.g., code you used to install a package, or a plot that you made but don’t want to use). For convenience, RStudio provides a keyboard shortcut to comment or uncomment a paragraph: after selecting the lines you want to comment, press at the same time on your keyboard
Ctrl+Shift+C. If you only want to comment out one line, you can put the cursor at any location of that line (i.e., no need to select the whole line), then pressCtrl+Shift+C.