All the material presented here, to the extent it is original, is available under CC-BY-SA.
I am running R 3.6.1, with recent update.packages()
.
needed <- c("rgdal", "spdep", "sf", "spData", "sp", "WDI", "wbstats", "eurostat",
"SmarterPoland", "htmltools", "httr", "ggplot2", "rbenchmark",
"readstata13", "foreign", "DBI", "RSQLite", "feather", "data.table", "readr")
Script and data at https://github.com/rsbivand/ban421_h19/raw/master/ban421_h19_wed.zip. Download to suitable location, unzip and use as basis.
We’ll examine output first, to give something to import without needing external files
We’ll use this blog post to prime the files, but with a broader selection of interfaces
The blog uses a number of contributed packages, but there are too many rows to try Excel
There is a lot of room for experimentation here
if (!file.exists("outdata")) dir.create("outdata")
set.seed(123)
df <- data.frame(replicate(10, sample(0:2000, 15 * 10^5, rep = TRUE)),
replicate(10, stringi::stri_rand_strings(1000, 5)))
dim(df)
## [1] 1500000 20
system.time(write.table(df, file="outdata/df.txt", row.names = FALSE))
## user system elapsed
## 8.856 0.129 9.077
system.time(write.csv2(df, file = "outdata/df2.csv", row.names = FALSE))
## user system elapsed
## 8.867 0.118 9.073
library(readr)
system.time(write_csv(df, path = "outdata/df.csv"))
## user system elapsed
## 4.047 0.107 4.203
library(data.table)
system.time(fwrite(df, file = "outdata/df_dt.csv", row.names=FALSE))
## user system elapsed
## 1.451 0.068 0.766
file.info(paste("outdata", list.files("outdata"), sep="/"))[,1, drop=FALSE]
## size
## outdata/df_dt.csv 156678659
## outdata/df.csv 156678659
## outdata/df.txt 186678699
## outdata/df2.csv 186678699
system.time(save(df, file="outdata/df_gz6.rda", compress="gzip", compression_level=6))
## user system elapsed
## 7.804 0.030 7.904
system.time(save(df, file="outdata/df_gz0.rda", compress="gzip", compression_level=0))
## user system elapsed
## 0.274 0.038 0.315
system.time(saveRDS(df, file="outdata/df.rds"))
## user system elapsed
## 7.863 0.044 7.993
library(feather)
system.time(write_feather(df, "outdata/df.feather"))
## user system elapsed
## 0.136 0.048 0.187
file.info(paste("outdata", list.files("outdata"), sep="/"))[,1, drop=FALSE]
## size
## outdata/df_dt.csv 156678659
## outdata/df_gz0.rda 120150055
## outdata/df_gz6.rda 29936378
## outdata/df.csv 156678659
## outdata/df.feather 120092160
## outdata/df.rds 29936369
## outdata/df.txt 186678699
## outdata/df2.csv 186678699
library(RSQLite)
library(DBI)
con <- dbConnect(RSQLite::SQLite(), "outdata/df.sqlite")
system.time(dbWriteTable(con, "df", df, overwrite=TRUE))
## user system elapsed
## 2.996 0.099 3.144
dbDisconnect(con)
library(foreign)
system.time(write.dta(df, file="outdata/df.dta"))
## user system elapsed
## 0.979 0.052 1.033
library(readstata13)
system.time(save.dta13(df, file="outdata/df_s13.dta"))
## user system elapsed
## 3.272 0.112 3.390
file.info(paste("outdata", list.files("outdata"), sep="/"))[,1, drop=FALSE]
## size
## outdata/df_dt.csv 156678659
## outdata/df_gz0.rda 120150055
## outdata/df_gz6.rda 29936378
## outdata/df_s13.dta 120145152
## outdata/df.csv 156678659
## outdata/df.dta 120143836
## outdata/df.feather 120092160
## outdata/df.rds 29936369
## outdata/df.sqlite 146665472
## outdata/df.txt 186678699
## outdata/df2.csv 186678699
Many of the alternatives are the same for input for obvious reasons
For text and csv files, readr and data.table complement functions in the base package utils
Many of the binary variants read uncompressed files, so importing from compressed should take longer
importing from databases should take longer, but may permit subsetting prior to import
system.time(df_in <- read.table("outdata/df.txt", header=TRUE))
## user system elapsed
## 6.230 0.178 6.418
class(df_in)
## [1] "data.frame"
head(df_in[,c(1, 11)])
## X1 X1.1
## 1 414 mJ55t
## 2 462 9V9dp
## 3 178 e12rf
## 4 525 VRfYu
## 5 194 PZjfT
## 6 937 lhWUD
system.time(df_in <- read.table("outdata/df.txt", header=TRUE, stringsAsFactors=FALSE))
## user system elapsed
## 5.520 0.082 5.613
class(df_in)
## [1] "data.frame"
head(df_in[,c(1,11)])
## X1 X1.1
## 1 414 mJ55t
## 2 462 9V9dp
## 3 178 e12rf
## 4 525 VRfYu
## 5 194 PZjfT
## 6 937 lhWUD
system.time(df_in <- read.csv2("outdata/df2.csv"))
## user system elapsed
## 5.841 0.066 5.917
class(df_in)
## [1] "data.frame"
head(df_in[,c(1,11)])
## X1 X1.1
## 1 414 mJ55t
## 2 462 9V9dp
## 3 178 e12rf
## 4 525 VRfYu
## 5 194 PZjfT
## 6 937 lhWUD
system.time(df_in <- read.csv2("outdata/df2.csv", stringsAsFactors=FALSE))
## user system elapsed
## 6.235 0.045 6.293
class(df_in)
## [1] "data.frame"
head(df_in[,c(1,11)])
## X1 X1.1
## 1 414 mJ55t
## 2 462 9V9dp
## 3 178 e12rf
## 4 525 VRfYu
## 5 194 PZjfT
## 6 937 lhWUD
library(readr)
system.time(suppressMessages(df_in <- read_csv2("outdata/df2.csv", progress = FALSE)))
## user system elapsed
## 2.483 0.020 2.580
class(df_in)
## [1] "spec_tbl_df" "tbl_df" "tbl" "data.frame"
head(df_in[,c(1,11)])
## # A tibble: 6 x 2
## X1 X1.1
## <dbl> <chr>
## 1 414 mJ55t
## 2 462 9V9dp
## 3 178 e12rf
## 4 525 VRfYu
## 5 194 PZjfT
## 6 937 lhWUD
library(data.table)
system.time(df_in <- fread("outdata/df_dt.csv", showProgress = FALSE))
## user system elapsed
## 1.226 0.015 0.678
class(df_in)
## [1] "data.table" "data.frame"
head(df_in[,c(1,11)])
## X1 X1.1
## 1: 414 mJ55t
## 2: 462 9V9dp
## 3: 178 e12rf
## 4: 525 VRfYu
## 5: 194 PZjfT
## 6: 937 lhWUD
library(rbenchmark);
res <- benchmark("CSV_factor"=read.csv2("outdata/df2.csv"),
"CSV"=read.csv2("outdata/df2.csv", stringsAsFactors=FALSE),
"readr_CSV"=suppressMessages(read_csv2("outdata/df2.csv", progress = FALSE)),
"fread_CSV"=fread("outdata/df_dt.csv", showProgress = FALSE),
replications=10, order="elapsed")
res[,1:4]
## test replications elapsed relative
## 4 fread_CSV 10 7.565 1.000
## 3 readr_CSV 10 26.637 3.521
## 2 CSV 10 59.065 7.808
## 1 CSV_factor 10 63.247 8.360
system.time({load("outdata/df_gz6.rda"); df_in <- df})
## user system elapsed
## 0.482 0.004 0.487
class(df_in)
## [1] "data.frame"
head(df_in[,c(1,11)])
## X1 X1.1
## 1 414 mJ55t
## 2 462 9V9dp
## 3 178 e12rf
## 4 525 VRfYu
## 5 194 PZjfT
## 6 937 lhWUD
system.time({load("outdata/df_gz0.rda"); df_in <- df})
## user system elapsed
## 0.242 0.021 0.263
class(df_in)
## [1] "data.frame"
head(df_in[,c(1,11)])
## X1 X1.1
## 1 414 mJ55t
## 2 462 9V9dp
## 3 178 e12rf
## 4 525 VRfYu
## 5 194 PZjfT
## 6 937 lhWUD
system.time(df_in <- readRDS("outdata/df.rds"))
## user system elapsed
## 0.496 0.017 0.514
class(df_in)
## [1] "data.frame"
head(df_in[,c(1,11)])
## X1 X1.1
## 1 414 mJ55t
## 2 462 9V9dp
## 3 178 e12rf
## 4 525 VRfYu
## 5 194 PZjfT
## 6 937 lhWUD
library(feather)
system.time(df_in <- read_feather("outdata/df.feather"))
## user system elapsed
## 0.032 0.025 0.058
class(df_in)
## [1] "tbl_df" "tbl" "data.frame"
head(df_in[,c(1,11)])
## # A tibble: 6 x 2
## X1 X1.1
## <int> <fct>
## 1 414 mJ55t
## 2 462 9V9dp
## 3 178 e12rf
## 4 525 VRfYu
## 5 194 PZjfT
## 6 937 lhWUD
library(foreign)
system.time(df_in <- read.dta("outdata/df.dta"))
## user system elapsed
## 3.594 0.170 3.777
class(df_in)
## [1] "data.frame"
head(df_in[,c(1,11)])
## X1 X1_1
## 1 414 mJ55t
## 2 462 9V9dp
## 3 178 e12rf
## 4 525 VRfYu
## 5 194 PZjfT
## 6 937 lhWUD
library(readstata13)
system.time(df_in <- read.dta13("outdata/df_s13.dta"))
## user system elapsed
## 3.787 0.030 3.823
class(df_in)
## [1] "data.frame"
head(df_in[,c(1,11)])
## X1 X1.1
## 1 414 mJ55t
## 2 462 9V9dp
## 3 178 e12rf
## 4 525 VRfYu
## 5 194 PZjfT
## 6 937 lhWUD
library(RSQLite)
library(DBI)
con <- dbConnect(RSQLite::SQLite(), "outdata/df.sqlite")
system.time(df_in <- dbReadTable(con, "df"))
## user system elapsed
## 6.149 0.037 6.205
dbDisconnect(con)
class(df_in)
## [1] "data.frame"
head(df_in[,c(1,11)])
## X1 X1.1
## 1 414 mJ55t
## 2 462 9V9dp
## 3 178 e12rf
## 4 525 VRfYu
## 5 194 PZjfT
## 6 937 lhWUD
res <- benchmark("SQLite"={con <- dbConnect(RSQLite::SQLite(), "outdata/df.sqlite");
system.time(df_in <- dbReadTable(con, "df")); dbDisconnect(con)},
"Stata"=read.dta("outdata/df.dta"),
"Stata13"=read.dta("outdata/df.dta"),
"feather"=read_feather("outdata/df.feather"),
"RDS"=readRDS("outdata/df.rds"),
"RDA0"=load("outdata/df_gz0.rda"),
"RDA6"=load("outdata/df_gz6.rda"),
replications=10, order="elapsed")
res[,1:4]
## test replications elapsed relative
## 4 feather 10 0.458 1.000
## 6 RDA0 10 2.754 6.013
## 5 RDS 10 4.917 10.736
## 7 RDA6 10 4.996 10.908
## 3 Stata13 10 32.368 70.672
## 2 Stata 10 32.966 71.978
## 1 SQLite 10 81.519 177.989
So far we’ve accessed public data from files downloaded from data providers
Many data providers now also offer application programming interfaces (APIs)
R contributed packages are providing access to these data catalogues and data repositories
Some require that users acquire an API key first, so that they can record activity
The interfaces are not simple, because we have to ask for data using codes:
suppressMessages(library(SmarterPoland))
tmp <- grepEurostatTOC("regional")
str(tmp)
## 'data.frame': 24 obs. of 8 variables:
## $ title : Factor w/ 8777 levels " Broadband and connectivity - households",..: 5018 3031 5183 4800 4799 3349 3350 3032 3033 2464 ...
## $ code : Factor w/ 7976 levels "aact","aact_ali",..: 710 4830 4825 1247 1248 4304 4305 4573 7857 4825 ...
## $ type : Factor w/ 4 levels "comext","dataset",..: 2 2 2 2 2 2 2 2 2 2 ...
## $ last.update.of.data : Factor w/ 482 levels " ","01.02.2018",..: 265 80 80 65 183 113 131 274 274 80 ...
## $ last.table.structure.change: Factor w/ 348 levels " ","01.02.2018",..: 95 8 285 47 106 89 89 197 197 285 ...
## $ data.start : Factor w/ 165 levels " ","1850","1925",..: 103 103 87 145 144 98 98 103 103 87 ...
## $ data.end : Factor w/ 81 levels " ","1984","1991",..: 58 55 55 55 55 58 58 55 55 55 ...
## $ values : logi NA NA NA NA NA NA ...
demo_r_gind3 <- getEurostatRCV(kod="demo_r_gind3")
levels(demo_r_gind3$indic_de)
## [1] "CNMIGRAT" "CNMIGRATRT" "DEATH" "GBIRTHRT" "GDEATHRT"
## [6] "GROW" "GROWRT" "JAN" "LBIRTH" "NATGROW"
## [11] "NATGROWRT"
The eurostat package extends the handling of Eurostat data found in SmarterPoland:
suppressMessages(library(eurostat))
toc <- get_eurostat_toc()
str(toc)
## Classes 'spec_tbl_df', 'tbl_df', 'tbl' and 'data.frame': 9819 obs. of 8 variables:
## $ title : chr "Database by themes" "General and regional statistics" "European and national indicators for short-term analysis" "Business and consumer surveys (source: DG ECFIN)" ...
## $ code : chr "data" "general" "euroind" "ei_bcs" ...
## $ type : chr "folder" "folder" "folder" "folder" ...
## $ last update of data : chr NA NA NA NA ...
## $ last table structure change: chr NA NA NA NA ...
## $ data start : chr NA NA NA NA ...
## $ data end : chr NA NA NA NA ...
## $ values : chr NA NA NA NA ...
## - attr(*, "spec")=
## .. cols(
## .. .default = col_character(),
## .. title = col_character(),
## .. code = col_character(),
## .. type = col_character(),
## .. `last update of data` = col_character(),
## .. `last table structure change` = col_character(),
## .. `data start` = col_character(),
## .. `data end` = col_character(),
## .. values = col_character()
## .. )
The examples site has a spatial example:
df <- get_eurostat("tgs00026", time_format = "raw")
## Table tgs00026 cached at /tmp/RtmpING71M/eurostat/tgs00026_raw_code_TF.rds
df$time <- eurotime2num(df$time)
suppressMessages(library("wbstats"))
pop_gdp_data <- wb(country = c("PL"), indicator = c("SP.POP.TOTL", "NY.GDP.MKTP.CD"),
startdate = 1990, enddate = 2016)
head(pop_gdp_data)
## iso3c date value indicatorID indicator iso2c country
## 1 POL 2016 37970087 SP.POP.TOTL Population, total PL Poland
## 2 POL 2015 37986412 SP.POP.TOTL Population, total PL Poland
## 3 POL 2014 38011735 SP.POP.TOTL Population, total PL Poland
## 4 POL 2013 38040196 SP.POP.TOTL Population, total PL Poland
## 5 POL 2012 38063164 SP.POP.TOTL Population, total PL Poland
## 6 POL 2011 38063255 SP.POP.TOTL Population, total PL Poland
The WDI package also accesses World Bank WDI data:
suppressMessages(library("WDI"))
res <- WDIsearch('gdp')
str(res)
## chr [1:493, 1:2] "BX.TRF.PWKR.GD.ZS" "BX.TRF.PWKR.DT.GD.ZS" ...
## - attr(*, "dimnames")=List of 2
## ..$ : NULL
## ..$ : chr [1:2] "indicator" "name"
The HPC Task View is a good place to start, with the parallel package
I have a working paper from 2010 pointing to issues in choosing where to parallelize (bottom up or top down)
Exchanging the reference BLAS for a threaded BLAS is possible
suppressMessages(library(spdep))
suppressMessages(require(rgdal, quietly=TRUE))
wheat <- readOGR(system.file("shapes/wheat.shp", package="spData"), verbose=FALSE)
nbr1 <- poly2nb(wheat, queen=FALSE)
nbrl <- nblag(nbr1, 2)
nbr12 <- nblag_cumul(nbrl)
cms0 <- with(as(wheat, "data.frame"), tapply(yield, c, median))
cms1 <- c(model.matrix(~ factor(c) -1, data=wheat) %*% cms0)
wheat$yield_detrend <- wheat$yield - cms1
RNGkind("L'Ecuyer-CMRG")
set.seed(1L)
system.time(boot_out_ser <- aple.mc(as.vector(scale(wheat$yield_detrend, scale=FALSE)),
nb2listw(nbr12, style="W"), nsim=10000))
## Registered S3 methods overwritten by 'spatialreg':
## method from
## residuals.stsls spdep
## deviance.stsls spdep
## coef.stsls spdep
## print.stsls spdep
## summary.stsls spdep
## print.summary.stsls spdep
## residuals.gmsar spdep
## deviance.gmsar spdep
## coef.gmsar spdep
## fitted.gmsar spdep
## print.gmsar spdep
## summary.gmsar spdep
## print.summary.gmsar spdep
## print.lagmess spdep
## summary.lagmess spdep
## print.summary.lagmess spdep
## residuals.lagmess spdep
## deviance.lagmess spdep
## coef.lagmess spdep
## fitted.lagmess spdep
## logLik.lagmess spdep
## fitted.SFResult spdep
## print.SFResult spdep
## fitted.ME_res spdep
## print.ME_res spdep
## print.lagImpact spdep
## plot.lagImpact spdep
## summary.lagImpact spdep
## HPDinterval.lagImpact spdep
## print.summary.lagImpact spdep
## print.sarlm spdep
## summary.sarlm spdep
## residuals.sarlm spdep
## deviance.sarlm spdep
## coef.sarlm spdep
## vcov.sarlm spdep
## fitted.sarlm spdep
## logLik.sarlm spdep
## anova.sarlm spdep
## predict.sarlm spdep
## print.summary.sarlm spdep
## print.sarlm.pred spdep
## as.data.frame.sarlm.pred spdep
## residuals.spautolm spdep
## deviance.spautolm spdep
## coef.spautolm spdep
## fitted.spautolm spdep
## print.spautolm spdep
## summary.spautolm spdep
## logLik.spautolm spdep
## print.summary.spautolm spdep
## print.WXImpact spdep
## summary.WXImpact spdep
## print.summary.WXImpact spdep
## predict.SLX spdep
## user system elapsed
## 7.447 0.031 7.542
suppressMessages(library(spdep))
library(parallel)
nc <- detectCores(logical=FALSE)
nc
## [1] 2
invisible(set.coresOption(nc))
set.seed(1L)
system.time({if (!get.mcOption()) {
cl <- makeCluster(nc, "PSOCK")
set.ClusterOption(cl)
} else{
mc.reset.stream()
}
boot_out_par <- aple.mc(as.vector(scale(wheat$yield_detrend, scale=FALSE)),
nb2listw(nbr12, style="W"), nsim=10000)
if (!get.mcOption()) {
set.ClusterOption(NULL)
stopCluster(cl)
}})
## Registered S3 methods overwritten by 'spatialreg':
## method from
## residuals.stsls spdep
## deviance.stsls spdep
## coef.stsls spdep
## print.stsls spdep
## summary.stsls spdep
## print.summary.stsls spdep
## residuals.gmsar spdep
## deviance.gmsar spdep
## coef.gmsar spdep
## fitted.gmsar spdep
## print.gmsar spdep
## summary.gmsar spdep
## print.summary.gmsar spdep
## print.lagmess spdep
## summary.lagmess spdep
## print.summary.lagmess spdep
## residuals.lagmess spdep
## deviance.lagmess spdep
## coef.lagmess spdep
## fitted.lagmess spdep
## logLik.lagmess spdep
## fitted.SFResult spdep
## print.SFResult spdep
## fitted.ME_res spdep
## print.ME_res spdep
## print.lagImpact spdep
## plot.lagImpact spdep
## summary.lagImpact spdep
## HPDinterval.lagImpact spdep
## print.summary.lagImpact spdep
## print.sarlm spdep
## summary.sarlm spdep
## residuals.sarlm spdep
## deviance.sarlm spdep
## coef.sarlm spdep
## vcov.sarlm spdep
## fitted.sarlm spdep
## logLik.sarlm spdep
## anova.sarlm spdep
## predict.sarlm spdep
## print.summary.sarlm spdep
## print.sarlm.pred spdep
## as.data.frame.sarlm.pred spdep
## residuals.spautolm spdep
## deviance.spautolm spdep
## coef.spautolm spdep
## fitted.spautolm spdep
## print.spautolm spdep
## summary.spautolm spdep
## logLik.spautolm spdep
## print.summary.spautolm spdep
## print.WXImpact spdep
## summary.WXImpact spdep
## print.summary.WXImpact spdep
## predict.SLX spdep
## user system elapsed
## 4.429 0.126 5.276
system.time({if (!get.mcOption()) {
cl <- makeCluster(nc, "FORK")
set.ClusterOption(cl)
} else{
mc.reset.stream()
}
boot_out_par <- aple.mc(as.vector(scale(wheat$yield_detrend, scale=FALSE)),
nb2listw(nbr12, style="W"), nsim=10000)
if (!get.mcOption()) {
set.ClusterOption(NULL)
stopCluster(cl)
}})
## user system elapsed
## 4.500 0.149 5.557
sessionInfo()
sessionInfo()
## R version 3.6.1 (2019-07-05)
## Platform: x86_64-pc-linux-gnu (64-bit)
## Running under: Fedora 30 (Workstation Edition)
##
## Matrix products: default
## BLAS: /home/rsb/topics/R/R361-share/lib64/R/lib/libRblas.so
## LAPACK: /home/rsb/topics/R/R361-share/lib64/R/lib/libRlapack.so
##
## Random number generation:
## RNG: L'Ecuyer-CMRG
## Normal: Inversion
## Sample: Rejection
##
## locale:
## [1] LC_CTYPE=en_GB.UTF-8 LC_NUMERIC=C
## [3] LC_TIME=en_GB.UTF-8 LC_COLLATE=en_GB.UTF-8
## [5] LC_MONETARY=en_GB.UTF-8 LC_MESSAGES=en_GB.UTF-8
## [7] LC_PAPER=en_GB.UTF-8 LC_NAME=C
## [9] LC_ADDRESS=C LC_TELEPHONE=C
## [11] LC_MEASUREMENT=en_GB.UTF-8 LC_IDENTIFICATION=C
##
## attached base packages:
## [1] parallel stats graphics grDevices utils datasets methods
## [8] base
##
## other attached packages:
## [1] spdep_1.1-3 sf_0.8-1 spData_0.3.2
## [4] sp_1.3-1 WDI_2.6.0 wbstats_0.2
## [7] eurostat_3.3.5 SmarterPoland_1.7 htmltools_0.3.6
## [10] httr_1.4.1 ggplot2_3.2.1
##
## loaded via a namespace (and not attached):
## [1] Rcpp_1.0.2 lubridate_1.7.4 lattice_0.20-38
## [4] tidyr_1.0.0 deldir_0.1-23 gtools_3.8.1
## [7] class_7.3-15 assertthat_0.2.1 zeallot_0.1.0
## [10] digest_0.6.21 spDataLarge_0.3.1 R6_2.4.0
## [13] plyr_1.8.4 backports_1.1.4 coda_0.19-3
## [16] evaluate_0.14 e1071_1.7-2 pillar_1.4.2
## [19] rlang_0.4.0 lazyeval_0.2.2 curl_4.2
## [22] gdata_2.18.0 gmodels_2.18.1 Matrix_1.2-17
## [25] rmarkdown_1.15 splines_3.6.1 RefManageR_1.2.12
## [28] readr_1.3.1 stringr_1.4.0 munsell_0.5.0
## [31] broom_0.5.2 compiler_3.6.1 xfun_0.9
## [34] pkgconfig_2.0.3 tidyselect_0.2.5 expm_0.999-4
## [37] tibble_2.1.3 crayon_1.3.4 dplyr_0.8.3
## [40] withr_2.1.2 spatialreg_1.1-3 MASS_7.3-51.4
## [43] grid_3.6.1 nlme_3.1-141 jsonlite_1.6
## [46] gtable_0.3.0 lifecycle_0.1.0 DBI_1.0.0
## [49] magrittr_1.5 units_0.6-4 scales_1.0.0
## [52] bibtex_0.4.2 KernSmooth_2.23-15 stringi_1.4.3
## [55] LearnBayes_2.15.1 xml2_1.2.2 ellipsis_0.3.0
## [58] vctrs_0.2.0 generics_0.0.2 boot_1.3-23
## [61] RColorBrewer_1.1-2 tools_3.6.1 RJSONIO_1.3-1.2
## [64] glue_1.3.1 purrr_0.3.2 hms_0.5.1
## [67] yaml_2.2.0 colorspace_1.4-1 classInt_0.4-1
## [70] knitr_1.25