R Basics

Get the lesson R script: rbasics.R

Get the lesson data: download zip

View the lesson recording: recording

Lesson Exercises

Goals and Motivation

R is a language for statistical computing as well as a general purpose programming language. Increasingly, it has become one of the primary languages used in data science and for data analysis across many of the natural sciences.

The goals of this training are to expose you to fundamentals and to develop an appreciation of what’s possible with this software. We also provide resources that you can use for follow-up learning on your own. You should be able to answer these questions at the end of this session:

  • What is R and why should I use it?
  • Why would I use RStudio?
  • How can I write, save, and run scripts in RStudio?
  • Where can I go for help?
  • What are the basic data structures in R?
  • How do I import data?

Why should I invest time in R?

There are many programming languages available and each has it’s specific benefits. R was originally created as a statistical programming language but now it is largely viewed as a ‘data science’ language. Why would you invest time in learning R compared to other languages?

R is also an open-source programming language - not only is it free, but this means anybody can contribute to it’s development. As of 2021-04-12, there are 17407 supplemental packages for R on CRAN!

RStudio

In the old days, the only way to use R was directly from the Console - this is a bare bones way of running R only with direct input of commands. Now, RStudio is the go-to Interactive Development Environment (IDE) for R. Think of it like a car that is built around an engine. It is integrated with the R console (engine) and includes many other features to improve the user’s experience, such as code highlighting and completion, package manager and creation, version control, debugging, and dynamic documents.

Let’s get familiar with RStudio before we go on.

Open R and RStudio

If you haven’t done so, download and install RStudio from the link above. After it’s installed, find the RStudio shortcut and fire it up (just watch for now). You should see something like this:

There are four panes in RStudio:

  • Source: Your primary window for writing code to send to the console, this is where you write and save R “scripts”
  • Console: This is where code is executed in R - you should almost never write code here.
  • Environment, History, etc.: A tabbed window showing your working environment, code execution history, and other useful things
  • Files, plots, etc.: A tabbed window showing a file explorer, a plot window, list of installed packages, help files, and viewer

Scripting

In most cases, you will not enter and execute code directly in the console. Code can be written in a script and then sent directly to the console when you’re ready to run it. The key difference here is that a script can be saved and shared.

Open a new script from the File menu…

Executing code in RStudio

After you write code in your script, it can be sent to the Console to run the code in R. Anything you write in the script will not be run or saved in R until it is sent to the console. There are two ways to do this. First, you can hit the Run button at the top right of the scripting window. Second, you can use ctrl+enter (cmd+enter on a Mac). Both approaches will send the selected line to the console, then move to the next line in your script. You can also highlight and send an entire block of code.

Exercise 1

This exercise will make sure R and RStudio are working and that you can get around the basics in RStudio.

  1. Start RStudio if using a version you installed OR navigate to https://rstudio.cloud/project/2140348 if using RStudio Cloud. To start both R and RStudio requires only firing up RStudio. RStudio should be available from All Programs at the Start Menu. Fire up RStudio.

  2. If you’re not using RStudio Cloud, create a new project (File menu, New project, New directory, New project, Directory Name…). Name it “r_workshop”. We will use this for the rest of the workshop.

  3. Create a new “R Script” in the Source Pane, save that file into your newly created project and name it “first_script.R”. It’ll just be a blank text file at this point.

  4. Add in a comment line to separate this section. It should look something like: # Exercise 1: Just Getting used to RStudio and Scripts. Add some additional code that you can send to the console, e.g., try 1 + 1.

  5. Lastly, we need to get this project set up with some example data for our exercises (if you’re using RStudio Cloud, ignore this step). You should have downloaded this already, but if not, the data are available here. The data are in a zipped folder. Download the file to your computer (anywhere). Create a folder in your new project named data and extract the files into this location (there are several files).

R language fundamentals

R is built around functions. These are commands that do specific things based on what you provide. The basic syntax of a function follows the form: function_name(arg1, arg2, ...).

With the base install, you will gain access to many functions (2292, to be exact). Some examples:

# print
print('hello world!')
## [1] "hello world!"
# sequence
seq(1, 10)
##  [1]  1  2  3  4  5  6  7  8  9 10
# random numbers
rnorm(100, mean = 10, sd = 2)
##   [1] 14.569853 13.913440  8.255795  9.045516 11.810650 12.736531  6.858636
##   [8] 11.871014 10.233804  8.155321  8.760942  9.186733  9.645789  7.163662
##  [15]  9.044760  6.647533  8.903276 13.274406 10.013776  9.871183 12.498449
##  [22]  5.120401 10.405055  7.442277  6.438727 10.016774 10.670662 10.124157
##  [29]  7.324237  9.255008  6.549692  9.188994  8.667527  8.227980 14.198025
##  [36] 12.348068  6.801872 12.571909  9.977486  8.682623 11.247821  8.363380
##  [43]  6.660036  7.714498  8.527343 10.610565  9.488799 12.005517 10.193764
##  [50] 10.185408 11.429080  9.398920 11.666192 14.519987 10.759050  8.663776
##  [57] 10.401966 10.823552  9.554549  7.936093  8.703142  7.575200  4.808449
##  [64]  8.302505  9.906150  8.910085  8.401455  8.592140  9.599329 11.557543
##  [71] 10.412482 12.231374  8.777033 10.784013  9.794213  8.583790 10.962841
##  [78]  9.602027  8.728437  8.991741  9.502100  7.828449  8.011683  8.900650
##  [85]  9.749423 10.147798 11.441750  8.037719  6.459697 13.538514 10.717050
##  [92] 11.992981 11.407935  6.068502 10.146920  8.421186  9.071036  8.644649
##  [99] 11.107036  9.216956
# average 
mean(rnorm(100))
## [1] -0.008863516
# sum
sum(rnorm(100))
## [1] -11.28559

Very often you will see functions used like this:

my_random_sum <- sum(rnorm(100))

In this case the first part of the line is the name of an object. You make this up. Ideally it should have some meaning, but the only rules are that it can’t start with a number and must not have any spaces. The second bit, <-, is the assignment operator. This tells R to take the result of sum(rnorm(100)) and store it in an object named, my_random_sum. It is stored in the environment and can be used by just executing it’s name in the console.

my_random_sum
## [1] -11.74473

What is the environment?

There are two outcomes when you run code. First, the code will simply print output directly in the console. Second, there is no output because you have stored it as a variable using <-. Output that is stored is actually saved in the environment. The environment is the collection of named objects that are stored in memory for your current R session. Anything stored in memory will be accessible by it’s name without running the original script that was used to create it.

With this, you have the very basics of how we write R code and save objects that can be used later.

Packages

The base install of R is quite powerful, but you will soon have a need or desire to go beyond this. Packages provide this ability. They are a standardized way of extending R with new methods, techniques, and programming functionality. There is a lot to say about packages regarding finding them, using them, etc., but for now let’s focus just on the basics.

CRAN

One of the reasons for R’s popularity is CRAN, The Comprehensive R Archive Network. This is where you download R and also where most will gain access to packages (there are other places, but that is for later). Not much else to say about this now other than to be aware of it. As of 2021-04-12, there are 17407 packages on CRAN!

Installing packages

When a package gets installed, that means the source code is downloaded and put into your library. A default library location is set for you so no need to worry about that. In fact, on Windows most of this is pretty automatic. Let’s give it a shot.

Exercise 2

We’re going to install some packages from CRAN that will give us the tools for our workshop today. We’ll use the tidyverse, SWMPr, and WtRegDO packages (the remotes package is only needed to install WtRegDO from GitHub). Later, we’ll explain in detail what each of these packages provide. Again, if you are using RStudio Cloud, these packages will already be installed. You can skip to step 5 in this case.

  1. At the top of the script you just created, type the following functions.

    # install packages
    install.packages(c("tidyverse", "SWMPr", "remotes"))
    remotes::install_github("fawda123/WtRegDO")
  2. Select all the lines by clicking and dragging the mouse pointer over the text.

  3. Send all the commands to the console using ctrl+enter. You should see some text output on the console about the installation process. The installation may take a few minutes so don’t be alarmed.

  4. After the packages are done installing, verify that there were no errors during the process (this should be pretty obvious, i.e., error text in big scary red letters).

  5. Load the packages after they’ve installed. Do not load remotes, it was only needed to install WtRegDO from GitHub.

    library("tidyverse")
    library("SWMPr")
    library("WtRegDO")

An important aspect of packages is that you only need to download them once, but every time you start RStudio you need to load them with the library() function. Loading a package makes all of its functions available in your current R session.

Getting Help

Being able to find help and interpret that help is probably one of the most important skills for learning a new language. R is no different. Help on functions and packages can be accessed directly from R, can be found on CRAN and other official R resources, searched on Google, found on StackOverflow, or from any number of fantastic online resources. I will cover a few of these here.

Help from the console

Getting help from the console is straightforward and can be done numerous ways.

# Using the help command/shortcut
# When you know the name of a function
help("print") # Help on the print command
?print # Help on the print command using the `?` shortcut

# When you know the name of the package
help(package = "sf") # Help on the package `dplyr`

# Don't know the exact name or just part of it
apropos("print") # Returns all available functions with "print" in the name
??print # shortcut, but also searches demos and vignettes in a formatted page

Official R Resources

In addition to help from within R itself, CRAN and the R-Project have many resources available for support. Two of the most notable are the mailing lists and the task views.

  • R Help Mailing List: The main mailing list for R help. Can be a bit daunting and some (although not most) senior folks can be, um, curmudgeonly…
  • R-sig-ecology: A special interest group for use of R in ecology. Less daunting than the main help with participation from some big names in ecological modelling and statistics (e.g., Ben Bolker, Gavin Simpson, and Phil Dixon).
  • Environmetrics Task View: Task views are great in that they provide an annotated list of packages relevant to a particular field. This one is maintained by Gavin Simpson and has great info on packages relevant to the environmental sciences.
  • Spatial Analysis Task View: One I use a lot that lists all the relevant packages for spatial analysis, GIS, and Remote Sensing in R.

Google and StackOverflow

While the resources already mentioned are useful, often the quickest way is to just turn to Google. However, a search for “R” is a bit challenging. A few ways around this. Google works great if you search for a given package or function name. You can also search for mailing lists directly (i.e. “R-sig-geo”), although Google often finds results from these sources.

Blind googling can require a bit of strategy to get the info you want. Some pointers:

  • Always preface the search with “r”
  • Understand which sources are reliable
  • Take note of the number of hits and date of a web page
  • When in doubt, search with the exact error message (see here for details about warnings vs errors)

One specific resource that I use quite a bit is StackOverflow with the ‘r’ tag. StackOverflow is a discussion forum for all things related to programming. You can then use this tag and the search functions in StackOverflow and find answers to almost anything you can think of. However, these forums are also very strict and I typically use them to find answers, not to ask questions.

Other Resources

As I mentioned earlier, there are TOO many resources to list here and everyone has their favorites. Below are just a few that I like.

  • R For Cats: Basic introduction site, meant to be a gentle and light-hearted introduction
  • WTF about R: What they forgot to teach you about R, some basics of using R in the wild.
  • R for Data Science: My favorite resource for learning data science methods with R, focusing on the tidyverse.
  • Advanced R: Web home of Hadley Wickham’s book, the same author of R for Data Science. Gets into more advanced topics, but also covers the basics in a great way.
  • CRAN Cheatsheets: A good cheat sheet from the official source
  • RStudio Cheatsheets: Additional cheat sheets from RStudio. I am especially fond of the data wrangling one.

Data structures in R

Now that you know how to get started in R and where to find resources, we can begin talking about R data structures. Simply put, a data structure is a way for programming languages to handle information storage.

There is a bewildering amount of formats for storing data and R is no exception. Understanding the basic building blocks that make up data types is essential. All functions in R require specific types of input data and the key to using functions is knowing how these types relate to each other.

Vectors (one-dimensional data)

The basic data format in R is a vector - a one-dimensional grouping of elements that have the same type. These are all vectors and they are created with the c (concatenate) function:

dbl_var <- c(1, 2.5, 4.5)
int_var <- c(1L, 6L, 10L)
log_var <- c(TRUE, FALSE, T, F)
chr_var <- c("a", "b", "c")

The four types of atomic vectors (think atoms that make up a molecule aka vector) are double (or numeric), integer, logical, and character. For most purposes you can ignore the integer class, so there are basically three types. Each type has some useful properties:

class(dbl_var)
## [1] "numeric"
length(log_var)
## [1] 4

These properties are useful for not only describing an object, but they define limits on which functions or types of operations that can be used. That is, some functions require a character string input while others require a numeric input. Similarly, vectors of different types or properties may not play well together. Let’s look at some examples:

# taking the mean of a character vector
mean(chr_var)

# adding two numeric vectors of different lengths
vec1 <- c(1, 2, 3, 4)
vec2 <- c(2, 3, 5)
vec1 + vec2

2-dimensional data

A collection of vectors represented as one data object are often described as two-dimensional data, or in R speak, a data frame (i.e., data.frame()). Think of them like your standard spreadsheet, where each column describes a variable (vector) and rows link observations between columns. Here’s a simple example:

ltrs <- c('a', 'b', 'c')
nums <- c(1, 2, 3)
logs <- c(T, F, T)
mydf <- data.frame(ltrs, nums, logs)
mydf
##   ltrs nums  logs
## 1    a    1  TRUE
## 2    b    2 FALSE
## 3    c    3  TRUE

The only constraints required to make a data frame are:

  1. Each column (vector) contains the same type of data

  2. The number of observations in each column is equal.

Getting your data into R

It is the rare case when you manually enter your data in R, not to mention impractical for most datasets. Most data analysis workflows typically begin with importing a dataset from an external source. Literally, this means committing a dataset to memory (i.e., storing it as a variable) as one of R’s data structure formats.

Flat data files (text only, rectangular format) present the least complications on import because there is very little to assume about the structure of the data. On import, R tries to guess the data type for each column and this is fairly unambiguous with flat files. In this lesson, we’ll be using read_csv() function from the readr package that comes with the tidyverse. Later we’ll use the SWMPr package to import SWMP data.

The working directory

Before we import data, we need to talk about the “working directory”. Whenever RStudio is opened, it uses a file location on your computer to access and save data. If you’re using an RStudio project, the working directory will be the folder where you created the project. If not, it is probably the the user’s home directory (e.g., C:/Users/Marcus), which you’ll want to change to where you have your data.

You can see your working directory with the getwd() function or from the file path at the top of the console in RStudio. All files in the File pane window on the bottom right of RStudio are also those within the working directory. If you want to change your working directory, you can use the setwd() function and put the file path (as a character string) inside the function, e.g., setwd('C:/Users/Marcus/Desktop/newdirectory').

The working directory is important to know when you’re importing or exporting data. When you import data, a relative file path can be used that is an extension of the working directory. For example, if your working directory is 'C:/Users/Marcus/Desktop' and you have a file called mydata.csv in that directory, you can use read_csv('mydata.csv') to import the file. Alternatively, if there’s a folder called “data” in your working directory with the file you want to import, you would use read_csv('data/mydata.csv').

If you want to import a file that is not in your working directory, you will have to use an absolute path that is the full file location. Otherwise, R will not know where to look outside of the working directory.

Exercise 3

Now that we have the data downloaded and extracted to our data folder, we’ll use read_csv to import two files into our environment. The read_csv function comes with the tidyverse package, so make sure that package is loaded (i.e., library(tidyverse)) before you do this exercise. This should have been done in the second exercise.

  1. Type the following in your script. Note the use of relative file paths within your project (see the explanation above).

    apacpwq2019 <- read_csv('data/apacpwq2019.csv')
    sapcawq2019 <- read_csv('data/sapcawq2019.csv')
  2. Send the commands to the console with ctrl+enter.

  3. Verify that the data imported correctly by viewing the first six rows of each dataset. Use the head() function directly in the console, e.g., head(apacpwq2019) or head(sapcawq2019)

Let’s explore the datasets a bit. There are many useful functions for exploring the characteristics of a dataset. This is always a good idea when you first import something.

# get the dimensions
dim(apacpwq2019)
## [1] 35040    31
dim(sapcawq2019)
## [1] 35040    31
# get the column names
names(apacpwq2019)
##  [1] "StationCode"     "isSWMP"          "DateTimeStamp"   "Historical"     
##  [5] "ProvisionalPlus" "F_Record"        "Temp"            "F_Temp"         
##  [9] "SpCond"          "F_SpCond"        "Sal"             "F_Sal"          
## [13] "DO_Pct"          "F_DO_Pct"        "DO_mgl"          "F_DO_mgl"       
## [17] "Depth"           "F_Depth"         "cDepth"          "F_cDepth"       
## [21] "Level"           "F_Level"         "cLevel"          "F_cLevel"       
## [25] "pH"              "F_pH"            "Turb"            "F_Turb"         
## [29] "ChlFluor"        "F_ChlFluor"      "X31"
names(sapcawq2019)
##  [1] "StationCode"     "isSWMP"          "DateTimeStamp"   "Historical"     
##  [5] "ProvisionalPlus" "F_Record"        "Temp"            "F_Temp"         
##  [9] "SpCond"          "F_SpCond"        "Sal"             "F_Sal"          
## [13] "DO_Pct"          "F_DO_Pct"        "DO_mgl"          "F_DO_mgl"       
## [17] "Depth"           "F_Depth"         "cDepth"          "F_cDepth"       
## [21] "Level"           "F_Level"         "cLevel"          "F_cLevel"       
## [25] "pH"              "F_pH"            "Turb"            "F_Turb"         
## [29] "ChlFluor"        "F_ChlFluor"      "X31"
# see the first six rows
head(apacpwq2019)
## # A tibble: 6 x 31
##   StationCode isSWMP DateTimeStamp   Historical ProvisionalPlus F_Record  Temp
##   <chr>       <chr>  <chr>                <dbl>           <dbl> <chr>    <dbl>
## 1 apacpwq     P      01/01/2019 0:00          1               1 {CWD}     18.1
## 2 apacpwq     P      01/01/2019 0:15          1               1 {CWD}     18.1
## 3 apacpwq     P      01/01/2019 0:30          1               1 {CWD}     18  
## 4 apacpwq     P      01/01/2019 0:45          1               1 {CWD}     18.1
## 5 apacpwq     P      01/01/2019 1:00          1               1 {CWD}     18.2
## 6 apacpwq     P      01/01/2019 1:15          1               1 {CWD}     18.2
## # … with 24 more variables: F_Temp <chr>, SpCond <dbl>, F_SpCond <chr>,
## #   Sal <dbl>, F_Sal <chr>, DO_Pct <dbl>, F_DO_Pct <chr>, DO_mgl <dbl>,
## #   F_DO_mgl <chr>, Depth <dbl>, F_Depth <chr>, cDepth <lgl>, F_cDepth <chr>,
## #   Level <lgl>, F_Level <chr>, cLevel <lgl>, F_cLevel <lgl>, pH <dbl>,
## #   F_pH <chr>, Turb <dbl>, F_Turb <chr>, ChlFluor <lgl>, F_ChlFluor <chr>,
## #   X31 <lgl>
head(sapcawq2019)
## # A tibble: 6 x 31
##   StationCode isSWMP DateTimeStamp   Historical ProvisionalPlus F_Record  Temp
##   <chr>       <chr>  <chr>                <dbl>           <dbl> <lgl>    <dbl>
## 1 sapcawq     P      01/01/2019 0:00          0               1 NA        16.6
## 2 sapcawq     P      01/01/2019 0:15          0               1 NA        16.4
## 3 sapcawq     P      01/01/2019 0:30          0               1 NA        16.4
## 4 sapcawq     P      01/01/2019 0:45          0               1 NA        16.3
## 5 sapcawq     P      01/01/2019 1:00          0               1 NA        16.3
## 6 sapcawq     P      01/01/2019 1:15          0               1 NA        16.2
## # … with 24 more variables: F_Temp <chr>, SpCond <dbl>, F_SpCond <chr>,
## #   Sal <dbl>, F_Sal <chr>, DO_Pct <dbl>, F_DO_Pct <chr>, DO_mgl <dbl>,
## #   F_DO_mgl <chr>, Depth <dbl>, F_Depth <chr>, cDepth <dbl>, F_cDepth <chr>,
## #   Level <lgl>, F_Level <chr>, cLevel <lgl>, F_cLevel <lgl>, pH <dbl>,
## #   F_pH <chr>, Turb <dbl>, F_Turb <chr>, ChlFluor <lgl>, F_ChlFluor <chr>,
## #   X31 <lgl>
# get the overall structure
str(apacpwq2019)
## spec_tbl_df[,31] [35,040 × 31] (S3: spec_tbl_df/tbl_df/tbl/data.frame)
##  $ StationCode    : chr [1:35040] "apacpwq" "apacpwq" "apacpwq" "apacpwq" ...
##  $ isSWMP         : chr [1:35040] "P" "P" "P" "P" ...
##  $ DateTimeStamp  : chr [1:35040] "01/01/2019 0:00" "01/01/2019 0:15" "01/01/2019 0:30" "01/01/2019 0:45" ...
##  $ Historical     : num [1:35040] 1 1 1 1 1 1 1 1 1 1 ...
##  $ ProvisionalPlus: num [1:35040] 1 1 1 1 1 1 1 1 1 1 ...
##  $ F_Record       : chr [1:35040] "{CWD}" "{CWD}" "{CWD}" "{CWD}" ...
##  $ Temp           : num [1:35040] 18.1 18.1 18 18.1 18.2 18.2 18.2 18.2 18.3 18.2 ...
##  $ F_Temp         : chr [1:35040] "<0> [GSM] (CWD)" "<0> [GSM] (CWD)" "<0> [GSM] (CWD)" "<0> [GSM] (CWD)" ...
##  $ SpCond         : num [1:35040] 26.8 27.6 27.8 28 27.7 ...
##  $ F_SpCond       : chr [1:35040] "<0> [GSM] (CWD)" "<0> [GSM] (CWD)" "<0> [GSM] (CWD)" "<0> [GSM] (CWD)" ...
##  $ Sal            : num [1:35040] 16.5 17 17.1 17.3 17.1 16.9 16.9 16.7 15.9 16.8 ...
##  $ F_Sal          : chr [1:35040] "<0> [GSM] (CWD)" "<0> [GSM] (CWD)" "<0> [GSM] (CWD)" "<0> [GSM] (CWD)" ...
##  $ DO_Pct         : num [1:35040] 97.4 96.4 95.8 96.8 97.2 96.8 96.7 95.7 95.4 95.4 ...
##  $ F_DO_Pct       : chr [1:35040] "<0> [GSM] (CWD)" "<0> [GSM] (CWD)" "<0> [GSM] (CWD)" "<0> [GSM] (CWD)" ...
##  $ DO_mgl         : num [1:35040] 8.3 8.2 8.2 8.3 8.3 8.3 8.2 8.2 8.2 8.1 ...
##  $ F_DO_mgl       : chr [1:35040] "<0> [GSM] (CWD)" "<0> [GSM] (CWD)" "<0> [GSM] (CWD)" "<0> [GSM] (CWD)" ...
##  $ Depth          : num [1:35040] 1.06 1.05 1.04 1.02 1.01 0.99 0.96 0.94 0.91 0.89 ...
##  $ F_Depth        : chr [1:35040] "<1> [GSM] (CWD)" "<1> [GSM] (CWD)" "<1> [GSM] (CWD)" "<1> [GSM] (CWD)" ...
##  $ cDepth         : logi [1:35040] NA NA NA NA NA NA ...
##  $ F_cDepth       : chr [1:35040] "<-2> [GCM]" "<-2> [GCM]" "<-2> [GCM]" "<-2> [GCM]" ...
##  $ Level          : logi [1:35040] NA NA NA NA NA NA ...
##  $ F_Level        : chr [1:35040] "<-1>" "<-1>" "<-1>" "<-1>" ...
##  $ cLevel         : logi [1:35040] NA NA NA NA NA NA ...
##  $ F_cLevel       : logi [1:35040] NA NA NA NA NA NA ...
##  $ pH             : num [1:35040] 7.9 7.9 7.9 7.9 7.9 7.9 7.9 7.9 7.8 7.9 ...
##  $ F_pH           : chr [1:35040] "<0> [GSM] (CWD)" "<0> [GSM] (CWD)" "<0> [GSM] (CWD)" "<0> [GSM] (CWD)" ...
##  $ Turb           : num [1:35040] 2 2 2 2 2 2 2 2 2 2 ...
##  $ F_Turb         : chr [1:35040] "<0> [GSM] (CWD)" "<0> [GSM] (CWD)" "<0> [GSM] (CWD)" "<0> [GSM] (CWD)" ...
##  $ ChlFluor       : logi [1:35040] NA NA NA NA NA NA ...
##  $ F_ChlFluor     : chr [1:35040] "<-1>" "<-1>" "<-1>" "<-1>" ...
##  $ X31            : logi [1:35040] NA NA NA NA NA NA ...
##  - attr(*, "problems")= tibble[,5] [11,504 × 5] (S3: tbl_df/tbl/data.frame)
##   ..$ row     : int [1:11504] 21455 21456 21457 21458 21459 21460 21461 21462 21463 21464 ...
##   ..$ col     : chr [1:11504] "cDepth" "cDepth" "cDepth" "cDepth" ...
##   ..$ expected: chr [1:11504] "1/0/T/F/TRUE/FALSE" "1/0/T/F/TRUE/FALSE" "1/0/T/F/TRUE/FALSE" "1/0/T/F/TRUE/FALSE" ...
##   ..$ actual  : chr [1:11504] "2.10" "2.11" "2.11" "2.11" ...
##   ..$ file    : chr [1:11504] "'data/apacpwq2019.csv'" "'data/apacpwq2019.csv'" "'data/apacpwq2019.csv'" "'data/apacpwq2019.csv'" ...
##  - attr(*, "spec")=
##   .. cols(
##   ..   StationCode = col_character(),
##   ..   isSWMP = col_character(),
##   ..   DateTimeStamp = col_character(),
##   ..   Historical = col_double(),
##   ..   ProvisionalPlus = col_double(),
##   ..   F_Record = col_character(),
##   ..   Temp = col_double(),
##   ..   F_Temp = col_character(),
##   ..   SpCond = col_double(),
##   ..   F_SpCond = col_character(),
##   ..   Sal = col_double(),
##   ..   F_Sal = col_character(),
##   ..   DO_Pct = col_double(),
##   ..   F_DO_Pct = col_character(),
##   ..   DO_mgl = col_double(),
##   ..   F_DO_mgl = col_character(),
##   ..   Depth = col_double(),
##   ..   F_Depth = col_character(),
##   ..   cDepth = col_logical(),
##   ..   F_cDepth = col_character(),
##   ..   Level = col_logical(),
##   ..   F_Level = col_character(),
##   ..   cLevel = col_logical(),
##   ..   F_cLevel = col_logical(),
##   ..   pH = col_double(),
##   ..   F_pH = col_character(),
##   ..   Turb = col_double(),
##   ..   F_Turb = col_character(),
##   ..   ChlFluor = col_logical(),
##   ..   F_ChlFluor = col_character(),
##   ..   X31 = col_logical()
##   .. )
str(sapcawq2019)
## spec_tbl_df[,31] [35,040 × 31] (S3: spec_tbl_df/tbl_df/tbl/data.frame)
##  $ StationCode    : chr [1:35040] "sapcawq" "sapcawq" "sapcawq" "sapcawq" ...
##  $ isSWMP         : chr [1:35040] "P" "P" "P" "P" ...
##  $ DateTimeStamp  : chr [1:35040] "01/01/2019 0:00" "01/01/2019 0:15" "01/01/2019 0:30" "01/01/2019 0:45" ...
##  $ Historical     : num [1:35040] 0 0 0 0 0 0 0 0 0 0 ...
##  $ ProvisionalPlus: num [1:35040] 1 1 1 1 1 1 1 1 1 1 ...
##  $ F_Record       : logi [1:35040] NA NA NA NA NA NA ...
##  $ Temp           : num [1:35040] 16.6 16.4 16.4 16.3 16.3 16.2 16.1 15.9 15.7 15.6 ...
##  $ F_Temp         : chr [1:35040] "<0>" "<0>" "<0>" "<0>" ...
##  $ SpCond         : num [1:35040] 41.5 41.5 41.4 41 40.4 ...
##  $ F_SpCond       : chr [1:35040] "<0>" "<0>" "<0>" "<0>" ...
##  $ Sal            : num [1:35040] 26.6 26.6 26.6 26.3 25.8 25.5 25.7 25.6 25.6 25.1 ...
##  $ F_Sal          : chr [1:35040] "<0>" "<0>" "<0>" "<0>" ...
##  $ DO_Pct         : num [1:35040] 93.7 94.5 94.6 96.1 97.2 98.5 99.1 98.3 97.4 96.6 ...
##  $ F_DO_Pct       : chr [1:35040] "<0>" "<0>" "<0>" "<0>" ...
##  $ DO_mgl         : num [1:35040] 7.8 7.9 7.9 8 8.2 8.3 8.4 8.3 8.3 8.2 ...
##  $ F_DO_mgl       : chr [1:35040] "<0>" "<0>" "<0>" "<0>" ...
##  $ Depth          : num [1:35040] 1.98 2.09 2.2 2.36 2.49 2.63 2.76 2.9 3.04 3.15 ...
##  $ F_Depth        : chr [1:35040] "<0>" "<0>" "<0>" "<0>" ...
##  $ cDepth         : num [1:35040] 1.91 2.02 2.13 2.29 2.42 2.56 2.69 2.83 2.97 3.08 ...
##  $ F_cDepth       : chr [1:35040] "<3>" "<3>" "<3>" "<3>" ...
##  $ Level          : logi [1:35040] NA NA NA NA NA NA ...
##  $ F_Level        : chr [1:35040] "<-1>" "<-1>" "<-1>" "<-1>" ...
##  $ cLevel         : logi [1:35040] NA NA NA NA NA NA ...
##  $ F_cLevel       : logi [1:35040] NA NA NA NA NA NA ...
##  $ pH             : num [1:35040] 7.7 7.7 7.7 7.7 7.7 7.8 7.8 7.8 7.8 7.8 ...
##  $ F_pH           : chr [1:35040] "<0>" "<0>" "<0>" "<0>" ...
##  $ Turb           : num [1:35040] 1 0 3 4 4 5 6 6 7 5 ...
##  $ F_Turb         : chr [1:35040] "<0>" "<0>" "<0>" "<0>" ...
##  $ ChlFluor       : logi [1:35040] NA NA NA NA NA NA ...
##  $ F_ChlFluor     : chr [1:35040] "<-1>" "<-1>" "<-1>" "<-1>" ...
##  $ X31            : logi [1:35040] NA NA NA NA NA NA ...
##  - attr(*, "spec")=
##   .. cols(
##   ..   StationCode = col_character(),
##   ..   isSWMP = col_character(),
##   ..   DateTimeStamp = col_character(),
##   ..   Historical = col_double(),
##   ..   ProvisionalPlus = col_double(),
##   ..   F_Record = col_logical(),
##   ..   Temp = col_double(),
##   ..   F_Temp = col_character(),
##   ..   SpCond = col_double(),
##   ..   F_SpCond = col_character(),
##   ..   Sal = col_double(),
##   ..   F_Sal = col_character(),
##   ..   DO_Pct = col_double(),
##   ..   F_DO_Pct = col_character(),
##   ..   DO_mgl = col_double(),
##   ..   F_DO_mgl = col_character(),
##   ..   Depth = col_double(),
##   ..   F_Depth = col_character(),
##   ..   cDepth = col_double(),
##   ..   F_cDepth = col_character(),
##   ..   Level = col_logical(),
##   ..   F_Level = col_character(),
##   ..   cLevel = col_logical(),
##   ..   F_cLevel = col_logical(),
##   ..   pH = col_double(),
##   ..   F_pH = col_character(),
##   ..   Turb = col_double(),
##   ..   F_Turb = col_character(),
##   ..   ChlFluor = col_logical(),
##   ..   F_ChlFluor = col_character(),
##   ..   X31 = col_logical()
##   .. )

You can also view each dataset in a spreadsheet style in the scripting window:

View(apacpwq2019)
View(sapcawq2019)

Other ways to import data

You might want to import an Excel spreadsheet as well. In the old days, importing spreadsheets into R was almost impossible given the proprietary data structure used by Microsoft. The tools available in R have since matured and it’s now pretty painless to import a spreadsheet. The readxl package is the most recent and by far most flexible data import package for Excel files. It comes with the tidyverse family of packages.

Once installed, we can load it to access the import functions.

library(readxl)
dat <- read_excel('location/of/excel/file.xlsx')

Summary

In this lesson we learned about R and Rstudio, some of the basic syntax and data structures in R, and how to import files. We’ve just imported some water quality files from Apalachicola and Sapelo Island. Next we’ll learn how to import these data with SWMPr and prepare the data for further analysis.