1  Getting started

1.1 Intended learning outcomes

By the end of this chapter you will be able to:

  • Load the tidyverse, janitor and patchwork packages
  • Read a CSV file into R with read_csv() and verify the import worked
  • Standardise messy column names with clean_names() from the janitor package
  • Rename variables with rename() to make them easier to work with
  • Convert columns to factors with factor(), controlling the display order
  • Use mutate() and across() to transform several columns at once

1.2 Functions used

1.3 Set-up

For this tutorial you will find it helpful to write your code in a Quarto document. Quarto lets you intersperse code, output and notes in a single file that is easy to share. If you have not used Quarto before, the Quarto Reports chapter of ads-v3 is a good starting point.

  1. Open RStudio.
  2. Create a new RStudio project in a fresh folder.
  3. Download this data into that folder.
  4. Create a new Quarto document.
  5. Replace the default setup chunk at the top of your .qmd file with the one below.
```{r}
#| label: setup
#| include: false

library(tidyverse)
library(janitor)
library(patchwork)
```

1.4 Loading packages

The main package we will use is the tidyverse collection. This loads readr for importing data, dplyr for wrangling, tidyr for reshaping, and ggplot2 for plotting, along with several others. We will also use janitor to tidy up the column names, and patchwork later to combine multiple plots into a single figure. janitor and patchwork are separate packages, so install them first with install.packages(c("janitor", "patchwork")) if you have not already.

library(tidyverse)
library(janitor)
library(patchwork)
Tip

You only need to install a package once (install.packages("tidyverse")) but you need to load it with library() every time you start a new R session.

1.5 Loading the data

The data are in a CSV file called data.csv. We read them in with read_csv() from readr. The result is stored in an object called dat.

dat <- read_csv("data.csv")

When read_csv() runs successfully it prints a column specification telling you what type of data it found in each column. chr means character (text), dbl means double (decimal number). If you get the error message …does not exist in current working directory you have almost certainly mis-typed the file name, forgotten the .csv extension, or saved the data outside your project folder. If you get could not find function "read_csv" you have not loaded the tidyverse.

After importing, always check that the resulting table looks like you expect. Click dat in the Environment pane, or run glimpse(dat) in the console.

glimpse(dat)
Rows: 10,507
Columns: 13
$ `Voyage ID`                                                              <dbl> …
$ `Vessel name`                                                            <chr> …
$ `Voyage itinerary imputed port where began (ptdepimp) place`             <chr> …
$ `Voyage itinerary imputed principal place of slave purchase (mjbyptimp)` <chr> …
$ `Total embarked`                                                         <dbl> …
$ `Total disembarked`                                                      <dbl> …
$ `Year of arrival at port of disembarkation`                              <dbl> …
$ `Percent men`                                                            <dbl> …
$ `Percent women`                                                          <dbl> …
$ `Percent children`                                                       <dbl> …
$ `Slaves died during middle passage`                                      <dbl> …
$ `Mortality rate`                                                         <dbl> …
$ `Slaves outcome label`                                                   <chr> …
  • The dataset has rows of data and columns.

1.6 House-keeping

The column names are informative but long, and several contain spaces, capital letters and brackets. That makes them awkward to type and to refer to in code. As a rule, variable names should avoid spaces and special characters. Pick a naming convention (my.var, myVar, my_var) and stick with it. This tutorial uses underscores and no capitals, a style often called snake case.

The clean_names() function from the janitor package does the mechanical part of this for us. It converts every column name to lower case and replaces spaces and brackets with underscores, so we no longer need back-ticks to refer to a column.

dat_clean <- clean_names(dat)

names(dat_clean)
 [1] "voyage_id"                                                           
 [2] "vessel_name"                                                         
 [3] "voyage_itinerary_imputed_port_where_began_ptdepimp_place"            
 [4] "voyage_itinerary_imputed_principal_place_of_slave_purchase_mjbyptimp"
 [5] "total_embarked"                                                      
 [6] "total_disembarked"                                                   
 [7] "year_of_arrival_at_port_of_disembarkation"                           
 [8] "percent_men"                                                         
 [9] "percent_women"                                                       
[10] "percent_children"                                                    
[11] "slaves_died_during_middle_passage"                                   
[12] "mortality_rate"                                                      
[13] "slaves_outcome_label"                                                

Every name is now consistent snake case. Two of them, total_embarked and total_disembarked, are already short enough to use as they are. The rest are still long, because clean_names() standardises names but cannot know which ones we would like to be shorter.

For that we use rename(). The syntax is new_name = old_name. Because clean_names() has already removed the spaces, no back-ticks are needed.

dat_rename <- rename(dat_clean,
                     id = voyage_id,
                     vessel = vessel_name,
                     start_port = voyage_itinerary_imputed_port_where_began_ptdepimp_place,
                     purchase_place = voyage_itinerary_imputed_principal_place_of_slave_purchase_mjbyptimp,
                     arrival_year = year_of_arrival_at_port_of_disembarkation,
                     men = percent_men,
                     women = percent_women,
                     children = percent_children,
                     died = slaves_died_during_middle_passage,
                     mortality = mortality_rate,
                     outcome = slaves_outcome_label)
Tip

When code starts to spread across many lines, pressing Enter after a comma to break the line makes it much easier to read.

1.7 Checking variable types

After importing and renaming, check what R thinks each column is. Three useful options are:

str(dat_rename)
summary(dat_rename)
map_chr(dat_rename, class)
  • How many of the variables are character (text) variables?
  • How many of the variables are numeric (double)?

Several are correct as-is, but two issues need attention. The id column contains numbers, but those numbers are identifiers, not quantities you would average. The character columns (vessel, start_port, purchase_place, outcome) hold a fixed set of categories rather than free text. Both kinds of column should be factors, which is how R represents categorical data.

1.8 Converting to factors

We use mutate() to overwrite each column with a factor version of itself. factor() lets us set the display order with the levels argument, which matters because R will otherwise sort categories alphabetically in plots.

dat_final <- mutate(dat_rename,
                    id             = factor(id),
                    vessel         = factor(vessel),
                    purchase_place = factor(purchase_place),
                    outcome        = factor(outcome),
                    start_port     = factor(start_port,
                                            levels = c("Liverpool",
                                                       "London",
                                                       "Bristol",
                                                       sort(setdiff(unique(start_port),
                                                                    c("Liverpool", "London", "Bristol"))))))

We have given start_port an explicit order. Liverpool, London and Bristol come first because we will focus on those three; the remaining ports follow in alphabetical order. This means later plots will show the three big British ports in a meaningful order, rather than the default alphabetical Bristol, Liverpool, London.

If you do not need to control the levels for each column individually, you can convert several columns at once with across():

dat_final <- mutate(dat_rename,
                    across(c(id, vessel, purchase_place, outcome, start_port),
                           as.factor))

This is more compact but loses the explicit ordering of start_port. See the dplyr documentation for more.

Run summary() again on dat_final and look at how the factor variables are now summarised by their counts per level.

summary(dat_final)

1.9 Activities

TipActivity 1

Run glimpse(dat_final) and identify which columns are now factors. How many factor columns are there?

TipActivity 2

The mortality column is a proportion. Use summary(dat_final$mortality) to find its mean. To two decimal places, what is it?

summary(dat_final$mortality)

The mean mortality rate across the 10,507 voyages in this subset is about 0.18 (18%).