R

This page has two parts:

  1. Setting up your environment: installing R, RStudio and Quarto, learning how we organise files and paths, and installing all the packages used in the course. Everyone needs to complete this part before the first lab.
  2. R basics: a short introduction to R objects, data types and data structures. If you are new to R, work through it before the first lab. If you have used R before, skim it as a refresher.

Setting up your environment

Software

To run the code in this course in R, you need the following software:

  • R: the latest release (version 4.5 or later)
  • RStudio Desktop: the latest release
  • Quarto: bundled with recent versions of RStudio, so you normally don’t need to install it separately
  • The R packages listed in Installing packages below

To install or update:

To check your version of:

  • R and loaded packages: run sessionInfo() in the Console
  • RStudio: click Help on the menu bar and then About RStudio
  • Quarto: in the RStudio Terminal tab (not the Console), run quarto --version

RStudio

Upon startup, RStudio will look something like this. The Pane Layout and Appearance settings can be changed under Tools > Global Options > Pane Layout and Tools > Global Options > Appearance (on macOS, this is also available under RStudio > Settings). I personally like to have my Console in the top right corner and Environment in the bottom left, and keep the Source and Environment panes wider than Console and Files for easier readability. Default settings will probably have the Console in the bottom left and Environment in the top right. You will also have a standard white background, but you can choose a different editor theme under Appearance.

RStudio at startup

At the start of a session, it’s good practice to start from a clean R environment. You can clear all objects with:

Code
rm(list = ls())
Tip

To make sure every session starts clean, go to Tools > Global Options > General and untick Restore .RData into workspace at startup, and set Save workspace to .RData on exit to Never.

Working in Quarto documents with relative paths

In this course we write all our code in Quarto documents (.qmd) rather than R scripts (.R). A Quarto document lets you mix text, code and outputs (tables, maps, plots) in one file, and render it to an HTML page with the Render button. This is also the format you will use for your assignments, which are submitted as HTML files, so getting used to it now will make things much easier later.

We also work with relative paths, which means file paths are written relative to where your document is saved (e.g. data/London/Tables/...) rather than as full paths on your computer (e.g. C:/Users/yourname/Documents/...). Relative paths mean your code keeps working if you move the course folder, and it will run on someone else’s computer too.

The key rule is simple: code in a Quarto document runs from the folder where the .qmd file is saved. So you don’t need setwd(); you just need to save your .qmd in the right place. The easiest set-up is to save your .qmd files in the main course folder, next to the data folder:

envs363_563/
├── data/
│   └── London/
│       └── Tables/
│           └── Densities_UK_cities.csv
├── lab_01.qmd
└── lab_02.qmd

From lab_01.qmd, the path to the csv file is then simply "data/London/Tables/Densities_UK_cities.csv". If you prefer to keep your .qmd files in a subfolder (e.g. labs/), use .. to go up one level first: "../data/London/Tables/Densities_UK_cities.csv".

To create a new Quarto document in RStudio, go to File > New File > Quarto Document…, then save it in your course folder. You can check which folder your code is running from by running getwd() in a code chunk:

Code
getwd()

Checking the working directory
Tip

Opening the course folder as an RStudio Project (File > New Project > Existing Directory) keeps the Files pane, Console and Terminal pointed at your course folder, which makes it easier to find your files. Open it by double-clicking the .Rproj file.

Important

Avoid setwd() and full paths (e.g. "C:/Users/yourname/..." or "~/Desktop/...") in your Quarto documents. They will break as soon as the file is moved or opened on another computer, including when your assignment is marked.

Installing packages

In R, packages are collections of functions, compiled code and sample data. They act as “extensions” to the base R language and cover almost anything you might want to do in R (and if no package serves your purpose, you can write your own!).

There are two steps to using a package, and it helps to keep them apart:

  • A package only needs to be installed once on your computer, with install.packages(). Run this in the Console, not in your .qmd, otherwise R will try to reinstall the package every time you render your document.
  • A package needs to be loaded with library() every time you start a new R session or render a Quarto document. This goes at the top of your .qmd.
Code
# Run once, in the Console
install.packages("tidyverse")
Code
# At the top of every .qmd that uses it
library(tidyverse)
── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
✔ dplyr     1.1.4     ✔ readr     2.1.5
✔ forcats   1.0.0     ✔ stringr   1.5.1
✔ ggplot2   4.0.0     ✔ tibble    3.3.0
✔ lubridate 1.9.4     ✔ tidyr     1.3.1
✔ purrr     1.1.0     
── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
✖ dplyr::filter() masks stats::filter()
✖ dplyr::lag()    masks stats::lag()
ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors

The packages used in this course are listed below, grouped by what they are used for:

Purpose Packages
Data wrangling tidyverse, dplyr, tidyr, tibble, readr, data.table, R.utils
Spatial vector data sf, geojsonsf, osmdata
Raster data terra, raster, exactextractr, tidyterra
Maps and plots tmap, ggplot2, ggspatial, mapview, basemapR, rosm, patchwork, GGally
Colours and classification RColorBrewer, viridis, colorspace, classInt
Spatial statistics spdep, rgeoda, gstat, spatstat, eks
Clustering cluster, dbscan, fpc
Networks igraph, tidygraph

Install all of them by running the code below in the RStudio Console. It only installs the packages you don’t already have, so it is safe to run more than once. The first run can take a while.

Code
# Packages available on CRAN
cran_packages <- c(
  "tidyverse", "data.table", "sf", "tmap", "readr", "geojsonsf", "osmdata",
  "RColorBrewer", "classInt", "R.utils", "dplyr", "ggplot2", "viridis",
  "raster", "terra", "exactextractr", "tidyterra", "spdep", "tibble",
  "patchwork", "rosm", "tidyr", "GGally", "cluster", "rgeoda", "mapview",
  "ggspatial", "colorspace", "gstat", "spatstat", "dbscan", "fpc", "eks",
  "igraph", "tidygraph", "remotes"
)

# Install any CRAN packages that are missing
missing_packages <- setdiff(cran_packages, rownames(installed.packages()))
if (length(missing_packages) > 0) install.packages(missing_packages)

# basemapR is not on CRAN, so it is installed from GitHub
if (!requireNamespace("basemapR", quietly = TRUE)) {
  remotes::install_github("Chrisjb/basemapR")
}

To check that everything installed correctly, run:

Code
all_packages <- c(cran_packages, "basemapR")
setdiff(all_packages, rownames(installed.packages()))

If this returns character(0), you are all set. If it lists any package names, try installing those individually with install.packages("name") and read the error message in the Console. If R asks whether you want to install from source a package that needs compilation, answering No usually works and is faster.

R basics

Note

This part is an introduction to R for those who are new to it, or a refresher if you have used R before. Run the code chunks in a .qmd document of your own as you go.

Using the console

Try to use the console to perform a few operations. For example type in:

Code
1 + 1
[1] 2

Slightly more complicated:

Code
print("hello world")
[1] "hello world"

If you are unsure about what a command does, use the “Help” panel in your Files pane or type ?function in the console. For example, to see how the dplyr::rename() function works, type in ?dplyr::rename. The double colon syntax in that command calls a function from a package without loading the whole package with library().

R Objects

Everything in R is an object. R possesses a simple generic function mechanism which can be used for an object-oriented style of programming. Indeed, everything that happens in R is the result of a function call (John M. Chambers). Method dispatch takes place based on the class of the first argument to the generic function.

All R statements where you create objects – “assignments” – have this form: object_name <- value. Assignment can also be performed using = instead of <-, but the standard advice is to use the latter syntax (see e.g. The R Inferno, ch. 8.2.26). In RStudio, the standard shortcut for the assignment operator <- is Alt + - (Windows) or Option + - (macOS).

A mock assignment of the value 30 to the name age is reported below. In order to inspect the content of the newly created variable, it is sufficient to type the name into the console. Within R, the hash symbol # is used to write comments.

Code
age <- 30 # Assign the number 30 to the name "age"
age # print the variable "age" to the console
[1] 30

A small note on variable types

The function class() is used to inspect the type of an object.

There are four main types of variables:

  • Logical: boolean/binary, can either be TRUE or FALSE
Code
class(TRUE)
[1] "logical"
  • Character (or string): simple text, including symbols and numbers. It can be wrapped in single or double quotation marks, which usually highlights text in a different colour in RStudio
Code
class("I am a city")
[1] "character"
  • Numeric: Numbers. Mathematical operators can be used here.
Code
class(2022)
[1] "numeric"
  • Factor: Characters or strings, but ordered in categories.
Code
class(as.factor(c("I", "am", "a", "factor")))
[1] "factor"

Another important value to know is NA. It stands for “Not Available” and simply denotes a missing value.

Code
vector_with_missing <- c(NA, 1, 2, NA)
vector_with_missing
[1] NA  1  2 NA

Logical operators and expressions

  • == asks whether two values are the same or equal (“is equal to”)
  • != asks whether two values are not the same or unequal (“is not equal to”)
  • > greater than
  • < smaller than
  • >= greater or equal to
  • <= smaller or equal to
  • & stands for “and” (unsurprisingly)
  • | stands for “or”
  • ! stands for “not”

A first example

Let’s create some R objects:

Code
# Population and area of two cities
London <- 8982000 # population
Bristol <- 467099 # population
London_area <- 1572 # area km2
Bristol_area <- 110 # area km2

London
[1] 8982000

Calculate population density in London and Bristol:

Code
London_pop_dens <- London / London_area
Bristol_pop_dens <- Bristol / Bristol_area

London_pop_dens
[1] 5713.74

The function c(), which you will use extensively if you keep coding in R, means “concatenate” (or “combine”). In this case, we use it to create a vector of population densities for London and Bristol:

Code
c(London_pop_dens, Bristol_pop_dens)
[1] 5713.740 4246.355
Code
pop_density <- c(London_pop_dens, Bristol_pop_dens)

Create a character variable:

Code
x <- "a city"
class(x)
[1] "character"
Code
typeof(x)
[1] "character"
Code
length(x)
[1] 1

Data Structures

Objects in R are typically stored in data structures. There are multiple types of data structures:

Vectors

In R, a vector is a sequence of elements which share the same data type. A vector supports logical, integer, double, character, complex, or raw data types.

Code
# first vector y
y <- 1:10
class(y)      # 1:10 creates an integer vector
[1] "integer"
Code
as.numeric(y) # returns a numeric copy; y itself is unchanged
 [1]  1  2  3  4  5  6  7  8  9 10
Code
length(y)
[1] 10
Code
# another vector z
z <- c(2, 4, 56, 4)
z
[1]  2  4 56  4
Code
# and another one called cities
cities <- c("London", "Bristol", "Bath")
cities
[1] "London"  "Bristol" "Bath"   

Matrices

Two-dimensional, rectangular, and homogeneous data structures. They are similar to vectors, with the additional attribute of having two dimensions: the number of rows and columns.

Code
m <- matrix(nrow = 2, ncol = 2)
m
     [,1] [,2]
[1,]   NA   NA
[2,]   NA   NA
Code
n <- matrix(c(4, 5, 78, 56), nrow = 2, ncol = 2)
n
     [,1] [,2]
[1,]    4   78
[2,]    5   56

Lists

Lists are containers which can store elements of different types and sizes. A list can contain vectors, matrices, data frames, other lists, and functions, which can be accessed, unlisted, and assigned to other objects.

Code
list_data <- list("Red", "Green", c(21, 32, 11), TRUE, 51.23, 119.1)
print(list_data)
[[1]]
[1] "Red"

[[2]]
[1] "Green"

[[3]]
[1] 21 32 11

[[4]]
[1] TRUE

[[5]]
[1] 51.23

[[6]]
[1] 119.1

Data frames

They are the most common way of storing data in R and are the most used data structure for statistical analysis. Data frames are “rectangular lists”, i.e. tabular structures in which every column has the same length, and can also be thought of as lists of equal-length vectors.

Code
# A data frame of 3 columns named id, x, y and 10 rows
dat <- data.frame(id = letters[1:10], x = 1:10, y = 11:20)
dat
   id  x  y
1   a  1 11
2   b  2 12
3   c  3 13
4   d  4 14
5   e  5 15
6   f  6 16
7   g  7 17
8   h  8 18
9   i  9 19
10  j 10 20
Code
head(dat) # read the first 6 rows
  id x  y
1  a 1 11
2  b 2 12
3  c 3 13
4  d 4 14
5  e 5 15
6  f 6 16
Code
tail(dat) # read the last 6 rows
   id  x  y
5   e  5 15
6   f  6 16
7   g  7 17
8   h  8 18
9   i  9 19
10  j 10 20
Code
names(dat)
[1] "id" "x"  "y" 

Data frames in R are indexed by row and column numbers using the [rows, cols] syntax. The $ operator allows you to access columns in the data frame, or to create new columns in the data frame.

Code
dat[1, ] # read first row and all columns
  id x  y
1  a 1 11
Code
dat[, 1] # read all rows and the first column
 [1] "a" "b" "c" "d" "e" "f" "g" "h" "i" "j"
Code
dat[6, 3] # read 6th row, third column
[1] 16
Code
dat[c(2:4), ] # read rows 2 to 4 and all columns
  id x  y
2  b 2 12
3  c 3 13
4  d 4 14
Code
dat$y # read column y
 [1] 11 12 13 14 15 16 17 18 19 20
Code
dat[dat$x < 7, ] # read rows that have an x value less than 7
  id x  y
1  a 1 11
2  b 2 12
3  c 3 13
4  d 4 14
5  e 5 15
6  f 6 16
Code
dat$new_column <- runif(10, 0, 1) # create a new variable called "new_column"

dat
   id  x  y new_column
1   a  1 11 0.95281644
2   b  2 12 0.19292909
3   c  3 13 0.02548571
4   d  4 14 0.61881681
5   e  5 15 0.54319665
6   f  6 16 0.24438039
7   g  7 17 0.47773011
8   h  8 18 0.94101199
9   i  9 19 0.02573676
10  j 10 20 0.04152465

Importing data from a csv file

To read a csv file we use read_csv() from the readr package, which is part of the tidyverse we loaded with library(tidyverse) in Installing packages. Note the relative path: it works because this .qmd is saved in the course folder, next to the data folder.

Code
Densities_UK_cities <- read_csv("data/London/Tables/Densities_UK_cities.csv")
Rows: 76 Columns: 5
── Column specification ────────────────────────────────────────────────────────
Delimiter: ","
chr (2): city, pop
dbl (1): n
num (2): area, density

ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
Code
Densities_UK_cities
# A tibble: 76 × 5
       n city               pop        area density
   <dbl> <chr>              <chr>     <dbl>   <dbl>
 1     1 Greater London     9,787,426 1738.    5630
 2     2 Greater Manchester 2,553,379  630.    4051
 3     3 West Midlands      2,440,986  599.    4076
 4     4 West Yorkshire     1,777,934  488.    3645
 5     5 Greater Glasgow    957,620    368.    3390
 6     6 Liverpool          864,122    200.    4329
 7     7 South Hampshire    855,569    192     4455
 8     8 Tyneside           774,891    180.    4292
 9     9 Nottingham         729,977    176.    4139
10    10 Sheffield          685,368    168.    4092
# ℹ 66 more rows

You can also inspect the data set with:

Code
glimpse(Densities_UK_cities)
Rows: 76
Columns: 5
$ n       <dbl> 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18,…
$ city    <chr> "Greater London", "Greater Manchester", "West Midlands", "West…
$ pop     <chr> "9,787,426", "2,553,379", "2,440,986", "1,777,934", "957,620",…
$ area    <dbl> 1737.9, 630.3, 598.9, 487.8, 368.5, 199.6, 192.0, 180.5, 176.4…
$ density <dbl> 5630, 4051, 4076, 3645, 3390, 4329, 4455, 4292, 4139, 4092, 42…
Code
table(Densities_UK_cities$city)

               Aberdeen  Accrington/ Rossendale Barnsley/ Dearne Valley 
                      1                       1                       1 
               Basildon             Basingstoke                 Bedford 
                      1                       1                       1 
                Belfast              Birkenhead               Blackburn 
                      1                       1                       1 
              Blackpool      Bournemouth/ Poole       Brighton and Hove 
                      1                       1                       1 
                Bristol                 Burnley       Burton-upon-Trent 
                      1                       1                       1 
              Cambridge                 Cardiff              Chelmsford 
                      1                       1                       1 
             Cheltenham            Chesterfield              Colchester 
                      1                       1                       1 
               Coventry                 Crawley                   Derby 
                      1                       1                       1 
              Doncaster                  Dundee              Eastbourne 
                      1                       1                       1 
              Edinburgh                  Exeter  Farnborough/ Aldershot 
                      1                       1                       1 
             Gloucester         Greater Glasgow          Greater London 
                      1                       1                       1 
     Greater Manchester                 Grimsby                Hastings 
                      1                       1                       1 
           High Wycombe                 Ipswich      Kingston upon Hull 
                      1                       1                       1 
              Leicester                 Lincoln               Liverpool 
                      1                       1                       1 
                  Luton               Maidstone               Mansfield 
                      1                       1                       1 
           Medway Towns           Milton Keynes              Motherwell 
                      1                       1                       1 
                Newport             Northampton                 Norwich 
                      1                       1                       1 
             Nottingham                  Oxford       Paignton/ Torquay 
                      1                       1                       1 
           Peterborough                Plymouth                 Preston 
                      1                       1                       1 
                Reading               Sheffield                  Slough 
                      1                       1                       1 
        South Hampshire         Southend-on-Sea          Stoke-on-Trent 
                      1                       1                       1 
             Sunderland                 Swansea                 Swindon 
                      1                       1                       1 
               Teesside                 Telford                  Thanet 
                      1                       1                       1 
               Tyneside              Warrington           West Midlands 
                      1                       1                       1 
         West Yorkshire                   Wigan               Worcester 
                      1                       1                       1 
                   York 
                      1 

Resources

Some help along the way with:

  1. R for Data Science (2e) by Hadley Wickham, Mine Çetinkaya-Rundel and Garrett Grolemund. R4DS teaches you how to do data science with R: you’ll learn how to get your data into R, get it into the most useful structure, transform it, visualise it and model it.

  2. Spatial Data Science by Edzer Pebesma and Roger Bivand introduces and explains the concepts underlying spatial data.

  3. Geocomputation with R by Robin Lovelace, Jakub Nowosad and Jannes Muenchow.

  4. Quarto documentation for writing and rendering .qmd documents.