NOTE: This document is in progress. Feel free to suggest changes on the package’s GitHub page, or by email silas.tittes@gmail.com.
performr
packageperformr
implements a probabilistic Bayesian hierarchical model (using Stan) to predict tolerance/performance curves for a set of input taxa. The manuscript that describes the method is in revision. This page is intended to help those interested in using the model for their own data.
Installing performr
is done using the following command:
#install
devtools::install_github("silastittes/performr", local = FALSE)
#load other libraries used below
library(performr)
library(tidyverse)
library(ggridges)
theme_set(theme_minimal())
As the model is written in Stan, it requires a c++ compiler. For Apple and PC users, you likely need to install one. If the installation command above fails, Mac users can open their terminal and type:
xcode-select --install
This should open some dialogue to install the Xcode developer tools. Follow the prompts to install. Once the install finishes, try the install_github()
command again. At this point, I have not tested the package on PCs, but I would guess a similar step is required (please email me if you have success on a PC!).
Linux users can likely run the command as-is, or by using devtools::install_github("silastittes/performr")
, which would use the pre-compiled version that my Linux machine built (Linux Mint 18.3).
Last installation detail, performr
depends on several packages. These can take some time to install, but usually goes smoothly as long as your R is up to date! If you run into troubles, check the R session info at the bottom of this page. Compare to your own session info for missing packages and older package versions.
For demonstration and model validation, data can be simulated from the hyperpriors. The true parameter values for both hyper parameters and species-level parameters are returned in addition to a simulated data frame. All arguments have defaults, but fiddling with parameter values is encouraged.
I’ll demonstrate a data set with three species, 20 positions sampled along an environmental axis, and three replicates per species at each position along the axis (wouldn’t that be something):
set.seed(223524)
perf_df <- simulate_data(n_spp = 3, n_axis = 20, n_reps = 3)
Here are a few quick ways to look at the output:
head(perf_df$sim_data)
## # A tibble: 6 x 4
## x trait mu species
## <dbl> <dbl> <dbl> <int>
## 1 -4.72 0.0668 0.0389 1
## 2 -4.72 0.0471 0.0389 1
## 3 -4.72 0 0.0389 1
## 4 -4.32 0.0560 0.0983 1
## 5 -4.32 0.102 0.0983 1
## 6 -4.32 0.0726 0.0983 1
str(perf_df)
## List of 2
## $ true_params:List of 12
## ..$ shape1 : num [1:3] 3.84 3.17 2.25
## ..$ shape2 : num [1:3] 2.61 2.97 2.64
## ..$ stretch : num [1:3] 2.55 2.1 1.97
## ..$ x_min : num [1:3] -5.76 -5.39 -4.55
## ..$ x_max : num [1:3] 4.41 2.52 4.38
## ..$ nu : num [1:3] 17.1 33.6 26
## ..$ mu_shape1 : num 2.57
## ..$ mu_shape2 : num 2.91
## ..$ mu_stretch: num 1.75
## ..$ mu_min : num -5.39
## ..$ mu_max : num 4.22
## ..$ mu_nu : num 3.96
## $ sim_data : tibble [180 × 4] (S3: tbl_df/tbl/data.frame)
## ..$ x : num [1:180] -4.72 -4.72 -4.72 -4.32 -4.32 ...
## ..$ trait : num [1:180] 0.0668 0.0471 0 0.056 0.1024 ...
## ..$ mu : num [1:180] 0.0389 0.0389 0.0389 0.0983 0.0983 ...
## ..$ species: int [1:180] 1 1 1 1 1 1 1 1 1 1 ...
perf_df$sim_data %>%
mutate(species = factor(species)) %>%
ggplot(aes(x, trait, colour = species)) +
geom_point() +
geom_line(aes(x, mu))
There are 3 columns of input data required to run the model, where each row represents an individual unit of sampling (name and order the columns as you please):
Integers representing the groups (or “species”) each sample belongs to – even if there is only one group.
An x-axis consisting of measurements from some environmental variable (soil moisture, temperature, etc.).
A measure of performance for each individual studied in that environmental condition (trait). Rows with missing values must be removed before fitting – tidyr::drop_na()
is good for this.
performr::stan_performance()
Now that we have some example data, we can fit the model. Arguments that include “pr” are parameters for the priors (for brevity, I will gloss over prior details here and refer readers to the paper once available), which I’ve set to match the defaults of the simulation (so this is best case scenario for the model getting it right). Notice, I’ve set a seed to make the results reproducible, and I’ve reduced the total number of iterations to 200. The default iterations of 2000 (or more) should be used for analysis, but 200 is good for demonstration and troubleshooting purposes.
perf_out <-
stan_performance(
df = perf_df$sim_data,
response = trait,
treatment = x,
group_ids = species,
shape1_pr_mu = 2,
shape1_pr_sig = 1,
shape2_pr_mu = 2,
shape2_pr_sig = 1,
stretch_pr_mu = 1,
stretch_pr_sig = 1,
nu_pr_shape = 8,
nu_pr_scale = 3,
min_pr_mu = -5,
min_pr_sig = 1,
max_pr_mu = 5,
max_pr_sig = 1,
iter = 200,
seed = 7345,
file_id = "stan_example"
)
Although it won’t appear on the webpage (the code above is not being evaluated) Stan warns us about the max tree depth (it may also warn about divergent transitions if the simulation is modified). Ideally, those messages should not appear. You can modify the arguments it recommends in your call to stan_performance()
as you would if calling Stan directly. Typically, a max_tree_depth between 12 to 14 works well (though slower). The adapt_delta defaults to 0.95, which is sufficient in my experience. Notice the file_id argument, which takes a file prefix for saving the model output to file in your current directory.
We can read in the model from file as such:
perf_stan <-
rstan::read_stan_csv(
csvfiles = c(
"stan_example.samples_1.csv",
"stan_example.samples_2.csv",
"stan_example.samples_3.csv",
"stan_example.samples_4.csv"
)
)
The output is the same as any Stan model.
knitr::kable(rstan::summary(perf_stan)$summary, digits = 3)
mean | se_mean | sd | 2.5% | 25% | 50% | 75% | 97.5% | n_eff | Rhat | |
---|---|---|---|---|---|---|---|---|---|---|
shape1[1] | 3.636 | 0.020 | 0.329 | 3.068 | 3.415 | 3.581 | 3.858 | 4.348 | 282.480 | 1.007 |
shape1[2] | 3.345 | 0.009 | 0.184 | 3.005 | 3.229 | 3.336 | 3.451 | 3.732 | 453.234 | 1.008 |
shape1[3] | 2.432 | 0.006 | 0.096 | 2.267 | 2.368 | 2.420 | 2.492 | 2.643 | 300.961 | 1.015 |
shape2[1] | 3.318 | 0.058 | 0.733 | 2.212 | 2.785 | 3.194 | 3.723 | 5.119 | 161.212 | 1.013 |
shape2[2] | 3.122 | 0.012 | 0.273 | 2.570 | 2.963 | 3.137 | 3.300 | 3.597 | 492.069 | 1.002 |
shape2[3] | 3.329 | 0.046 | 0.600 | 2.404 | 2.891 | 3.290 | 3.744 | 4.508 | 166.263 | 1.041 |
stretch[1] | 2.514 | 0.011 | 0.194 | 2.179 | 2.392 | 2.503 | 2.635 | 2.964 | 303.164 | 1.007 |
stretch[2] | 2.135 | 0.003 | 0.064 | 2.017 | 2.087 | 2.136 | 2.174 | 2.265 | 463.008 | 1.001 |
stretch[3] | 1.825 | 0.008 | 0.104 | 1.629 | 1.751 | 1.820 | 1.900 | 2.016 | 178.662 | 1.031 |
min_max[1,1] | -5.398 | 0.021 | 0.362 | -6.159 | -5.619 | -5.341 | -5.152 | -4.812 | 295.698 | 1.001 |
min_max[1,2] | 5.021 | 0.042 | 0.621 | 3.912 | 4.583 | 4.952 | 5.385 | 6.299 | 218.130 | 1.001 |
min_max[2,1] | -5.533 | 0.009 | 0.174 | -5.902 | -5.634 | -5.524 | -5.412 | -5.236 | 409.407 | 1.008 |
min_max[2,2] | 2.558 | 0.004 | 0.087 | 2.373 | 2.509 | 2.571 | 2.618 | 2.703 | 445.618 | 1.000 |
min_max[3,1] | -4.676 | 0.004 | 0.081 | -4.864 | -4.730 | -4.666 | -4.620 | -4.537 | 444.753 | 1.009 |
min_max[3,2] | 4.831 | 0.046 | 0.568 | 3.848 | 4.398 | 4.796 | 5.221 | 5.997 | 153.640 | 1.043 |
nu[1] | 18.210 | 0.097 | 2.136 | 14.405 | 16.755 | 18.153 | 19.609 | 22.454 | 486.572 | 1.004 |
nu[2] | 38.470 | 0.184 | 3.837 | 30.529 | 35.753 | 38.559 | 41.090 | 45.929 | 436.497 | 1.004 |
nu[3] | 32.539 | 0.128 | 2.942 | 26.829 | 30.617 | 32.609 | 34.288 | 38.747 | 530.208 | 0.997 |
mu_shape1 | 2.882 | 0.028 | 0.514 | 1.906 | 2.537 | 2.888 | 3.212 | 3.900 | 333.334 | 1.013 |
mu_shape2 | 2.890 | 0.050 | 0.578 | 1.794 | 2.525 | 2.902 | 3.309 | 3.950 | 133.850 | 1.021 |
mu_stretch | 1.852 | 0.032 | 0.511 | 0.883 | 1.510 | 1.850 | 2.227 | 2.788 | 251.485 | 1.001 |
mu_min | -5.129 | 0.033 | 0.487 | -6.110 | -5.441 | -5.128 | -4.824 | -4.087 | 217.046 | 0.998 |
mu_max | 4.326 | 0.048 | 0.539 | 3.244 | 3.979 | 4.334 | 4.699 | 5.339 | 124.908 | 1.031 |
mu_nu | 0.295 | 0.002 | 0.053 | 0.206 | 0.257 | 0.293 | 0.328 | 0.406 | 520.257 | 0.993 |
x_min[1] | -5.398 | 0.021 | 0.362 | -6.159 | -5.619 | -5.341 | -5.152 | -4.812 | 295.698 | 1.001 |
x_min[2] | -5.533 | 0.009 | 0.174 | -5.902 | -5.634 | -5.524 | -5.412 | -5.236 | 409.407 | 1.008 |
x_min[3] | -4.676 | 0.004 | 0.081 | -4.864 | -4.730 | -4.666 | -4.620 | -4.537 | 444.753 | 1.009 |
x_max[1] | 5.021 | 0.042 | 0.621 | 3.912 | 4.583 | 4.952 | 5.385 | 6.299 | 218.130 | 1.001 |
x_max[2] | 2.558 | 0.004 | 0.087 | 2.373 | 2.509 | 2.571 | 2.618 | 2.703 | 445.618 | 1.000 |
x_max[3] | 4.831 | 0.046 | 0.568 | 3.848 | 4.398 | 4.796 | 5.221 | 5.997 | 153.640 | 1.043 |
lp__ | -13.662 | 0.321 | 3.795 | -21.247 | -16.072 | -13.385 | -10.956 | -7.699 | 140.101 | 1.039 |
We can access the posterior draws using rstan::extract()
, which produces a list containing draws for each parameter of the model.
draws <- rstan::extract(perf_stan)
ndraws <- length(draws$lp__)
There are a lot of good packages out there for visualizing posteriors. I haven’t learned any of them yet, but here’s a quick approach I’m fond of:
#choose parameter
param <- "x_max"
max_df <- draws[[param]] %>%
as_tibble() %>%
gather(species, value)
## Warning: The `x` argument of `as_tibble.matrix()` must have column names if `.name_repair` is omitted as of tibble 2.0.0.
## Using compatibility `.name_repair`.
## This warning is displayed once every 8 hours.
## Call `lifecycle::last_warnings()` to see where this warning was generated.
max_df %>%
ggplot(aes(value, species, fill = species)) +
geom_density_ridges(colour = "white") +
xlab(param) +
theme(legend.position = "none")
## Picking joint bandwidth of 0.113
Quickly, let’s eyeball how these marginal posteriors for the x_max parameter (where performance falls to zero above the optimum) for each species.
max_df %>%
group_by(species) %>%
summarise(
cred_025 = quantile(value, 0.025),
cred_975 = quantile(value, 0.975)
) %>%
mutate(
truth = perf_df$true_params$x_max
) %>%
mutate(
within_cred = truth > cred_025 & truth < cred_975
)
## `summarise()` ungrouping output (override with `.groups` argument)
## # A tibble: 3 x 5
## species cred_025 cred_975 truth within_cred
## <chr> <dbl> <dbl> <dbl> <lgl>
## 1 V1 3.91 6.30 4.41 TRUE
## 2 V2 2.37 2.70 2.52 TRUE
## 3 V3 3.85 6.00 4.38 TRUE
Cool, looks like the 95% credible interval captures the true value in each case. It would be easy to extend this approach using a function and quickly verify each parameter. Notice the increased uncertainty in posteriors further from the treatments on the x-axis … Love that!
First, let’s generate a tidy data frame with all the parameters, plus some valuable derived parameters, like the optimum, area, and breadth for each species. We will use this data frame for other tasks below as well.
head(
tidy_perf <-
perform_df(
perf_stan,
species_order = c(1, 2, 3)
)
)
## # A tibble: 6 x 12
## # Groups: species [1]
## species x_min draw x_max shape1 shape2 stretch nu maxima breadth area
## <chr> <dbl> <int> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 1 -5.39 1 6.28 3.56 5.16 1.88 14.6 1.42 11.7 21.9
## 2 1 -4.87 2 4.37 3.20 2.39 2.51 18.3 1.66 9.24 23.2
## 3 1 -5.18 3 5.30 3.35 3.32 2.26 16.1 1.60 10.5 23.7
## 4 1 -5.36 4 6.20 3.72 4.76 2.61 23.0 1.74 11.6 30.1
## 5 1 -5.08 5 5.19 3.21 2.87 2.38 17.1 1.74 10.3 24.5
## 6 1 -5.66 6 5.43 3.87 4.13 2.33 17.4 1.58 11.1 25.9
## # … with 1 more variable: special <dbl>
The next step is to generate prediction intervals using the predict_interval()
function. The function generates posterior quantiles for each set of posterior draws specified (x_draws
), and averages over the quantiles. The argument p
can takes a vector of credible levels, which can be modified to consider other and/or additional levels.
#set up sequence from smallest to largest x
x_seq = seq(min(draws$x_min),
max(draws$x_max),
length.out = 100)
#sub-sample draws randomly
poly_draws <- sample(1:ndraws, 100)
head(
creds <-
predict_interval(
x = x_seq,
spp = spp,
par_df = tidy_perf,
x_draws = poly_draws,
p = c(0.95, 0.5))
)
## # A tibble: 6 x 6
## # Groups: species [1]
## species x lower upper mu level
## <chr> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 1 -6.67 0 0.110 0 95
## 2 1 -6.67 0 0.0379 0 50
## 3 1 -6.52 0 0.110 0 95
## 4 1 -6.52 0 0.0379 0 50
## 5 1 -6.38 0 0.110 0 95
## 6 1 -6.38 0 0.0379 0 50
Notice the output of predict_interval()
also produces a “mu” column, which contains the mean preduction of the curve for each input species.
Here is an example of how the data could be plotted. Other approach using plot()
are certainly possible:
ggplot(data = filter(creds, level == 95)) +
geom_ribbon(
aes(x = x,
ymin = upper,
ymax = lower,
fill = species),
alpha = 0.3,
inherit.aes = F) +
geom_ribbon(
data = filter(creds, level == 50),
aes(x = x,
ymin = upper,
ymax = lower,
fill = species),
inherit.aes = F,
alpha = 0.7) +
geom_line(aes(x, mu, group = species), inherit.aes = F, colour = "white", lwd = 1) +
geom_point(
data = perf_df$sim_data,
aes(x,
trait,
alpha = 0.5),
inherit.aes = F,
colour = "grey70") +
theme(legend.position = "none")
The whole concept of posterior prediction and generating data from the model is one of my favorite things about Bayesian statistics. It allows for a lot of creativity in how we check our assumptions. We can generate data from the model using this approach:
Now we can generate pseudo observed data from the posterior draws.
tidy_perf %>%
filter(draw == 1) %>%
posterior_predict(par_df = .) %>%
head()
## # A tibble: 6 x 5
## x trait mu species draw
## <dbl> <dbl> <dbl> <chr> <int>
## 1 -5.58 0 0 1 1
## 2 -5.46 0 0 1 1
## 3 -5.34 0 0.0000387 1 1
## 4 -5.22 0.0161 0.000741 1 1
## 5 -5.10 0 0.00282 1 1
## 6 -4.98 0 0.00674 1 1
By default, the x-axis will be constructed as a sequence of 100 values that start from the minimum posterior draw value of x_min and end at the maximum of x_max. This default can be changed using the x argument. Filtering for posterior draws is not required before using the function – posterior predictive data will be produced for every posterior draw passed to par_df
.
If you have questions, comments, or concerns, please get in touch. I would be excited to discuss!
<button data-toggle=“collapse” data-target=“#sessioninfo” class="btn btn-primary btn-md btn-info> R session info
#writeLines(readLines(file.path(Sys.getenv("HOME"), ".R/Makevars")))
devtools::session_info()
## ─ Session info ───────────────────────────────────────────────────────────────
## setting value
## version R version 4.0.0 (2020-04-24)
## os macOS Catalina 10.15.5
## system x86_64, darwin17.0
## ui X11
## language (EN)
## collate en_US.UTF-8
## ctype en_US.UTF-8
## tz America/Denver
## date 2020-07-01
##
## ─ Packages ───────────────────────────────────────────────────────────────────
## package * version date lib source
## assertthat 0.2.1 2019-03-21 [1] CRAN (R 4.0.0)
## backports 1.1.8 2020-06-17 [1] CRAN (R 4.0.0)
## bindr * 0.1.1 2018-03-13 [1] CRAN (R 4.0.0)
## blob 1.2.1 2020-01-20 [1] CRAN (R 4.0.0)
## broom 0.5.6 2020-04-20 [1] CRAN (R 4.0.0)
## callr 3.4.3 2020-03-28 [1] CRAN (R 4.0.0)
## cellranger 1.1.0 2016-07-27 [1] CRAN (R 4.0.0)
## cli 2.0.2 2020-02-28 [1] CRAN (R 4.0.0)
## codetools 0.2-16 2018-12-24 [1] CRAN (R 4.0.0)
## colorspace 1.4-1 2019-03-18 [1] CRAN (R 4.0.0)
## crayon 1.3.4 2017-09-16 [1] CRAN (R 4.0.0)
## DBI 1.1.0 2019-12-15 [1] CRAN (R 4.0.0)
## dbplyr 1.4.4 2020-05-27 [1] CRAN (R 4.0.0)
## desc 1.2.0 2018-05-01 [1] CRAN (R 4.0.0)
## devtools 2.3.0 2020-04-10 [1] CRAN (R 4.0.0)
## digest 0.6.25 2020-02-23 [1] CRAN (R 4.0.0)
## dplyr * 1.0.0 2020-05-29 [1] CRAN (R 4.0.0)
## ellipsis 0.3.1 2020-05-15 [1] CRAN (R 4.0.0)
## evaluate 0.14 2019-05-28 [1] CRAN (R 4.0.0)
## fansi 0.4.1 2020-01-08 [1] CRAN (R 4.0.0)
## farver 2.0.3 2020-01-16 [1] CRAN (R 4.0.0)
## forcats * 0.5.0 2020-03-01 [1] CRAN (R 4.0.0)
## fs 1.4.1 2020-04-04 [1] CRAN (R 4.0.0)
## generics 0.0.2 2018-11-29 [1] CRAN (R 4.0.0)
## ggplot2 * 3.3.2 2020-06-19 [1] CRAN (R 4.0.0)
## ggridges * 0.5.2 2020-01-12 [1] CRAN (R 4.0.0)
## glue 1.4.1 2020-05-13 [1] CRAN (R 4.0.0)
## gridExtra 2.3 2017-09-09 [1] CRAN (R 4.0.0)
## gtable 0.3.0 2019-03-25 [1] CRAN (R 4.0.0)
## haven 2.3.1 2020-06-01 [1] CRAN (R 4.0.0)
## highr 0.8 2019-03-20 [1] CRAN (R 4.0.0)
## hms 0.5.3 2020-01-08 [1] CRAN (R 4.0.0)
## htmltools 0.4.0 2019-10-04 [1] CRAN (R 4.0.0)
## httr 1.4.1 2019-08-05 [1] CRAN (R 4.0.0)
## inline 0.3.15 2018-05-18 [1] CRAN (R 4.0.0)
## jsonlite 1.6.1 2020-02-02 [1] CRAN (R 4.0.0)
## knitr 1.28 2020-02-06 [1] CRAN (R 4.0.0)
## labeling 0.3 2014-08-23 [1] CRAN (R 4.0.0)
## lattice 0.20-41 2020-04-02 [1] CRAN (R 4.0.0)
## lifecycle 0.2.0 2020-03-06 [1] CRAN (R 4.0.0)
## loo 2.2.0 2019-12-19 [1] CRAN (R 4.0.0)
## lubridate 1.7.9 2020-06-08 [1] CRAN (R 4.0.0)
## magrittr * 1.5 2014-11-22 [1] CRAN (R 4.0.0)
## matrixStats 0.56.0 2020-03-13 [1] CRAN (R 4.0.0)
## memoise 1.1.0 2017-04-21 [1] CRAN (R 4.0.0)
## modelr 0.1.8 2020-05-19 [1] CRAN (R 4.0.0)
## munsell 0.5.0 2018-06-12 [1] CRAN (R 4.0.0)
## nlme 3.1-148 2020-05-24 [1] CRAN (R 4.0.0)
## performr * 0.2 2020-07-01 [1] Github (silastittes/performr@fb5b84d)
## pillar 1.4.4 2020-05-05 [1] CRAN (R 4.0.0)
## pkgbuild 1.0.8 2020-05-07 [1] CRAN (R 4.0.0)
## pkgconfig 2.0.3 2019-09-22 [1] CRAN (R 4.0.0)
## pkgload 1.1.0 2020-05-29 [1] CRAN (R 4.0.0)
## plyr 1.8.6 2020-03-03 [1] CRAN (R 4.0.0)
## prettyunits 1.1.1 2020-01-24 [1] CRAN (R 4.0.0)
## processx 3.4.2 2020-02-09 [1] CRAN (R 4.0.0)
## ps 1.3.3 2020-05-08 [1] CRAN (R 4.0.0)
## purrr * 0.3.4 2020-04-17 [1] CRAN (R 4.0.0)
## R6 2.4.1 2019-11-12 [1] CRAN (R 4.0.0)
## Rcpp * 1.0.4.6 2020-04-09 [1] CRAN (R 4.0.0)
## RcppParallel 5.0.2 2020-06-24 [1] CRAN (R 4.0.0)
## readr * 1.3.1 2018-12-21 [1] CRAN (R 4.0.0)
## readxl 1.3.1 2019-03-13 [1] CRAN (R 4.0.0)
## remotes 2.1.1 2020-02-15 [1] CRAN (R 4.0.0)
## reprex 0.3.0 2019-05-16 [1] CRAN (R 4.0.0)
## rlang 0.4.6 2020-05-02 [1] CRAN (R 4.0.0)
## rmarkdown 2.2 2020-05-31 [1] CRAN (R 4.0.0)
## rprojroot 1.3-2 2018-01-03 [1] CRAN (R 4.0.0)
## rstan 2.19.3 2020-02-11 [1] CRAN (R 4.0.0)
## rstantools 2.0.0 2019-09-15 [1] CRAN (R 4.0.0)
## rstudioapi 0.11 2020-02-07 [1] CRAN (R 4.0.0)
## rvest 0.3.5 2019-11-08 [1] CRAN (R 4.0.0)
## scales 1.1.1 2020-05-11 [1] CRAN (R 4.0.0)
## sessioninfo 1.1.1 2018-11-05 [1] CRAN (R 4.0.0)
## StanHeaders 2.21.0-5 2020-06-09 [1] CRAN (R 4.0.0)
## stringi 1.4.6 2020-02-17 [1] CRAN (R 4.0.0)
## stringr * 1.4.0 2019-02-10 [1] CRAN (R 4.0.0)
## testthat 2.3.2 2020-03-02 [1] CRAN (R 4.0.0)
## tibble * 3.0.1 2020-04-20 [1] CRAN (R 4.0.0)
## tidyr * 1.1.0 2020-05-20 [1] CRAN (R 4.0.0)
## tidyselect 1.1.0 2020-05-11 [1] CRAN (R 4.0.0)
## tidyverse * 1.3.0 2019-11-21 [1] CRAN (R 4.0.0)
## truncnorm * 1.0-8 2018-02-27 [1] CRAN (R 4.0.0)
## usethis 1.6.1 2020-04-29 [1] CRAN (R 4.0.0)
## utf8 1.1.4 2018-05-24 [1] CRAN (R 4.0.0)
## vctrs 0.3.1 2020-06-05 [1] CRAN (R 4.0.0)
## withr 2.2.0 2020-04-20 [1] CRAN (R 4.0.0)
## xfun 0.14 2020-05-20 [1] CRAN (R 4.0.0)
## xml2 1.3.2 2020-04-23 [1] CRAN (R 4.0.0)
## yaml 2.2.1 2020-02-01 [1] CRAN (R 4.0.0)
##
## [1] /Library/Frameworks/R.framework/Versions/4.0/Resources/library