Overview

Data scientists, according to interviews and expert estimates, spend from 50 percent to 80 percent of their time mired in the mundane labor of collecting and preparing data, before it can be explored for useful information. - NYTimes (2014)

This tutorial will cover the tidyr and dplyr packages created by the mythical code wizard Hadley Wickham of ggplot2 fame. The “gg” in ggplot2 stands for the “grammar of graphics”. Hadley similarly considers the functionality of the two packages dplyr and tidyr to provide the “grammar of data manipulation”.

Getting Started

You can download RStudio if you don’t have latest version 0.99.892 (menu RStudio -> About RStudio), which has many nice additions for running R chunks and providing table of contents in Rmarkdown documents.

Install and/or load the following packages:

## Install packages if needed
# install.packages('devtools')
# install.packages('readr')
# install.packages('dplyr')
# install.packages('plyr')
# install.packages('tidyr')
# install.packages('stringr')
# install.packages('ggplot2')

# Load packages
suppressPackageStartupMessages({
  library(devtools)
  library(readr)
  library(dplyr)
  library(broom)
  library(tidyr)
  library(stringr)
  library(ggplot2)
})
## Warning: package 'ggplot2' was built under R version 3.2.4
# Check package versions after Packages pane -> Update
devtools::session_info()
## Session info --------------------------------------------------------------
##  setting  value
##  version  R version 3.2.3 (2015-12-10)
##  system   x86_64, darwin13.4.0
##  ui       X11
##  language (EN)
##  collate  en_US.UTF-8
##  tz       America/Los_Angeles
##  date     2016-03-11
## Packages ------------------------------------------------------------------
##  package    * version date       source
##  assertthat   0.1     2013-12-06 CRAN (R 3.2.0)
##  broom      * 0.4.0   2015-11-30 CRAN (R 3.2.3)
##  colorspace   1.2-6   2015-03-11 CRAN (R 3.2.0)
##  DBI          0.3.1   2014-09-24 CRAN (R 3.2.0)
##  devtools   * 1.10.0  2016-01-23 CRAN (R 3.2.3)
##  digest       0.6.9   2016-01-08 CRAN (R 3.2.3)
##  dplyr      * 0.4.3   2015-09-01 CRAN (R 3.2.0)
##  evaluate     0.8.3   2016-03-05 CRAN (R 3.2.4)
##  formatR      1.3     2016-03-05 CRAN (R 3.2.3)
##  ggplot2    * 2.1.0   2016-03-01 CRAN (R 3.2.4)
##  gtable       0.2.0   2016-02-26 CRAN (R 3.2.3)
##  htmltools    0.3     2015-12-29 CRAN (R 3.2.3)
##  knitr        1.12.3  2016-01-22 CRAN (R 3.2.3)
##  lattice      0.20-33 2015-07-14 CRAN (R 3.2.3)
##  magrittr     1.5     2014-11-22 CRAN (R 3.2.0)
##  memoise      1.0.0   2016-01-29 CRAN (R 3.2.3)
##  mnormt       1.5-3   2015-05-25 CRAN (R 3.2.0)
##  munsell      0.4.3   2016-02-13 CRAN (R 3.2.3)
##  nlme         3.1-125 2016-02-27 CRAN (R 3.2.3)
##  plyr         1.8.3   2015-06-12 CRAN (R 3.2.0)
##  psych        1.5.8   2015-08-30 CRAN (R 3.2.0)
##  R6           2.1.2   2016-01-26 CRAN (R 3.2.3)
##  Rcpp         0.12.3  2016-01-10 CRAN (R 3.2.3)
##  readr      * 0.2.2   2015-10-22 CRAN (R 3.2.0)
##  reshape2     1.4.1   2014-12-06 CRAN (R 3.2.0)
##  rmarkdown    0.9.5   2016-02-22 CRAN (R 3.2.3)
##  scales       0.4.0   2016-02-26 CRAN (R 3.2.3)
##  stringi      1.0-1   2015-10-22 CRAN (R 3.2.0)
##  stringr    * 1.0.0   2015-04-30 CRAN (R 3.2.0)
##  tidyr      * 0.4.1   2016-02-05 CRAN (R 3.2.3)
##  yaml         2.1.13  2014-06-12 CRAN (R 3.2.0)

Why use dplyr and tidyr?

  1. Speed - dplyr and tidyr are really fast
  2. Readability - the code syntax is straightforward and easy to read
  3. Chaining - never break the chain. More on this later
  4. Integrates with ggplot2 - plot your data in the same workflow that you manipulate it with
  5. Can be used to analyze external databases without knowledge of additional database query languages

Basics of dplyr and tidyr

Data frames and data tables

Although technically two separate packages, dplyr and tidyr were designed to work together and can basically be thought of as a single package. They are designed to work with data frames as is, but it is generally a good idea to convert your data to table data using the read_csv() or tbl_df() functions, particularly when working with large datasets.

## Comparing read.csv with read_csv
# Read in FAO data
fao   <- read.csv(file = 'data/FAO_1950to2012_111914.csv', stringsAsFactors = F)
summary(fao)
##  Country..Country.  Species..ASFIS.species. Species..ISSCAAP.group.
##  Length:17692       Length:17692            Min.   :11.00
##  Class :character   Class :character        1st Qu.:33.00
##  Mode  :character   Mode  :character        Median :36.00
##                                             Mean   :37.38
##                                             3rd Qu.:38.00
##                                             Max.   :77.00
##  Species..ISSCAAP.group..1 Species..ASFIS.species..1
##  Length:17692              Length:17692
##  Class :character          Class :character
##  Mode  :character          Mode  :character
##
##
##
##  Species..ASFIS.species..2 Fishing.area..FAO.major.fishing.area.
##  Length:17692              Min.   :18.00
##  Class :character          1st Qu.:31.00
##  Mode  :character          Median :37.00
##                            Mean   :45.34
##                            3rd Qu.:57.00
##                            Max.   :88.00
##  Measure..Measure.     X1950              X1951
##  Length:17692       Length:17692       Length:17692
##  Class :character   Class :character   Class :character
##  Mode  :character   Mode  :character   Mode  :character
##
##
##
##     X1952              X1953              X1954
##  Length:17692       Length:17692       Length:17692
##  Class :character   Class :character   Class :character
##  Mode  :character   Mode  :character   Mode  :character
##
##
##
##     X1955              X1956              X1957
##  Length:17692       Length:17692       Length:17692
##  Class :character   Class :character   Class :character
##  Mode  :character   Mode  :character   Mode  :character
##
##
##
##     X1958              X1959              X1960
##  Length:17692       Length:17692       Length:17692
##  Class :character   Class :character   Class :character
##  Mode  :character   Mode  :character   Mode  :character
##
##
##
##     X1961              X1962              X1963
##  Length:17692       Length:17692       Length:17692
##  Class :character   Class :character   Class :character
##  Mode  :character   Mode  :character   Mode  :character
##
##
##
##     X1964              X1965              X1966
##  Length:17692       Length:17692       Length:17692
##  Class :character   Class :character   Class :character
##  Mode  :character   Mode  :character   Mode  :character
##
##
##
##     X1967              X1968              X1969
##  Length:17692       Length:17692       Length:17692
##  Class :character   Class :character   Class :character
##  Mode  :character   Mode  :character   Mode  :character
##
##
##
##     X1970              X1971              X1972
##  Length:17692       Length:17692       Length:17692
##  Class :character   Class :character   Class :character
##  Mode  :character   Mode  :character   Mode  :character
##
##
##
##     X1973              X1974              X1975
##  Length:17692       Length:17692       Length:17692
##  Class :character   Class :character   Class :character
##  Mode  :character   Mode  :character   Mode  :character
##
##
##
##     X1976              X1977              X1978
##  Length:17692       Length:17692       Length:17692
##  Class :character   Class :character   Class :character
##  Mode  :character   Mode  :character   Mode  :character
##
##
##
##     X1979              X1980              X1981
##  Length:17692       Length:17692       Length:17692
##  Class :character   Class :character   Class :character
##  Mode  :character   Mode  :character   Mode  :character
##
##
##
##     X1982              X1983              X1984
##  Length:17692       Length:17692       Length:17692
##  Class :character   Class :character   Class :character
##  Mode  :character   Mode  :character   Mode  :character
##
##
##
##     X1985              X1986              X1987
##  Length:17692       Length:17692       Length:17692
##  Class :character   Class :character   Class :character
##  Mode  :character   Mode  :character   Mode  :character
##
##
##
##     X1988              X1989              X1990
##  Length:17692       Length:17692       Length:17692
##  Class :character   Class :character   Class :character
##  Mode  :character   Mode  :character   Mode  :character
##
##
##
##     X1991              X1992              X1993
##  Length:17692       Length:17692       Length:17692
##  Class :character   Class :character   Class :character
##  Mode  :character   Mode  :character   Mode  :character
##
##
##
##     X1994              X1995              X1996
##  Length:17692       Length:17692       Length:17692
##  Class :character   Class :character   Class :character
##  Mode  :character   Mode  :character   Mode  :character
##
##
##
##     X1997              X1998              X1999
##  Length:17692       Length:17692       Length:17692
##  Class :character   Class :character   Class :character
##  Mode  :character   Mode  :character   Mode  :character
##
##
##
##     X2000              X2001              X2002
##  Length:17692       Length:17692       Length:17692
##  Class :character   Class :character   Class :character
##  Mode  :character   Mode  :character   Mode  :character
##
##
##
##     X2003              X2004              X2005
##  Length:17692       Length:17692       Length:17692
##  Class :character   Class :character   Class :character
##  Mode  :character   Mode  :character   Mode  :character
##
##
##
##     X2006              X2007              X2008
##  Length:17692       Length:17692       Length:17692
##  Class :character   Class :character   Class :character
##  Mode  :character   Mode  :character   Mode  :character
##
##
##
##     X2009              X2010              X2011
##  Length:17692       Length:17692       Length:17692
##  Class :character   Class :character   Class :character
##  Mode  :character   Mode  :character   Mode  :character
##
##
##
##     X2012
##  Length:17692
##  Class :character
##  Mode  :character
##
##
## 
head(fao)
##   Country..Country.      Species..ASFIS.species. Species..ISSCAAP.group.
## 1           Albania Angelsharks, sand devils nei                      38
## 2           Albania              Atlantic bonito                      36
## 3           Albania               Barracudas nei                      37
## 4           Albania          Blue and red shrimp                      45
## 5           Albania     Blue whiting(=Poutassou)                      32
## 6           Albania                     Bluefish                      37
##      Species..ISSCAAP.group..1 Species..ASFIS.species..1
## 1      Sharks, rays, chimaeras                10903XXXXX
## 2   Tunas, bonitos, billfishes                1750100101
## 3 Miscellaneous pelagic fishes                17710001XX
## 4              Shrimps, prawns                2280203101
## 5        Cods, hakes, haddocks                1480403301
## 6 Miscellaneous pelagic fishes                1702021301
##   Species..ASFIS.species..2 Fishing.area..FAO.major.fishing.area.
## 1               Squatinidae                                    37
## 2               Sarda sarda                                    37
## 3             Sphyraena spp                                    37
## 4       Aristeus antennatus                                    37
## 5  Micromesistius poutassou                                    37
## 6       Pomatomus saltatrix                                    37
##   Measure..Measure. X1950 X1951 X1952 X1953 X1954 X1955 X1956 X1957 X1958
## 1 Quantity (tonnes)   ...   ...   ...   ...   ...   ...   ...   ...   ...
## 2 Quantity (tonnes)   ...   ...   ...   ...   ...   ...   ...   ...   ...
## 3 Quantity (tonnes)   ...   ...   ...   ...   ...   ...   ...   ...   ...
## 4 Quantity (tonnes)   ...   ...   ...   ...   ...   ...   ...   ...   ...
## 5 Quantity (tonnes)   ...   ...   ...   ...   ...   ...   ...   ...   ...
## 6 Quantity (tonnes)   ...   ...   ...   ...   ...   ...   ...   ...   ...
##   X1959 X1960 X1961 X1962 X1963 X1964 X1965 X1966 X1967 X1968 X1969 X1970
## 1   ...   ...   ...   ...   ...   ...   ...   ...   ...   ...   ...   ...
## 2   ...   ...   ...   ...   ...   ...   ...   ...   ...   ...   ...   ...
## 3   ...   ...   ...   ...   ...   ...   ...   ...   ...   ...   ...   ...
## 4   ...   ...   ...   ...   ...   ...   ...   ...   ...   ...   ...   ...
## 5   ...   ...   ...   ...   ...   ...   ...   ...   ...   ...   ...   ...
## 6   ...   ...   ...   ...   ...   ...   ...   ...   ...   ...   ...   ...
##   X1971 X1972 X1973 X1974 X1975 X1976 X1977 X1978 X1979 X1980 X1981 X1982
## 1   ...   ...   ...   ...   ...   ...   ...   ...   ...   ...   ...   ...
## 2   ...   ...   ...   ...   ...   ...   ...   ...   ...   ...   ...   ...
## 3   ...   ...   ...   ...   ...   ...   ...   ...   ...   ...   ...   ...
## 4   ...   ...   ...   ...   ...   ...   ...   ...   ...   ...   ...   ...
## 5   ...   ...   ...   ...   ...   ...   ...   ...   ...   ...   ...   ...
## 6   ...   ...   ...   ...   ...   ...   ...   ...   ...   ...   ...   ...
##   X1983 X1984 X1985 X1986 X1987 X1988 X1989 X1990 X1991 X1992 X1993 X1994
## 1   ...   ...   ...   ...   ...   ...   ...   ...   ...   ...   ...   ...
## 2   ...   ...   ...   ...   ...   ...   ...   ...   ...   ...   ...   ...
## 3   ...   ...   ...   ...   ...   ...   ...   ...   ...   ...   ...   ...
## 4   ...   ...   ...   ...   ...   ...   ...   ...   ...   ...   ...   ...
## 5   ...   ...   ...   ...   ...   ...   ...   ...   ...   ...   ...   ...
## 6   ...   ...   ...   ...   ...   ...   ...   ...   ...   ...   ...   ...
##   X1995 X1996 X1997 X1998 X1999 X2000 X2001 X2002 X2003 X2004 X2005 X2006
## 1   0 0    53    20    31    30    30    16    79     1     4    68    55
## 2     1     2   0 0    12    30    25    30    24     4     2    23    30
## 3   ...   ...   ...   ...   ...     2   ...   ...   ...     2     4     7
## 4   0 0     3   0 0     -     -     -     -    34    22    15    12    18
## 5   0 0     2   0 0     -     -     -     -     6   ...     1     5     8
## 6   ...   ...   ...   ...   ...   ...   ...   ...   ...     2     6     9
##   X2007 X2008 X2009 X2010 X2011 X2012
## 1    12    23    14    78    12     5
## 2    19    27    21    23    12     5
## 3   ...   ...   ...     7   ...   ...
## 4   ...   ...   ...   ...   ...   ...
## 5     -     -     -     -     -     -
## 6     -     -     -     -     -     -
# vs using read_csv
fao   <- read_csv(file = 'data/FAO_1950to2012_111914.csv')
fao
## Source: local data frame [17,692 x 71]
##
##    Country (Country)      Species (ASFIS species) Species (ISSCAAP group)
##                (chr)                        (chr)                   (int)
## 1            Albania Angelsharks, sand devils nei                      38
## 2            Albania              Atlantic bonito                      36
## 3            Albania               Barracudas nei                      37
## 4            Albania          Blue and red shrimp                      45
## 5            Albania     Blue whiting(=Poutassou)                      32
## 6            Albania                     Bluefish                      37
## 7            Albania                        Bogue                      33
## 8            Albania               Caramote prawn                      45
## 9            Albania   Catsharks, nursehounds nei                      38
## 10           Albania            Common cuttlefish                      57
## ..               ...                          ...                     ...
## Variables not shown: Species (ISSCAAP group) (chr), Species (ASFIS
##   species) (chr), Species (ASFIS species) (chr), Fishing area (FAO major
##   fishing area) (int), Measure (Measure) (chr), 1950 (chr), 1951 (chr),
##   1952 (chr), 1953 (chr), 1954 (chr), 1955 (chr), 1956 (chr), 1957 (chr),
##   1958 (chr), 1959 (chr), 1960 (chr), 1961 (chr), 1962 (chr), 1963 (chr),
##   1964 (chr), 1965 (chr), 1966 (chr), 1967 (chr), 1968 (chr), 1969 (chr),
##   1970 (chr), 1971 (chr), 1972 (chr), 1973 (chr), 1974 (chr), 1975 (chr),
##   1976 (chr), 1977 (chr), 1978 (chr), 1979 (chr), 1980 (chr), 1981 (chr),
##   1982 (chr), 1983 (chr), 1984 (chr), 1985 (chr), 1986 (chr), 1987 (chr),
##   1988 (chr), 1989 (chr), 1990 (chr), 1991 (chr), 1992 (chr), 1993 (chr),
##   1994 (chr), 1995 (chr), 1996 (chr), 1997 (chr), 1998 (chr), 1999 (chr),
##   2000 (chr), 2001 (chr), 2002 (chr), 2003 (chr), 2004 (chr), 2005 (chr),
##   2006 (chr), 2007 (chr), 2008 (chr), 2009 (chr), 2010 (chr), 2011 (chr),
##   2012 (chr)
# note: read_csv like read.csv(...)
#       also keeps original column names and converts to tbl_df()
names(fao) = make.names(names(fao), unique=T) # since original column names have duplicates

## Consider what happens with the following command
# fao # all entries are printed in your console
head(fao) # top five entries are printed in your console, columns wrap and can be difficult to follow if working with many variables
## Source: local data frame [6 x 71]
##
##   Country..Country.      Species..ASFIS.species. Species..ISSCAAP.group.
##               (chr)                        (chr)                   (int)
## 1           Albania Angelsharks, sand devils nei                      38
## 2           Albania              Atlantic bonito                      36
## 3           Albania               Barracudas nei                      37
## 4           Albania          Blue and red shrimp                      45
## 5           Albania     Blue whiting(=Poutassou)                      32
## 6           Albania                     Bluefish                      37
## Variables not shown: Species..ISSCAAP.group..1 (chr),
##   Species..ASFIS.species..1 (chr), Species..ASFIS.species..2 (chr),
##   Fishing.area..FAO.major.fishing.area. (int), Measure..Measure. (chr),
##   X1950 (chr), X1951 (chr), X1952 (chr), X1953 (chr), X1954 (chr), X1955
##   (chr), X1956 (chr), X1957 (chr), X1958 (chr), X1959 (chr), X1960 (chr),
##   X1961 (chr), X1962 (chr), X1963 (chr), X1964 (chr), X1965 (chr), X1966
##   (chr), X1967 (chr), X1968 (chr), X1969 (chr), X1970 (chr), X1971 (chr),
##   X1972 (chr), X1973 (chr), X1974 (chr), X1975 (chr), X1976 (chr), X1977
##   (chr), X1978 (chr), X1979 (chr), X1980 (chr), X1981 (chr), X1982 (chr),
##   X1983 (chr), X1984 (chr), X1985 (chr), X1986 (chr), X1987 (chr), X1988
##   (chr), X1989 (chr), X1990 (chr), X1991 (chr), X1992 (chr), X1993 (chr),
##   X1994 (chr), X1995 (chr), X1996 (chr), X1997 (chr), X1998 (chr), X1999
##   (chr), X2000 (chr), X2001 (chr), X2002 (chr), X2003 (chr), X2004 (chr),
##   X2005 (chr), X2006 (chr), X2007 (chr), X2008 (chr), X2009 (chr), X2010
##   (chr), X2011 (chr), X2012 (chr)
summary(fao)
##  Country..Country.  Species..ASFIS.species. Species..ISSCAAP.group.
##  Length:17692       Length:17692            Min.   :11.00
##  Class :character   Class :character        1st Qu.:33.00
##  Mode  :character   Mode  :character        Median :36.00
##                                             Mean   :37.38
##                                             3rd Qu.:38.00
##                                             Max.   :77.00
##  Species..ISSCAAP.group..1 Species..ASFIS.species..1
##  Length:17692              Length:17692
##  Class :character          Class :character
##  Mode  :character          Mode  :character
##
##
##
##  Species..ASFIS.species..2 Fishing.area..FAO.major.fishing.area.
##  Length:17692              Min.   :18.00
##  Class :character          1st Qu.:31.00
##  Mode  :character          Median :37.00
##                            Mean   :45.34
##                            3rd Qu.:57.00
##                            Max.   :88.00
##  Measure..Measure.     X1950              X1951
##  Length:17692       Length:17692       Length:17692
##  Class :character   Class :character   Class :character
##  Mode  :character   Mode  :character   Mode  :character
##
##
##
##     X1952              X1953              X1954
##  Length:17692       Length:17692       Length:17692
##  Class :character   Class :character   Class :character
##  Mode  :character   Mode  :character   Mode  :character
##
##
##
##     X1955              X1956              X1957
##  Length:17692       Length:17692       Length:17692
##  Class :character   Class :character   Class :character
##  Mode  :character   Mode  :character   Mode  :character
##
##
##
##     X1958              X1959              X1960
##  Length:17692       Length:17692       Length:17692
##  Class :character   Class :character   Class :character
##  Mode  :character   Mode  :character   Mode  :character
##
##
##
##     X1961              X1962              X1963
##  Length:17692       Length:17692       Length:17692
##  Class :character   Class :character   Class :character
##  Mode  :character   Mode  :character   Mode  :character
##
##
##
##     X1964              X1965              X1966
##  Length:17692       Length:17692       Length:17692
##  Class :character   Class :character   Class :character
##  Mode  :character   Mode  :character   Mode  :character
##
##
##
##     X1967              X1968              X1969
##  Length:17692       Length:17692       Length:17692
##  Class :character   Class :character   Class :character
##  Mode  :character   Mode  :character   Mode  :character
##
##
##
##     X1970              X1971              X1972
##  Length:17692       Length:17692       Length:17692
##  Class :character   Class :character   Class :character
##  Mode  :character   Mode  :character   Mode  :character
##
##
##
##     X1973              X1974              X1975
##  Length:17692       Length:17692       Length:17692
##  Class :character   Class :character   Class :character
##  Mode  :character   Mode  :character   Mode  :character
##
##
##
##     X1976              X1977              X1978
##  Length:17692       Length:17692       Length:17692
##  Class :character   Class :character   Class :character
##  Mode  :character   Mode  :character   Mode  :character
##
##
##
##     X1979              X1980              X1981
##  Length:17692       Length:17692       Length:17692
##  Class :character   Class :character   Class :character
##  Mode  :character   Mode  :character   Mode  :character
##
##
##
##     X1982              X1983              X1984
##  Length:17692       Length:17692       Length:17692
##  Class :character   Class :character   Class :character
##  Mode  :character   Mode  :character   Mode  :character
##
##
##
##     X1985              X1986              X1987
##  Length:17692       Length:17692       Length:17692
##  Class :character   Class :character   Class :character
##  Mode  :character   Mode  :character   Mode  :character
##
##
##
##     X1988              X1989              X1990
##  Length:17692       Length:17692       Length:17692
##  Class :character   Class :character   Class :character
##  Mode  :character   Mode  :character   Mode  :character
##
##
##
##     X1991              X1992              X1993
##  Length:17692       Length:17692       Length:17692
##  Class :character   Class :character   Class :character
##  Mode  :character   Mode  :character   Mode  :character
##
##
##
##     X1994              X1995              X1996
##  Length:17692       Length:17692       Length:17692
##  Class :character   Class :character   Class :character
##  Mode  :character   Mode  :character   Mode  :character
##
##
##
##     X1997              X1998              X1999
##  Length:17692       Length:17692       Length:17692
##  Class :character   Class :character   Class :character
##  Mode  :character   Mode  :character   Mode  :character
##
##
##
##     X2000              X2001              X2002
##  Length:17692       Length:17692       Length:17692
##  Class :character   Class :character   Class :character
##  Mode  :character   Mode  :character   Mode  :character
##
##
##
##     X2003              X2004              X2005
##  Length:17692       Length:17692       Length:17692
##  Class :character   Class :character   Class :character
##  Mode  :character   Mode  :character   Mode  :character
##
##
##
##     X2006              X2007              X2008
##  Length:17692       Length:17692       Length:17692
##  Class :character   Class :character   Class :character
##  Mode  :character   Mode  :character   Mode  :character
##
##
##
##     X2009              X2010              X2011
##  Length:17692       Length:17692       Length:17692
##  Class :character   Class :character   Class :character
##  Mode  :character   Mode  :character   Mode  :character
##
##
##
##     X2012
##  Length:17692
##  Class :character
##  Mode  :character
##
##
## 
## With dplyr
fao<-tbl_df(fao) # convert to table data
fao # now top 10 rows are shown along with data type of each variable. Variables that do not fit in console window are shown below.
## Source: local data frame [17,692 x 71]
##
##    Country..Country.      Species..ASFIS.species. Species..ISSCAAP.group.
##                (chr)                        (chr)                   (int)
## 1            Albania Angelsharks, sand devils nei                      38
## 2            Albania              Atlantic bonito                      36
## 3            Albania               Barracudas nei                      37
## 4            Albania          Blue and red shrimp                      45
## 5            Albania     Blue whiting(=Poutassou)                      32
## 6            Albania                     Bluefish                      37
## 7            Albania                        Bogue                      33
## 8            Albania               Caramote prawn                      45
## 9            Albania   Catsharks, nursehounds nei                      38
## 10           Albania            Common cuttlefish                      57
## ..               ...                          ...                     ...
## Variables not shown: Species..ISSCAAP.group..1 (chr),
##   Species..ASFIS.species..1 (chr), Species..ASFIS.species..2 (chr),
##   Fishing.area..FAO.major.fishing.area. (int), Measure..Measure. (chr),
##   X1950 (chr), X1951 (chr), X1952 (chr), X1953 (chr), X1954 (chr), X1955
##   (chr), X1956 (chr), X1957 (chr), X1958 (chr), X1959 (chr), X1960 (chr),
##   X1961 (chr), X1962 (chr), X1963 (chr), X1964 (chr), X1965 (chr), X1966
##   (chr), X1967 (chr), X1968 (chr), X1969 (chr), X1970 (chr), X1971 (chr),
##   X1972 (chr), X1973 (chr), X1974 (chr), X1975 (chr), X1976 (chr), X1977
##   (chr), X1978 (chr), X1979 (chr), X1980 (chr), X1981 (chr), X1982 (chr),
##   X1983 (chr), X1984 (chr), X1985 (chr), X1986 (chr), X1987 (chr), X1988
##   (chr), X1989 (chr), X1990 (chr), X1991 (chr), X1992 (chr), X1993 (chr),
##   X1994 (chr), X1995 (chr), X1996 (chr), X1997 (chr), X1998 (chr), X1999
##   (chr), X2000 (chr), X2001 (chr), X2002 (chr), X2003 (chr), X2004 (chr),
##   X2005 (chr), X2006 (chr), X2007 (chr), X2008 (chr), X2009 (chr), X2010
##   (chr), X2011 (chr), X2012 (chr)
glimpse(fao) # view all columns 
## Observations: 17,692
## Variables: 71
## $ Country..Country.                     (chr) "Albania", "Albania", "A...
## $ Species..ASFIS.species.               (chr) "Angelsharks, sand devil...
## $ Species..ISSCAAP.group.               (int) 38, 36, 37, 45, 32, 37, ...
## $ Species..ISSCAAP.group..1             (chr) "Sharks, rays, chimaeras...
## $ Species..ASFIS.species..1             (chr) "10903XXXXX", "175010010...
## $ Species..ASFIS.species..2             (chr) "Squatinidae", "Sarda sa...
## $ Fishing.area..FAO.major.fishing.area. (int) 37, 37, 37, 37, 37, 37, ...
## $ Measure..Measure.                     (chr) "Quantity (tonnes)", "Qu...
## $ X1950                                 (chr) "...", "...", "...", ".....
## $ X1951                                 (chr) "...", "...", "...", ".....
## $ X1952                                 (chr) "...", "...", "...", ".....
## $ X1953                                 (chr) "...", "...", "...", ".....
## $ X1954                                 (chr) "...", "...", "...", ".....
## $ X1955                                 (chr) "...", "...", "...", ".....
## $ X1956                                 (chr) "...", "...", "...", ".....
## $ X1957                                 (chr) "...", "...", "...", ".....
## $ X1958                                 (chr) "...", "...", "...", ".....
## $ X1959                                 (chr) "...", "...", "...", ".....
## $ X1960                                 (chr) "...", "...", "...", ".....
## $ X1961                                 (chr) "...", "...", "...", ".....
## $ X1962                                 (chr) "...", "...", "...", ".....
## $ X1963                                 (chr) "...", "...", "...", ".....
## $ X1964                                 (chr) "...", "...", "...", ".....
## $ X1965                                 (chr) "...", "...", "...", ".....
## $ X1966                                 (chr) "...", "...", "...", ".....
## $ X1967                                 (chr) "...", "...", "...", ".....
## $ X1968                                 (chr) "...", "...", "...", ".....
## $ X1969                                 (chr) "...", "...", "...", ".....
## $ X1970                                 (chr) "...", "...", "...", ".....
## $ X1971                                 (chr) "...", "...", "...", ".....
## $ X1972                                 (chr) "...", "...", "...", ".....
## $ X1973                                 (chr) "...", "...", "...", ".....
## $ X1974                                 (chr) "...", "...", "...", ".....
## $ X1975                                 (chr) "...", "...", "...", ".....
## $ X1976                                 (chr) "...", "...", "...", ".....
## $ X1977                                 (chr) "...", "...", "...", ".....
## $ X1978                                 (chr) "...", "...", "...", ".....
## $ X1979                                 (chr) "...", "...", "...", ".....
## $ X1980                                 (chr) "...", "...", "...", ".....
## $ X1981                                 (chr) "...", "...", "...", ".....
## $ X1982                                 (chr) "...", "...", "...", ".....
## $ X1983                                 (chr) "...", "...", "...", ".....
## $ X1984                                 (chr) "...", "...", "...", ".....
## $ X1985                                 (chr) "...", "...", "...", ".....
## $ X1986                                 (chr) "...", "...", "...", ".....
## $ X1987                                 (chr) "...", "...", "...", ".....
## $ X1988                                 (chr) "...", "...", "...", ".....
## $ X1989                                 (chr) "...", "...", "...", ".....
## $ X1990                                 (chr) "...", "...", "...", ".....
## $ X1991                                 (chr) "...", "...", "...", ".....
## $ X1992                                 (chr) "...", "...", "...", ".....
## $ X1993                                 (chr) "...", "...", "...", ".....
## $ X1994                                 (chr) "...", "...", "...", ".....
## $ X1995                                 (chr) "0 0", "1", "...", "0 0"...
## $ X1996                                 (chr) "53", "2", "...", "3", "...
## $ X1997                                 (chr) "20", "0 0", "...", "0 0...
## $ X1998                                 (chr) "31", "12", "...", "-", ...
## $ X1999                                 (chr) "30", "30", "...", "-", ...
## $ X2000                                 (chr) "30", "25", "2", "-", "-...
## $ X2001                                 (chr) "16", "30", "...", "-", ...
## $ X2002                                 (chr) "79", "24", "...", "34",...
## $ X2003                                 (chr) "1", "4", "...", "22", "...
## $ X2004                                 (chr) "4", "2", "2", "15", "1"...
## $ X2005                                 (chr) "68", "23", "4", "12", "...
## $ X2006                                 (chr) "55", "30", "7", "18", "...
## $ X2007                                 (chr) "12", "19", "...", "..."...
## $ X2008                                 (chr) "23", "27", "...", "..."...
## $ X2009                                 (chr) "14", "21", "...", "..."...
## $ X2010                                 (chr) "78", "23", "7", "...", ...
## $ X2011                                 (chr) "12", "12", "...", "..."...
## $ X2012                                 (chr) "5", "5", "...", "...", ...
summary(fao)
##  Country..Country.  Species..ASFIS.species. Species..ISSCAAP.group.
##  Length:17692       Length:17692            Min.   :11.00
##  Class :character   Class :character        1st Qu.:33.00
##  Mode  :character   Mode  :character        Median :36.00
##                                             Mean   :37.38
##                                             3rd Qu.:38.00
##                                             Max.   :77.00
##  Species..ISSCAAP.group..1 Species..ASFIS.species..1
##  Length:17692              Length:17692
##  Class :character          Class :character
##  Mode  :character          Mode  :character
##
##
##
##  Species..ASFIS.species..2 Fishing.area..FAO.major.fishing.area.
##  Length:17692              Min.   :18.00
##  Class :character          1st Qu.:31.00
##  Mode  :character          Median :37.00
##                            Mean   :45.34
##                            3rd Qu.:57.00
##                            Max.   :88.00
##  Measure..Measure.     X1950              X1951
##  Length:17692       Length:17692       Length:17692
##  Class :character   Class :character   Class :character
##  Mode  :character   Mode  :character   Mode  :character
##
##
##
##     X1952              X1953              X1954
##  Length:17692       Length:17692       Length:17692
##  Class :character   Class :character   Class :character
##  Mode  :character   Mode  :character   Mode  :character
##
##
##
##     X1955              X1956              X1957
##  Length:17692       Length:17692       Length:17692
##  Class :character   Class :character   Class :character
##  Mode  :character   Mode  :character   Mode  :character
##
##
##
##     X1958              X1959              X1960
##  Length:17692       Length:17692       Length:17692
##  Class :character   Class :character   Class :character
##  Mode  :character   Mode  :character   Mode  :character
##
##
##
##     X1961              X1962              X1963
##  Length:17692       Length:17692       Length:17692
##  Class :character   Class :character   Class :character
##  Mode  :character   Mode  :character   Mode  :character
##
##
##
##     X1964              X1965              X1966
##  Length:17692       Length:17692       Length:17692
##  Class :character   Class :character   Class :character
##  Mode  :character   Mode  :character   Mode  :character
##
##
##
##     X1967              X1968              X1969
##  Length:17692       Length:17692       Length:17692
##  Class :character   Class :character   Class :character
##  Mode  :character   Mode  :character   Mode  :character
##
##
##
##     X1970              X1971              X1972
##  Length:17692       Length:17692       Length:17692
##  Class :character   Class :character   Class :character
##  Mode  :character   Mode  :character   Mode  :character
##
##
##
##     X1973              X1974              X1975
##  Length:17692       Length:17692       Length:17692
##  Class :character   Class :character   Class :character
##  Mode  :character   Mode  :character   Mode  :character
##
##
##
##     X1976              X1977              X1978
##  Length:17692       Length:17692       Length:17692
##  Class :character   Class :character   Class :character
##  Mode  :character   Mode  :character   Mode  :character
##
##
##
##     X1979              X1980              X1981
##  Length:17692       Length:17692       Length:17692
##  Class :character   Class :character   Class :character
##  Mode  :character   Mode  :character   Mode  :character
##
##
##
##     X1982              X1983              X1984
##  Length:17692       Length:17692       Length:17692
##  Class :character   Class :character   Class :character
##  Mode  :character   Mode  :character   Mode  :character
##
##
##
##     X1985              X1986              X1987
##  Length:17692       Length:17692       Length:17692
##  Class :character   Class :character   Class :character
##  Mode  :character   Mode  :character   Mode  :character
##
##
##
##     X1988              X1989              X1990
##  Length:17692       Length:17692       Length:17692
##  Class :character   Class :character   Class :character
##  Mode  :character   Mode  :character   Mode  :character
##
##
##
##     X1991              X1992              X1993
##  Length:17692       Length:17692       Length:17692
##  Class :character   Class :character   Class :character
##  Mode  :character   Mode  :character   Mode  :character
##
##
##
##     X1994              X1995              X1996
##  Length:17692       Length:17692       Length:17692
##  Class :character   Class :character   Class :character
##  Mode  :character   Mode  :character   Mode  :character
##
##
##
##     X1997              X1998              X1999
##  Length:17692       Length:17692       Length:17692
##  Class :character   Class :character   Class :character
##  Mode  :character   Mode  :character   Mode  :character
##
##
##
##     X2000              X2001              X2002
##  Length:17692       Length:17692       Length:17692
##  Class :character   Class :character   Class :character
##  Mode  :character   Mode  :character   Mode  :character
##
##
##
##     X2003              X2004              X2005
##  Length:17692       Length:17692       Length:17692
##  Class :character   Class :character   Class :character
##  Mode  :character   Mode  :character   Mode  :character
##
##
##
##     X2006              X2007              X2008
##  Length:17692       Length:17692       Length:17692
##  Class :character   Class :character   Class :character
##  Mode  :character   Mode  :character   Mode  :character
##
##
##
##     X2009              X2010              X2011
##  Length:17692       Length:17692       Length:17692
##  Class :character   Class :character   Class :character
##  Mode  :character   Mode  :character   Mode  :character
##
##
##
##     X2012
##  Length:17692
##  Class :character
##  Mode  :character
##
##
## 
if (interactive()) View(fao) # interactive==T if in Console, not knitting

Tidy data

In general, it is good practice to have your data organized in a “tidy” format.

In tidy data:

  • Each variable forms a column
  • Each observation forms a row
  • Each type of observational unit forms a table

Main verbs of dplyr and tidyr

Tidyr and dplyr are designed to help manipulate data sets, allowing you to convert between wide and long formats, fill in missing values and combinations, separate or merge multiple columns, rename and create new variables, and summarize data according to grouping variables.

Dplyr and tidyr rely on the following main verbs:

  • Tidyr
  • gather() and spread() convert data between wide and long format
  • separate() and unite() separate a single column into multiple columns and vice versa
  • complete() turns implicit missing values in explicit missing values by completing missing data combinations

  • Dplyr
  • filter() subset data based on logical criteria
  • select() select certain columns
  • arrange() order rows by value of a column
  • rename() rename columns
  • group_by() group data by common variables for performing calculations
  • mutate() create a new variable/column
  • summarize() summarize data into a single row of values

Note that unquoted variable names are used by default in tidyr and dplyr functions.

We’ll use these verbs to process the raw FAO landings data into a more manageable tidy format.

Gather and Spread

First let’s convert the FAO data from the current wide format to a long format.

# Let's convert the fao data from it's current wide format to a long format using gather(). Note the use of helper fnc
d <- gather(fao, key='Year', value='Catch', num_range('X',1950:2012)) # ?select for num_range()

# We can convert back to wide format with the spread function by calling the previously created variables
spread(d,Year, Catch)
## Source: local data frame [17,692 x 71]
##
##    Country..Country.      Species..ASFIS.species. Species..ISSCAAP.group.
##                (chr)                        (chr)                   (int)
## 1            Albania Angelsharks, sand devils nei                      38
## 2            Albania              Atlantic bonito                      36
## 3            Albania               Barracudas nei                      37
## 4            Albania          Blue and red shrimp                      45
## 5            Albania     Blue whiting(=Poutassou)                      32
## 6            Albania                     Bluefish                      37
## 7            Albania                        Bogue                      33
## 8            Albania               Caramote prawn                      45
## 9            Albania   Catsharks, nursehounds nei                      38
## 10           Albania            Common cuttlefish                      57
## ..               ...                          ...                     ...
## Variables not shown: Species..ISSCAAP.group..1 (chr),
##   Species..ASFIS.species..1 (chr), Species..ASFIS.species..2 (chr),
##   Fishing.area..FAO.major.fishing.area. (int), Measure..Measure. (chr),
##   X1950 (chr), X1951 (chr), X1952 (chr), X1953 (chr), X1954 (chr), X1955
##   (chr), X1956 (chr), X1957 (chr), X1958 (chr), X1959 (chr), X1960 (chr),
##   X1961 (chr), X1962 (chr), X1963 (chr), X1964 (chr), X1965 (chr), X1966
##   (chr), X1967 (chr), X1968 (chr), X1969 (chr), X1970 (chr), X1971 (chr),
##   X1972 (chr), X1973 (chr), X1974 (chr), X1975 (chr), X1976 (chr), X1977
##   (chr), X1978 (chr), X1979 (chr), X1980 (chr), X1981 (chr), X1982 (chr),
##   X1983 (chr), X1984 (chr), X1985 (chr), X1986 (chr), X1987 (chr), X1988
##   (chr), X1989 (chr), X1990 (chr), X1991 (chr), X1992 (chr), X1993 (chr),
##   X1994 (chr), X1995 (chr), X1996 (chr), X1997 (chr), X1998 (chr), X1999
##   (chr), X2000 (chr), X2001 (chr), X2002 (chr), X2003 (chr), X2004 (chr),
##   X2005 (chr), X2006 (chr), X2007 (chr), X2008 (chr), X2009 (chr), X2010
##   (chr), X2011 (chr), X2012 (chr)
if (interactive()) View(d) # interactive==T if in Console, not knitting
# to handle: '-','...',' F','X'

Rename

Now let’s rename the columns to more manageable names (syntax is new name = old name)

# Note the use of backticks around column names with special characters like "("
d <- rename(
  d,
  country     = Country..Country.,
  commname    = Species..ASFIS.species.,
  sciname     = Species..ASFIS.species..2,
  spcode      = Species..ASFIS.species..1,
  spgroup     = Species..ISSCAAP.group.,
  spgroupname = Species..ISSCAAP.group..1,
  regionfao   = Fishing.area..FAO.major.fishing.area.,
  unit        = Measure..Measure.,
  year        = Year,catch=Catch)
d
## Source: local data frame [1,114,596 x 10]
##
##    country                     commname spgroup
##      (chr)                        (chr)   (int)
## 1  Albania Angelsharks, sand devils nei      38
## 2  Albania              Atlantic bonito      36
## 3  Albania               Barracudas nei      37
## 4  Albania          Blue and red shrimp      45
## 5  Albania     Blue whiting(=Poutassou)      32
## 6  Albania                     Bluefish      37
## 7  Albania                        Bogue      33
## 8  Albania               Caramote prawn      45
## 9  Albania   Catsharks, nursehounds nei      38
## 10 Albania            Common cuttlefish      57
## ..     ...                          ...     ...
## Variables not shown: spgroupname (chr), spcode (chr), sciname (chr),
##   regionfao (int), unit (chr), year (chr), catch (chr)

Select

Remove unwanted columns and observations.

# we could chose all the columns to keep
select(d,country, commname, sciname, spcode, spgroupname, regionfao, year, catch)
## Source: local data frame [1,114,596 x 8]
##
##    country                     commname                  sciname
##      (chr)                        (chr)                    (chr)
## 1  Albania Angelsharks, sand devils nei              Squatinidae
## 2  Albania              Atlantic bonito              Sarda sarda
## 3  Albania               Barracudas nei            Sphyraena spp
## 4  Albania          Blue and red shrimp      Aristeus antennatus
## 5  Albania     Blue whiting(=Poutassou) Micromesistius poutassou
## 6  Albania                     Bluefish      Pomatomus saltatrix
## 7  Albania                        Bogue              Boops boops
## 8  Albania               Caramote prawn       Penaeus kerathurus
## 9  Albania   Catsharks, nursehounds nei         Scyliorhinus spp
## 10 Albania            Common cuttlefish        Sepia officinalis
## ..     ...                          ...                      ...
## Variables not shown: spcode (chr), spgroupname (chr), regionfao (int),
##   year (chr), catch (chr)
# but it's easier to just specify the columns to get rid of
d<-select(d,-spgroup,-unit)

There are also a number of helper functions that can be used in conjunction with select() to let you select without individually listing all those you wish to keep or drop. We used a helper function previously in our gather() function and now we’ll try a few others.

# select all coloumns that begin with the letter s
select(d, starts_with('s'))
## Source: local data frame [1,114,596 x 3]
##
##                        spgroupname     spcode                  sciname
##                              (chr)      (chr)                    (chr)
## 1          Sharks, rays, chimaeras 10903XXXXX              Squatinidae
## 2       Tunas, bonitos, billfishes 1750100101              Sarda sarda
## 3     Miscellaneous pelagic fishes 17710001XX            Sphyraena spp
## 4                  Shrimps, prawns 2280203101      Aristeus antennatus
## 5            Cods, hakes, haddocks 1480403301 Micromesistius poutassou
## 6     Miscellaneous pelagic fishes 1702021301      Pomatomus saltatrix
## 7     Miscellaneous coastal fishes 1703926101              Boops boops
## 8                  Shrimps, prawns 2280100117       Penaeus kerathurus
## 9          Sharks, rays, chimaeras 10801003XX         Scyliorhinus spp
## 10 Squids, cuttlefishes, octopuses 3210200202        Sepia officinalis
## ..                             ...        ...                      ...
# select columns that match a regular expression
select(d, matches('*name'))
## Source: local data frame [1,114,596 x 3]
##
##                        commname                     spgroupname
##                           (chr)                           (chr)
## 1  Angelsharks, sand devils nei         Sharks, rays, chimaeras
## 2               Atlantic bonito      Tunas, bonitos, billfishes
## 3                Barracudas nei    Miscellaneous pelagic fishes
## 4           Blue and red shrimp                 Shrimps, prawns
## 5      Blue whiting(=Poutassou)           Cods, hakes, haddocks
## 6                      Bluefish    Miscellaneous pelagic fishes
## 7                         Bogue    Miscellaneous coastal fishes
## 8                Caramote prawn                 Shrimps, prawns
## 9    Catsharks, nursehounds nei         Sharks, rays, chimaeras
## 10            Common cuttlefish Squids, cuttlefishes, octopuses
## ..                          ...                             ...
## Variables not shown: sciname (chr)
# select columns between two columns by referencing their position like normal [,x:y] syntax
select(d, country, spcode:year)
## Source: local data frame [1,114,596 x 5]
##
##    country     spcode                  sciname regionfao  year
##      (chr)      (chr)                    (chr)     (int) (chr)
## 1  Albania 10903XXXXX              Squatinidae        37 X1950
## 2  Albania 1750100101              Sarda sarda        37 X1950
## 3  Albania 17710001XX            Sphyraena spp        37 X1950
## 4  Albania 2280203101      Aristeus antennatus        37 X1950
## 5  Albania 1480403301 Micromesistius poutassou        37 X1950
## 6  Albania 1702021301      Pomatomus saltatrix        37 X1950
## 7  Albania 1703926101              Boops boops        37 X1950
## 8  Albania 2280100117       Penaeus kerathurus        37 X1950
## 9  Albania 10801003XX         Scyliorhinus spp        37 X1950
## 10 Albania 3210200202        Sepia officinalis        37 X1950
## ..     ...        ...                      ...       ...   ...
# select every column (though I haven't found a situation where this is useful yet...)
select(d,everything())
## Source: local data frame [1,114,596 x 8]
##
##    country                     commname                     spgroupname
##      (chr)                        (chr)                           (chr)
## 1  Albania Angelsharks, sand devils nei         Sharks, rays, chimaeras
## 2  Albania              Atlantic bonito      Tunas, bonitos, billfishes
## 3  Albania               Barracudas nei    Miscellaneous pelagic fishes
## 4  Albania          Blue and red shrimp                 Shrimps, prawns
## 5  Albania     Blue whiting(=Poutassou)           Cods, hakes, haddocks
## 6  Albania                     Bluefish    Miscellaneous pelagic fishes
## 7  Albania                        Bogue    Miscellaneous coastal fishes
## 8  Albania               Caramote prawn                 Shrimps, prawns
## 9  Albania   Catsharks, nursehounds nei         Sharks, rays, chimaeras
## 10 Albania            Common cuttlefish Squids, cuttlefishes, octopuses
## ..     ...                          ...                             ...
## Variables not shown: spcode (chr), sciname (chr), regionfao (int), year
##   (chr), catch (chr)

Arrange

Arrange entries by country, scientific name, fao region and year. You can use desc() within arrange() to control which variables you want to order in ascending or descending fashion

# arrange by country, sciname, regionfao, and year
d<-arrange(d,country,sciname,regionfao,year)

# if we'd like the years to be descending
arrange(d, country, desc(sciname), regionfao, desc(year))
## Source: local data frame [1,114,596 x 8]
##
##    country  commname                   spgroupname     spcode    sciname
##      (chr)     (chr)                         (chr)      (chr)      (chr)
## 1  Albania John dory Miscellaneous demersal fishes 1620100101 Zeus faber
## 2  Albania John dory Miscellaneous demersal fishes 1620100101 Zeus faber
## 3  Albania John dory Miscellaneous demersal fishes 1620100101 Zeus faber
## 4  Albania John dory Miscellaneous demersal fishes 1620100101 Zeus faber
## 5  Albania John dory Miscellaneous demersal fishes 1620100101 Zeus faber
## 6  Albania John dory Miscellaneous demersal fishes 1620100101 Zeus faber
## 7  Albania John dory Miscellaneous demersal fishes 1620100101 Zeus faber
## 8  Albania John dory Miscellaneous demersal fishes 1620100101 Zeus faber
## 9  Albania John dory Miscellaneous demersal fishes 1620100101 Zeus faber
## 10 Albania John dory Miscellaneous demersal fishes 1620100101 Zeus faber
## ..     ...       ...                           ...        ...        ...
## Variables not shown: regionfao (int), year (chr), catch (chr)
# if we want to first order by species
arrange(d, sciname, country, regionfao, year)
## Source: local data frame [1,114,596 x 8]
##
##    country        commname                  spgroupname     spcode
##      (chr)           (chr)                        (chr)      (chr)
## 1    Qatar Flat needlefish Miscellaneous pelagic fishes 1470100801
## 2    Qatar Flat needlefish Miscellaneous pelagic fishes 1470100801
## 3    Qatar Flat needlefish Miscellaneous pelagic fishes 1470100801
## 4    Qatar Flat needlefish Miscellaneous pelagic fishes 1470100801
## 5    Qatar Flat needlefish Miscellaneous pelagic fishes 1470100801
## 6    Qatar Flat needlefish Miscellaneous pelagic fishes 1470100801
## 7    Qatar Flat needlefish Miscellaneous pelagic fishes 1470100801
## 8    Qatar Flat needlefish Miscellaneous pelagic fishes 1470100801
## 9    Qatar Flat needlefish Miscellaneous pelagic fishes 1470100801
## 10   Qatar Flat needlefish Miscellaneous pelagic fishes 1470100801
## ..     ...             ...                          ...        ...
## Variables not shown: sciname (chr), regionfao (int), year (chr), catch
##   (chr)

Mutate

Mutate can be used to edit existing variables or create new ones.

d <- mutate(
  d,
  year      = as.numeric(str_replace(year, 'X', '')), # strip X off all year values and convert to numeric
  catch     = as.numeric(str_replace(catch, c(' F','...','-'), replacement = '')),
  logcatch  = log10(catch)) # create a  new variable of log catch
## Warning in eval(substitute(expr), envir, enclos): NAs introduced by
## coercion

Filter

Remove unwanted rows/observations.

# remove the "Totals" values and any years with NA catch values
d<-filter(d,!(country %in% c('Totals - Quantity (number)','Totals - Quantity (tonnes)')) & !is.na(catch))

# print data
d
## Source: local data frame [310,619 x 9]
##
##    country                      commname                  spgroupname
##      (chr)                         (chr)                        (chr)
## 1  Albania           Blue and red shrimp              Shrimps, prawns
## 2  Albania           Blue and red shrimp              Shrimps, prawns
## 3  Albania           Blue and red shrimp              Shrimps, prawns
## 4  Albania           Blue and red shrimp              Shrimps, prawns
## 5  Albania           Blue and red shrimp              Shrimps, prawns
## 6  Albania           Blue and red shrimp              Shrimps, prawns
## 7  Albania Silversides(=Sand smelts) nei Miscellaneous pelagic fishes
## 8  Albania Silversides(=Sand smelts) nei Miscellaneous pelagic fishes
## 9  Albania Silversides(=Sand smelts) nei Miscellaneous pelagic fishes
## 10 Albania Silversides(=Sand smelts) nei Miscellaneous pelagic fishes
## ..     ...                           ...                          ...
## Variables not shown: spcode (chr), sciname (chr), regionfao (int), year
##   (dbl), catch (dbl), logcatch (dbl)

Piping and chaining code

While the above workflow is perfectly acceptable, dplyr allows you to use the pipe (%>%) operator to chain functions together. Chaining code allows you to streamline your workflow and make it easier to read.

When using the %>% operator, first specify the data frame that all following functions will use. For the rest of the chain the data frame argument can be omitted from the remaining functions.

Now consider the same process as before only using pipes and a single dplyr chain:

d <- fao %>%
  gather(key='Year',value = 'Catch',num_range('X',1950:2012)) %>% # convert to long format
  rename(
    country     = Country..Country., # rename columns
    #country     = `Country (Country)`, # backtick trick!
    commname    = Species..ASFIS.species.,
    spcode      = Species..ASFIS.species..1,
    sciname     = Species..ASFIS.species..2,
    spgroup     = Species..ISSCAAP.group.,
    spgroupname = Species..ISSCAAP.group..1,
    regionfao   = Fishing.area..FAO.major.fishing.area.,
    unit        = Measure..Measure.,
    year        = Year,
    catch       = Catch) %>%
  select(-spgroup,-unit) %>% # drop spgroup, regionfaoname, and unit variables
  arrange(country,sciname,regionfao,year) %>% # order by country, sciname, regionfao, and year
  mutate(
    year        = as.numeric(str_replace(year, 'X', '')), # strip X off all year values and convert to numeric
    catch       = as.numeric(gsub(catch, pattern=c(' F'), replacement = '', fixed = T)),
    logcatch    = log10(catch)) %>% # create a  new variable of log catch
  filter(!country %in% c('Totals - Quantity (number)','Totals - Quantity (tonnes)') & !is.na(catch)) # remove 'Totals' rows - rows: 1,114,596 -> 310,619
## Warning in eval(substitute(expr), envir, enclos): NAs introduced by
## coercion
# print data frame
d
## Source: local data frame [357,807 x 9]
##
##    country                      commname                  spgroupname
##      (chr)                         (chr)                        (chr)
## 1  Albania           Blue and red shrimp              Shrimps, prawns
## 2  Albania           Blue and red shrimp              Shrimps, prawns
## 3  Albania           Blue and red shrimp              Shrimps, prawns
## 4  Albania           Blue and red shrimp              Shrimps, prawns
## 5  Albania           Blue and red shrimp              Shrimps, prawns
## 6  Albania           Blue and red shrimp              Shrimps, prawns
## 7  Albania Silversides(=Sand smelts) nei Miscellaneous pelagic fishes
## 8  Albania Silversides(=Sand smelts) nei Miscellaneous pelagic fishes
## 9  Albania Silversides(=Sand smelts) nei Miscellaneous pelagic fishes
## 10 Albania Silversides(=Sand smelts) nei Miscellaneous pelagic fishes
## ..     ...                           ...                          ...
## Variables not shown: spcode (chr), sciname (chr), regionfao (int), year
##   (dbl), catch (dbl), logcatch (dbl)

By chaining our code we were able to reproduce the same data frame without the need to continually overwrite it, and we can easily read each step in the process by observing the different verbs. We also only needed to reference the original data frame (fao) at the beginning of the chain rather than in each function call.

Complete

Now our data is nice and tidy, but we realize that we actually want to retain NA values for years with missing catch data. We could just go back and remove the second argument from our filter() function. Or we could use the nifty complete() function to add in the missing combinations.

d %>%
  complete(year = 1950:2012)
## Source: local data frame [357,807 x 9]
##
##     year country                     commname
##    (dbl)   (chr)                        (chr)
## 1   1950 Albania            Marine fishes nei
## 2   1950 Algeria             European anchovy
## 3   1950 Algeria                European hake
## 4   1950 Algeria Surmullets(=Red mullets) nei
## 5   1950 Algeria               Norway lobster
## 6   1950 Algeria            Marine fishes nei
## 7   1950 Algeria       Deep-water rose shrimp
## 8   1950 Algeria  Rays, stingrays, mantas nei
## 9   1950 Algeria  European pilchard(=Sardine)
## 10  1950 Algeria            Atlantic mackerel
## ..   ...     ...                          ...
## Variables not shown: spgroupname (chr), spcode (chr), sciname (chr),
##   regionfao (int), catch (dbl), logcatch (dbl)
d %>%
  group_by(country,sciname,commname,regionfao,spgroupname,spcode) %>%
  complete(year = 1950:2012) %>%
  ungroup()
## Source: local data frame [1,099,791 x 9]
##
##    country             sciname            commname regionfao
##      (chr)               (chr)               (chr)     (int)
## 1  Albania Aristeus antennatus Blue and red shrimp        37
## 2  Albania Aristeus antennatus Blue and red shrimp        37
## 3  Albania Aristeus antennatus Blue and red shrimp        37
## 4  Albania Aristeus antennatus Blue and red shrimp        37
## 5  Albania Aristeus antennatus Blue and red shrimp        37
## 6  Albania Aristeus antennatus Blue and red shrimp        37
## 7  Albania Aristeus antennatus Blue and red shrimp        37
## 8  Albania Aristeus antennatus Blue and red shrimp        37
## 9  Albania Aristeus antennatus Blue and red shrimp        37
## 10 Albania Aristeus antennatus Blue and red shrimp        37
## ..     ...                 ...                 ...       ...
## Variables not shown: spgroupname (chr), spcode (chr), year (dbl), catch
##   (dbl), logcatch (dbl)

Separate and Unite

The df$spcode variable actually consists of 5 individual parts.

We decide we want to create a new column for each taxonomic division of the spcode. We can accomplish this with separate() and undue it with unite()

# create new variables for each taxonomic component
d<-separate(d,spcode, into = c('maintaxa','order','family','genus','species'), sep = c(2,4,6,9))

# recombine the columns with unite
d<-unite(d, col = spcode, maintaxa:species, sep = '') # Note - we can use helper functions here if needed

Joins

So far we’ve been working with a single data frame, but dplyr provides a handful of really useful join functions that allow you to combine datasets in a variety of ways. To demonstrate the different methods of joining, we will combine our FAO dataset with a dataset of life history information from FishBase.

Dplyr allows for mutating joins and filtering joins. Mutating joins will combine information from both data frames in different ways, while filtering joins will filter a single dataset based on matches in another data set.

For joins to work, variable names must be the same in both datasets. This often requires using rename() prior to your join functions if you do not want to permanently alter the variable names in each dataset.

  • Mutating joins
  • left_join(a, b, by = c('...')) join matching rows from b to a by matching variables in vector
  • right_join(a, b, by = c('...')) join matching rows from a to b by matching variables in vector
  • inner_join(a, b, by = c('...')) join data, retaining only rows in both a and b
  • full_join(a, b, by = c('...')) join data, retaining all values, all rows

Lets use join functions to explore adding life history parameters to our FAO data

# read in life history data
load(file = 'data/mpack.Rdata')
lh<-mpack$lh
rm(mpack)

lh<-lh %>%
  tbl_df() %>%
  rename(sciname=sname) %>% # rename to sciname for joining
  select(sciname,vbk,temp,maxl,agem) %>% # select variables we wish to add
  slice(match(unique(lh$sname),lh$sname))

# first let's pull out all species US fisheries
us<- d %>%
  ungroup() %>%
  filter(country=='United States of America' & year==2012) %>%
  select(country, sciname, commname, spgroupname) %>%
  distinct()

# left join to retain all data in our d data frame.
us %>%
  left_join(lh, by = 'sciname') # we only need to specify the right hand data set to join lh with since we've piped
## Source: local data frame [308 x 8]
##
##                     country                 sciname
##                       (chr)                   (chr)
## 1  United States of America  Acanthocybium solandri
## 2  United States of America            Acanthuridae
## 3  United States of America Acipenser transmontanus
## 4  United States of America             Alopias spp
## 5  United States of America        Alopias vulpinus
## 6  United States of America    Alosa pseudoharengus
## 7  United States of America       Alosa sapidissima
## 8  United States of America           Ammodytes spp
## 9  United States of America          Anadara ovalis
## 10 United States of America      Anoplopoma fimbria
## ..                      ...                     ...
## Variables not shown: commname (chr), spgroupname (chr), vbk (dbl), temp
##   (dbl), maxl (dbl), agem (dbl)
# right join to keep all lh data.
us %>%
  right_join(lh, by = 'sciname')
## Source: local data frame [1,059 x 8]
##
##                     country                  sciname            commname
##                       (chr)                    (chr)               (chr)
## 1                        NA   Notorynchus cepedianus                  NA
## 2                        NA       Cetorhinus maximus                  NA
## 3                        NA        Carcharias taurus                  NA
## 4  United States of America              Alopias spp Thresher sharks nei
## 5  United States of America         Alopias vulpinus            Thresher
## 6  United States of America        Isurus oxyrinchus       Shortfin mako
## 7                        NA    Scyliorhinus canicula                  NA
## 8  United States of America          Prionace glauca          Blue shark
## 9                        NA Carcharhinus falciformis                  NA
## 10                       NA  Carcharhinus brachyurus                  NA
## ..                      ...                      ...                 ...
## Variables not shown: spgroupname (chr), vbk (dbl), temp (dbl), maxl (dbl),
##   agem (dbl)
# inner join to only keep data for which we have matches in both data sets
us %>%
  inner_join(lh, by = 'sciname')
## Source: local data frame [245 x 8]
##
##                     country                     sciname
##                       (chr)                       (chr)
## 1  United States of America      Acanthocybium solandri
## 2  United States of America                Acanthuridae
## 3  United States of America                 Alopias spp
## 4  United States of America            Alopias vulpinus
## 5  United States of America        Alosa pseudoharengus
## 6  United States of America           Alosa sapidissima
## 7  United States of America               Ammodytes spp
## 8  United States of America              Anadara ovalis
## 9  United States of America          Anoplopoma fimbria
## 10 United States of America Archosargus probatocephalus
## ..                      ...                         ...
## Variables not shown: commname (chr), spgroupname (chr), vbk (dbl), temp
##   (dbl), maxl (dbl), agem (dbl)
# full join to keep all data for both data sets
us %>%
  full_join(lh, by = 'sciname')
## Source: local data frame [1,122 x 8]
##
##                     country                 sciname
##                       (chr)                   (chr)
## 1  United States of America  Acanthocybium solandri
## 2  United States of America            Acanthuridae
## 3  United States of America Acipenser transmontanus
## 4  United States of America             Alopias spp
## 5  United States of America        Alopias vulpinus
## 6  United States of America    Alosa pseudoharengus
## 7  United States of America       Alosa sapidissima
## 8  United States of America           Ammodytes spp
## 9  United States of America          Anadara ovalis
## 10 United States of America      Anoplopoma fimbria
## ..                      ...                     ...
## Variables not shown: commname (chr), spgroupname (chr), vbk (dbl), temp
##   (dbl), maxl (dbl), agem (dbl)

Analyzing and Manipulating Data

Now that we have our cleaned data in a tidy format let’s do some analyses. First, here are a few more simple examples of chaining code to select, filter, and arrange our data to obtain different subsets.

# Canada's fisheries from largest to smallest in 2012
d %>%
  filter(country=='Canada' & year==2012) %>%
  select(year,country,commname,catch) %>%
  arrange(desc(catch))
## Source: local data frame [90 x 4]
##
##     year country               commname  catch
##    (dbl)   (chr)                  (chr)  (dbl)
## 1   2012  Canada         Northern prawn 143350
## 2   2012  Canada       Atlantic herring 113989
## 3   2012  Canada             Queen crab  92902
## 4   2012  Canada       American lobster  71528
## 5   2012  Canada   American sea scallop  52845
## 6   2012  Canada     North Pacific hake  46913
## 7   2012  Canada                Capelin  31778
## 8   2012  Canada   Stimpson's surf clam  22005
## 9   2012  Canada Atlantic redfishes nei  14974
## 10  2012  Canada      Greenland halibut  13432
## ..   ...     ...                    ...    ...
# All fisheries in the Northwest Atlantic with a catch over 1000 MT
d %>%
  filter(regionfao==21 & year==2012 & catch>=1000) %>%
  select(country,commname,regionfao,catch) %>%
  arrange(desc(catch))
## Source: local data frame [95 x 4]
##
##                     country             commname regionfao  catch
##                       (chr)                (chr)     (int)  (dbl)
## 1  United States of America    Atlantic menhaden        21 224261
## 2  United States of America American sea scallop        21 214900
## 3                    Canada       Northern prawn        21 143350
## 4  United States of America         Ocean quahog        21 131425
## 5                    Canada     Atlantic herring        21 113989
## 6                 Greenland       Northern prawn        21 109303
## 7  United States of America   Atlantic surf clam        21  99004
## 8                    Canada           Queen crab        21  92902
## 9  United States of America     Atlantic herring        21  86415
## 10                   Canada     American lobster        21  71528
## ..                      ...                  ...       ...    ...
# Which countries have the 10 largest shark fisheries?
d %>%
  filter(spgroupname=='Sharks, rays, chimaeras' & year==2012) %>%
  select(country,commname,catch) %>%
  arrange(desc(catch)) %>%
  slice(1:10)
## Source: local data frame [10 x 3]
##
##                     country                       commname catch
##                       (chr)                          (chr) (dbl)
## 1                     India Sharks, rays, skates, etc. nei 53652
## 2                 Indonesia  Stingrays, butterfly rays nei 39812
## 3                     Spain                     Blue shark 27159
## 4                     India Sharks, rays, skates, etc. nei 22105
## 5                 Indonesia             Requiem sharks nei 20611
## 6  Taiwan Province of China Sharks, rays, skates, etc. nei 18465
## 7                 Argentina    Rays, stingrays, mantas nei 15168
## 8                     Spain                     Blue shark 14784
## 9                     Yemen Sharks, rays, skates, etc. nei 13217
## 10                   Mexico Sharks, rays, skates, etc. nei 12376

Grouping, Summarizing, and Mutating Data

Dplyr uses two main verbs to analyze data, summarize() and mutate(). Summary functions will summarize data two produce a single row of output while mutate functions create a new variable the same length as the input data. For both functions, you first indicate the name of the variable that will be created and then specify the calculation to be performed.

  • Example: totalcatch=sum(catch,na.rm=T)

The group_by() function lets you specify the level across which to apply your calculations.

  • A key thing to remember is to always ungroup() your data if you intend to perform additional calculations, as grouped data frames can result in incorrect results downstream if performed at different levels.

Using group_by() and summarize() let’s calculate total global harvest from 1950 to 2012 for several groups of data

# Total global harvest
global <- d %>%
  ungroup() %>%
  group_by(year) %>%
  summarize(totalcatch=sum(catch,na.rm=T)) %>%
  ggplot(aes(x=year,y=totalcatch)) +
  geom_line()
global

# Global harvest by country
cntry <- d %>%
  group_by(year,country) %>%
  summarize(totalcatch=sum(catch, na.rm=T)) %>%
  ungroup() %>% # -- Here's an example of why you need to ungroup! --
  arrange(country)
cntry
## Source: local data frame [11,156 x 3]
##
##     year country totalcatch
##    (dbl)   (chr)      (dbl)
## 1   1950 Albania       1000
## 2   1951 Albania       1100
## 3   1952 Albania       1400
## 4   1953 Albania       1700
## 5   1954 Albania       1600
## 6   1955 Albania       1700
## 7   1956 Albania       1700
## 8   1957 Albania       1800
## 9   1958 Albania       1700
## 10  1959 Albania       1800
## ..   ...     ...        ...
# Global harvest by species category
spcatch <- d %>%
  group_by(year,spgroupname) %>%
  summarize(totalcatch=sum(catch, na.rm=T)) %>%
  ungroup() %>%
  arrange(spgroupname)
spcatch
## Source: local data frame [1,886 x 3]
##
##     year               spgroupname totalcatch
##    (dbl)                     (chr)      (dbl)
## 1   1950 Abalones, winkles, conchs      30509
## 2   1951 Abalones, winkles, conchs      30964
## 3   1952 Abalones, winkles, conchs      29989
## 4   1953 Abalones, winkles, conchs      30524
## 5   1954 Abalones, winkles, conchs      26698
## 6   1955 Abalones, winkles, conchs      29160
## 7   1956 Abalones, winkles, conchs      32553
## 8   1957 Abalones, winkles, conchs      31148
## 9   1958 Abalones, winkles, conchs      42446
## 10  1959 Abalones, winkles, conchs      32584
## ..   ...                       ...        ...
# USA harvest by species category over time
usa <- d %>%
  filter(country=='United States of America') %>%
  group_by(year,country,spgroupname) %>%
  summarize(totalcatch=sum(catch,na.rm=T)) %>%
  ungroup() %>%
  arrange(spgroupname)
usa
## Source: local data frame [1,628 x 4]
##
##     year                  country               spgroupname totalcatch
##    (dbl)                    (chr)                     (chr)      (dbl)
## 1   1950 United States of America Abalones, winkles, conchs       2499
## 2   1951 United States of America Abalones, winkles, conchs       2554
## 3   1952 United States of America Abalones, winkles, conchs       2929
## 4   1953 United States of America Abalones, winkles, conchs       3164
## 5   1954 United States of America Abalones, winkles, conchs       2738
## 6   1955 United States of America Abalones, winkles, conchs       3100
## 7   1956 United States of America Abalones, winkles, conchs       3193
## 8   1957 United States of America Abalones, winkles, conchs       3788
## 9   1958 United States of America Abalones, winkles, conchs       2986
## 10  1959 United States of America Abalones, winkles, conchs       3024
## ..   ...                      ...                       ...        ...

Now let’s use mutate to calculate some additional information for our datasets

# Calculate what % of global catch each country contributes in each year and for rank each year by that %
cntry %>%
  group_by(year) %>%
  mutate(
    globalcatch = sum(totalcatch,na.rm=T),
    globalrank  = dense_rank(totalcatch)) %>% # global catch and cntry rank
  group_by(year,country) %>% # now we group by a different level before our next calculation
  mutate(
    percglobal = 100*(totalcatch/globalcatch)) %>%
  group_by(country) %>%
  mutate(
    ingrouprank = dense_rank(totalcatch))
## Source: local data frame [11,156 x 7]
## Groups: country [200]
##
##     year country totalcatch globalcatch globalrank  percglobal ingrouprank
##    (dbl)   (chr)      (dbl)       (dbl)      (int)       (dbl)       (int)
## 1   1950 Albania       1000    16780913         13 0.005959151           2
## 2   1951 Albania       1100    19063253         14 0.005770264           3
## 3   1952 Albania       1400    20740282         16 0.006750149           5
## 4   1953 Albania       1700    20844610         18 0.008155586           9
## 5   1954 Albania       1600    22557865         18 0.007092870           7
## 6   1955 Albania       1700    23751272         19 0.007157511           9
## 7   1956 Albania       1700    25437283         18 0.006683104           9
## 8   1957 Albania       1800    25606086         20 0.007029579          12
## 9   1958 Albania       1700    26229900         20 0.006481153           9
## 10  1959 Albania       1800    28577628         21 0.006298633          12
## ..   ...     ...        ...         ...        ...         ...         ...

Using Dplyr with broom and ggplot2

One of the best aspects of working with tidy data and dplyr is how easy it makes it to quickly manipulate and plot your data. Property organized, it’s a piece of cake to quickly make summaries and plots of your data without making all kinds of “temporary” files or lines of spaghetti code for plotting. You can also basically eliminate loops from your coding for all situations except that those that require dynamic updating (e.g. population models).

For this next exercise, we’re going to use tidyr, dplyr, broom, and ggplot2 to fit a model, run diagnostics, and plot results.

It’s 3am. You’ve been chasing the same cryptic error message for two days ( Error: towel not found, don't panic!). You decide enough is enough: you’re going to pack it in, buy a boat and become a fisherman. The only problem is, years of coding have left you with no knowledge of the outside world besides what R and data can tell you. How are you supposed to know what to fish for, or where to fish? Luckily, you have some data, so you turn to your laptop one last time before hurling it off of a cliff in a ritualistic sacrifice to the sea gods.

You want to find a fishery to join based on two criteria: high average catch, and low average variability. You might now know these data though, so you want to be able to predict what fishery to join based on geographic and life history traits.

Our first goals:

  1. Generate a unique ID for each fishery

  2. Calculate the mean log lifetime catch of each fishery

  3. Calculate the coefficient of variation of each fishery

  4. Filter out fisheries with short time series

# Prep our data
dat <- d %>%
  ungroup() %>% #Often a good idea to ungroup before starting something new
  mutate(
    id = paste(country,spcode,regionfao, sep = '_')) %>% #Generate a unique ID for each fishery
  group_by(id) %>%
  mutate(
    mean_log_catch = mean(logcatch, na.rm = T),
    cv_log_catch   = sd(logcatch, na.rm = T)/mean(logcatch, na.rm = T),
    length_catch   = sum(is.na(logcatch) == F & logcatch >0)) %>% # we want to keep some of the other data as well
  filter(
    year == max(year) & length_catch > 10,
    is.finite(mean_log_catch) == T,
    cv_log_catch >0) %>% # We don't want repeated entries, so let's just grab one random year
  select(-year, -catch, -logcatch)

# Always plot!
ggplot(dat, aes(mean_log_catch,cv_log_catch)) +
  geom_point()

OK, we see we’re onto something here: there’s clearly a relationship between average catch and the CV of the catch. We want to build a model that predicts that. Let’s create a composite score of the mean log catch and the inverse of the CV. We’re going to scale the log catches by the maximum log catch, and the CV by the the maximum of 1/CV. We also want to add in our nice life history data

regdat <-  dat %>%
  ungroup() %>% #we want global statistics now
  mutate(
    scaled_ml_catch = mean_log_catch/max(mean_log_catch),
    scaled_cv_catch =  (cv_log_catch/min(cv_log_catch))^-1,
    fishiness       = scaled_ml_catch + scaled_cv_catch) %>%
  left_join(lh, by = 'sciname')

regplot <- regdat %>% #great thing about ggplot is the ability to save as an object and use and modify later
  ggplot(aes(mean_log_catch,cv_log_catch, fill = fishiness)) +
  geom_point(shape = 21) +
  scale_fill_gradient(low = 'red',high = 'green')

regplot # grea

Now we’re getting somewhere! Now, lets run a regression using life history and geographic variables to try and predict the quality of fishing.

reg_vars <- c('regionfao', 'spgroupname', 'vbk','maxl','temp') #specify variables you want

class(regdat$regionfao) #whoops, it things FAO region is an integer, we want a factor
## [1] "integer"
filtered_dat <- regdat %>%
  ungroup() %>%
  mutate(has_all = apply(is.na(regdat[,reg_vars]) == F, 1,all)) %>%
  filter(has_all == T) %>%
  mutate(
    regionfao   = as.factor(regionfao),
    spgroupname = as.factor(spgroupname))

reg_fmla <- as.formula(paste('fishiness ~',paste(reg_vars, collapse = '+'), sep = '')) #create regression formula

fish_model <- lm(reg_fmla, data = filtered_dat) #run a linear regression
summary(fish_model)
##
## Call:
## lm(formula = reg_fmla, data = filtered_dat)
##
## Residuals:
##      Min       1Q   Median       3Q      Max
## -0.64362 -0.12021  0.00152  0.10966  0.86657
##
## Coefficients:
##                                              Estimate Std. Error t value
## (Intercept)                                 0.6601333  0.0281170  23.478
## regionfao27                                 0.0515901  0.0217864   2.368
## regionfao31                                 0.0011936  0.0254237   0.047
## regionfao34                                 0.0544856  0.0240581   2.265
## regionfao37                                -0.0121513  0.0298237  -0.407
## regionfao41                                 0.0299216  0.0277397   1.079
## regionfao47                                 0.0354956  0.0271043   1.310
## regionfao48                                 0.1044720  0.1379318   0.757
## regionfao51                                 0.1217675  0.0251469   4.842
## regionfao57                                 0.0971409  0.0272346   3.567
## regionfao58                                 0.2243586  0.1842908   1.217
## regionfao61                                 0.3047966  0.0334511   9.112
## regionfao67                                 0.0707998  0.0388540   1.822
## regionfao71                                 0.1675909  0.0258878   6.474
## regionfao77                                 0.1091043  0.0261506   4.172
## regionfao81                                 0.0776129  0.0310813   2.497
## regionfao87                                 0.1398581  0.0278864   5.015
## spgroupnameFlounders, halibuts, soles      -0.1839127  0.0305781  -6.015
## spgroupnameHerrings, sardines, anchovies    0.0086945  0.0338028   0.257
## spgroupnameMiscellaneous coastal fishes    -0.2994434  0.0644592  -4.645
## spgroupnameMiscellaneous demersal fishes   -0.1503954  0.0399963  -3.760
## spgroupnameMiscellaneous diadromous fishes -0.3822979  0.0661284  -5.781
## spgroupnameMiscellaneous pelagic fishes    -0.2040183  0.0320385  -6.368
## spgroupnameSalmons, trouts, smelts         -0.2106036  0.0373202  -5.643
## spgroupnameSharks, rays, chimaeras         -0.2216522  0.0305082  -7.265
## spgroupnameSturgeons, paddlefishes         -0.4162103  0.1764759  -2.358
## spgroupnameTunas, bonitos, billfishes      -0.2539178  0.0303525  -8.366
## vbk                                        -0.0551644  0.0221175  -2.494
## maxl                                       -0.0003563  0.0000372  -9.578
## temp                                        0.0014007  0.0015005   0.933
##                                            Pr(>|t|)
## (Intercept)                                 < 2e-16 ***
## regionfao27                                0.018000 *
## regionfao31                                0.962561
## regionfao34                                0.023657 *
## regionfao37                                0.683740
## regionfao41                                0.280898
## regionfao47                                0.190517
## regionfao48                                0.448908
## regionfao51                                1.40e-06 ***
## regionfao57                                0.000372 ***
## regionfao58                                0.223620
## regionfao61                                 < 2e-16 ***
## regionfao67                                0.068606 .
## regionfao71                                1.26e-10 ***
## regionfao77                                3.17e-05 ***
## regionfao81                                0.012619 *
## regionfao87                                5.87e-07 ***
## spgroupnameFlounders, halibuts, soles      2.22e-09 ***
## spgroupnameHerrings, sardines, anchovies   0.797047
## spgroupnameMiscellaneous coastal fishes    3.66e-06 ***
## spgroupnameMiscellaneous demersal fishes   0.000176 ***
## spgroupnameMiscellaneous diadromous fishes 8.86e-09 ***
## spgroupnameMiscellaneous pelagic fishes    2.48e-10 ***
## spgroupnameSalmons, trouts, smelts         1.96e-08 ***
## spgroupnameSharks, rays, chimaeras         5.72e-13 ***
## spgroupnameSturgeons, paddlefishes         0.018467 *
## spgroupnameTunas, bonitos, billfishes       < 2e-16 ***
## vbk                                        0.012723 *
## maxl                                        < 2e-16 ***
## temp                                       0.350703
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 0.1728 on 1649 degrees of freedom
## Multiple R-squared:   0.28,  Adjusted R-squared:  0.2674
## F-statistic: 22.12 on 29 and 1649 DF,  p-value: < 2.2e-16

Now we’ve got a model! we’re close to being able to use data to predict where we’ll start our fishing operation. But, while we know nothing about fishing, we are good statisticians, and we know we should look at our regression before using it to make a big life decision. This is where broom comes in. R has all kinds of great functions, like summary() to look at regressions. But, they can be a little ad hoc, and difficult to manipulate. broom helps us tidy up our regression data. First, suppose that we want a better way to look at summary statistics from the regression. The glance() function from the broom package extracts important summary statistics from the model, like the R2, the AIC, and the BIC.

library(broom)
reg_summary <- glance(fish_model)

reg_summary
##   r.squared adj.r.squared     sigma statistic      p.value df   logLik
## 1 0.2800327     0.2673711 0.1728461  22.11661 9.261001e-97 30 579.9767
##         AIC       BIC deviance df.residual
## 1 -1097.953 -929.7488 49.26515        1649

Unfortunately, our model is pretty poor; it only explains ~20% of the variation in the fishiness variable, but hopefully it’s better than guessing. Let’s dig into this model a bit more. We’re going to use the tidy() function from the broom package to provide neat summaries of the model coefficients.

tidy_model <- tidy(fish_model)

tidy_model$variable<- as.factor(tidy_model$term) #convert terms to factors

tidy_model$variable <- reorder(tidy_model$variable, tidy_model$p.value) #sort variables by pvalue

tidy_model$short_pval<- pmin(tidy_model$p.value,0.2) #create abbreviated version

regression_plot <- (
  ggplot(data=tidy_model,aes(x=variable,y=estimate,fill=short_pval)) +
    geom_bar(position='dodge',stat='identity',color='black') +
    scale_fill_gradient2(
      high='black',mid='gray99', low='red', midpoint=0.1,
      breaks=c(0.05,0.1,0.15,0.2), labels=c('0.05','0.10','0.15','>0.20'),
      name='P-Value', guide=guide_colorbar(reverse=T))
  +theme(axis.text.x=element_text(angle=45,hjust=0.9,vjust=0.9)) +
    geom_errorbar(mapping=aes(ymin=estimate-1.96*std.error,ymax=estimate+1.96*std.error)) +
    xlab('Variable') +
    ylab(paste('Marginal Effect on ',names(fish_model$model)[1],sep='')) +
    coord_flip())

regression_plot

So, we can now see that most of the significant terms are region specific, and the life history data doesn’t give us a whole lot of information on where we should start fishing. So far, the model is saying go fish in China, and maybe avoid salmons, halibuts, and tunas.

Before we charge off and use these results though to decide where we’re starting our new life, we’re now going to use the augment() function in the broom package to help us run some diagnostics on the regression. The augment function takes our original data passed to the regression, and adds all kinds of things, like the values predicted by the model and the residuals. This makes it very useful for regression diagnostics. First off, we might want to check whether our errors are actually normally distributed

auged_reg <- augment(fish_model)

obs_v_pred <- auged_reg %>%
  ggplot(aes(fishiness, .fitted)) +
  geom_point(shape = 21, size = 4, alpha = 0.6, fill = 'steelblue4') +
  geom_abline(aes(slope=1, intercept = 0)) +
  xlab('ovbserved') +
  ylab('predicted') +
  geom_label(aes(0.25,0.7), label = paste('R2 = ', round(reg_summary$r.squared,2), sep = ''))
obs_v_pred

qq_plot <- auged_reg %>% #create quantile-quantile plot
  ggplot(aes(sample = .resid)) +
  stat_qq(shape = 21, size = 4, alpha = 0.6, fill = 'steelblue4') +
  xlab('Theoretical') +
  ylab('Sample')
qq_plot

We see that our data are in fact normally distributed, that’s good! Let’s check for heteroskedasticity and model misspecification.

hetsk_plot <- auged_reg %>% #plot fitted vs residuals
  ggplot(aes(.fitted, .resid)) +
  geom_point(shape = 21, size = 4, alpha = 0.6, fill = 'steelblue4') +
  geom_hline(aes(yintercept = 0)) +
  xlab('Predicted') +
  ylab('Residuals')
hetsk_plot

Looks a little iffy, we’ve got some heteroskedasticity going on. Let’s try and see where it is. The great thing about broom is that it makes it really easy to manipulate data and plot diagnostics based on the original data.

hetsk_plot2 <- auged_reg %>%
  ggplot(aes(.fitted, .resid, fill = spgroupname)) +
  geom_point(shape = 21, size = 4, alpha = 0.6) +
  geom_hline(aes(yintercept = 0)) +
  xlab('Predicted') +
  ylab('Residuals')
hetsk_plot2

So, we see here that the culprit are the herrings and salmons. That tells us to be a little cautious in our predictive ability and estimated errors based on this model, and maybe we need to do a better job of clustering our errors. Let’s look at things another way. We saw from the coefficient plot that the region effects are the most significant in the model. How confident are we in those?

regional_bias <- auged_reg %>% #Check residuals by group
  ggplot(aes(regionfao,.resid)) +
  geom_boxplot(fill = 'steelblue4') +
  geom_hline(aes(yintercept = 0)) +
  xlab('FAO Region') +
  ylab('Residuals')
regional_bias

species_bias <- auged_reg %>%
  ggplot(aes(spgroupname,.resid)) +
  geom_boxplot(fill = 'steelblue4') +
  geom_hline(aes(yintercept = 0)) +
  xlab('Species Category') +
  ylab('Residuals') +
  coord_flip()
species_bias

All in all then, we’ve got some heteroskedasticity that makes us a little suspicious of our standard errors, but no major biases in our estimation. Our life choice model works! Let’s move to China and fish whatever, the model says it doesn’t matter.

In defense of plyr

One quick note. dplyr has taken over for a lot of the things we used to use plyr for. But, plyr is still useful for manipulating other types of objects instead of data frames. Specifically, I use plyr to convert lists and arrays to data frames.

Sometimes its useful to use lists. Suppose that I have a function that I want to evaluate a bunch of times. Loops can be cumbersome for a variety of reasons. Let’s write a function and apply it over a vector instead.

foo <- function(x){ #random function
  y <- x^2
  return(y)
}

food <- lapply(1:100,foo) #this can be more efficient and simpler than loops

Now, we’ve applied our function over 100 values. But, they’re stuck in list form. plyr to the rescue! So long as each element in every list has the same dimensions, ldply will “smash” the list into a data frame

plyr::ldply(food) %>% head
##   V1
## 1  1
## 2  4
## 3  9
## 4 16
## 5 25
## 6 36
# OR without plyr
food %>% lapply(as.data.frame) %>% rbind_all() %>% head
## Source: local data frame [6 x 1]
##
##   X[[i]]
##    (dbl)
## 1      1
## 2      4
## 3      9
## 4     16
## 5     25
## 6     36

The syntax is simple. ldply converts lists to data frames. adply converts arrays to data frames. You get the idea. Huge warning here. Make sure you load the plyr library before dplyr. Otherwise, bad bad things can happen. R will even throw a warning if you do it the other way around. Or, more simply, instead of loading the library, just use plyr::ldply. This loads that function for that instance, without actually loading into the environment and masking other things.

A quick warning on speed

So far, we’ve been preaching the dplyr gospel pretty hard. All in all, it makes code faster, more efficient, and much easier to read. But, there are times when its best to keep it simple, especially where speed is critical. This is less dplyr’s fault, than some issues with data frames themselves.

We are going to compare two functions that do the same thing, one using dplyr and data frames and one that uses more basic R functions. The goal is a function that calculates the mean length of catch history in an fao region

dplyr_fun <- function(region,dat){
  dat %>%
    filter(regionfao == region) %>%
    summarise(mean_length = mean(length_catch))
}

basic_fun <- function(region,dat){
  mean(as.numeric(dat[dat[,'regionfao'] == region,'length_catch']))
}

regions <- rep(unique(as.character(regdat$regionfao)), 100) #thing to test

system.time({ #time the dplyr version
  a <- lapply(regions, dplyr_fun, dat = regdat)
})
##    user  system elapsed
##   5.278   0.038   5.339
system.time({ #time the basic version
  b <- lapply(regions, basic_fun, dat = as.matrix(regdat))
})
##    user  system elapsed
##   0.759   0.125   0.886
all(plyr::ldply(a)$V1 == plyr::ldply(b)$V1) #check and make sure they do the same thing
## [1] TRUE

The dplyr version of the function takes nearly 7 times as long as the same function in basic notation! The difference between .45 and 3.1 seconds doesn’t matter much in most cases, but if you’re doing huge numbers of simulations, say in an MCMC, this starts to add up. This can be the difference between a model running a day and a few hours.

This time sink doesn’t always hold true, dplyr will often be faster than bunches of nested loops, but when speed is a priority, it’s worth checking to see using matrices instead of data frames and dplyr will save you some serious time.

Advanced Dplyr Applications

Underscore Functions

Often, when writing functions with dplyr we may want to be able to specify different grouping variables. But wait, dplyr arguments use unquoted variable names! Have no fear, underscore is here!

Check out the following two functions:

# function using standard dplyr functions
fun1<-function(x,gpvar1,gpvar2,gpvar3){
  y<-x %>%
    group_by(gpvar1) %>%
    mutate(
      globalcatch = sum(totalcatch,na.rm=T),
      globalrank  = dense_rank(totalcatch)) %>% # global catch and cntry rank
    group_by(gpvar2) %>% # now we group by a different level before our next calculation
    mutate(
      percglobal = 100*(totalcatch/globalcatch)) %>%
    group_by(gpvar3) %>%
    mutate(
      ingrouprank = dense_rank(totalcatch))
  return(y)
}

fun1(spcatch, gpvar1 = year, gpvar2 = c(year,country), gpvar3 = country) # !!!!! THIS WILL NOT WORK !!!!!

# function using underscores
fun1<-function(x,gpvar1,gpvar2,gpvar3){
  y<-x %>%
    group_by_(gpvar1) %>%
    mutate(
      globalcatch = sum(totalcatch,na.rm=T),
      globalrank  = dense_rank(totalcatch)) %>%
    group_by_(gpvar2) %>%
    mutate(
      percglobal = 100*(totalcatch/globalcatch)) %>%
    group_by_(gpvar3) %>%
    mutate(
      ingrouprank = dense_rank(desc(totalcatch)))
  return(y)
}

# apply function to species category and country datasets
spcatch<-fun1(spcatch,gpvar1 = c('year'), gpvar2 = c('year','spgroupname'), gpvar3 = c('spgroupname'))
cntry<-fun1(cntry,gpvar1 = c('year'), gpvar2 = c('year','country'), gpvar3 = c('country'))   

Using Dplyr to Query External Databases

Need to setup Google account first, per A new data processing workflow for R: dplyr, magrittr, tidyr, ggplot2 | Technical Tidbits From Spatial Analysis & Data Science.

# library(dplyr)
library(bigrquery) # install.packages('bigrquery')
sql<-"select * from [publicdata:samples.shakespeare]"
shakespeare <-query_exec(sql, project ="test-bigquery-1243",max_pages=Inf)