The model_parameters()
function (also accessible via the
shortcut parameters()
) allows you to extract the parameters
and their characteristics from various models in a consistent way. It
can be considered as a lightweight alternative to broom::tidy()
,
with some notable differences:
The names of the returned data frame are specific to their content. For instance, the column containing the statistic is named following the statistic name, i.e., t, z, etc., instead of a generic name such as statistic (however, you can get standardized (generic) column names using
standardize_names()
).It is able to compute or extract indices not available by default, such as **p*-values, CIs**, etc.
It includes feature engineering capabilities, including parameters bootstrapping.
Correlations and t-tests
Frequentist
library(parameters)
cor.test(iris$Sepal.Length, iris$Sepal.Width) |>
parameters()
#> Pearson's product-moment correlation
#>
#> Parameter1 | Parameter2 | r | 95% CI | t(148) | p
#> -----------------------------------------------------------------------------
#> iris$Sepal.Length | iris$Sepal.Width | -0.12 | [-0.27, 0.04] | -1.44 | 0.152
#>
#> Alternative hypothesis: true correlation is not equal to 0
t.test(mpg ~ vs, data = mtcars) |>
parameters()
#> Welch Two Sample t-test
#>
#> Parameter | Group | vs = 0 | vs = 1 | Difference | 95% CI | t(22.72) | p
#> --------------------------------------------------------------------------------------
#> mpg | vs | 16.62 | 24.56 | -7.94 | [-11.46, -4.42] | -4.67 | < .001
#>
#> Alternative hypothesis: true difference in means between group 0 and group 1 is not equal to 0
Bayesian
BayesFactor::correlationBF(iris$Sepal.Length, iris$Sepal.Width) |>
parameters()
#> Bayesian correlation analysis
#>
#> Parameter | Median | 95% CI | pd | Prior | BF
#> -------------------------------------------------------------------
#> rho | -0.11 | [-0.27, 0.04] | 92.25% | Beta (3 +- 3) | 0.509
BayesFactor::ttestBF(formula = mpg ~ vs, data = mtcars) |>
parameters()
#> Bayesian t-test
#>
#> Parameter | Median | 95% CI | pd | Prior | BF
#> ----------------------------------------------------------------------------
#> Difference | -7.31 | [-10.81, -3.79] | 99.98% | Cauchy (0 +- 0.71) | 529.27
ANOVAs
Indices of effect size for ANOVAs, such as partial and non-partial
versions of eta_squared()
, epsilon_sqared()
or
omega_squared()
are powered by the effectsize-package.
However, parameters uses these function to compute such
indices for parameters summaries, including confidence intervals
Simple
aov(Sepal.Length ~ Species, data = iris) |>
parameters(es_type = c("omega", "eta", "epsilon"))
#> Parameter | Sum_Squares | df | Mean_Square | F | p | Omega2 | Eta2 | Epsilon2
#> ----------------------------------------------------------------------------------------
#> Species | 63.21 | 2 | 31.61 | 119.26 | < .001 | 0.61 | 0.62 | 0.61
#> Residuals | 38.96 | 147 | 0.27 | | | | |
#>
#> Anova Table (Type 1 tests)
Let’s complicate things further with an interaction term:
aov(Sepal.Length ~ Species * Sepal.Width, data = iris) |>
parameters(
es_type = c("omega", "eta"),
ci = 0.8
)
#> Parameter | Sum_Squares | df | Mean_Square | F | p | Omega2 (partial) | Omega2 80% CI | Eta2 (partial) | Eta2 80% CI
#> ------------------------------------------------------------------------------------------------------------------------------------------
#> Species | 63.21 | 2 | 31.61 | 163.44 | < .001 | 0.68 | [0.65, 1.00] | 0.69 | [0.66, 1.00]
#> Sepal.Width | 10.95 | 1 | 10.95 | 56.64 | < .001 | 0.27 | [0.22, 1.00] | 0.28 | [0.23, 1.00]
#> Species:Sepal.Width | 0.16 | 2 | 0.08 | 0.41 | 0.667 | 0.00 | [0.00, 1.00] | 5.61e-03 | [0.00, 1.00]
#> Residuals | 27.85 | 144 | 0.19 | | | | | |
#>
#> Anova Table (Type 1 tests)
Repeated measures
parameters()
(resp. its alias
model_parameters()
) also works on repeated measures ANOVAs,
whether computed from aov()
or from a mixed model.
aov(mpg ~ am + Error(gear), data = mtcars) |>
parameters()
#> # gear
#>
#> Parameter | Sum_Squares | df | Mean_Square
#> ------------------------------------------
#> am | 259.75 | 1 | 259.75
#>
#> # Within
#>
#> Parameter | Sum_Squares | df | Mean_Square | F | p
#> ---------------------------------------------------------
#> am | 145.45 | 1 | 145.45 | 5.85 | 0.022
#> Residuals | 720.85 | 29 | 24.86 | |
#>
#> Anova Table (Type 1 tests)
Regressions (GLMs, Mixed Models, GAMs, …)
parameters()
(resp. its alias
model_parameters()
) was mainly built with regression models
in mind. It works for many types of models and packages, including mixed
models and Bayesian models.
GLMs
glm(vs ~ poly(mpg, 2) + cyl, data = mtcars, family = binomial()) |>
parameters()
#> Parameter | Log-Odds | SE | 95% CI | z | p
#> --------------------------------------------------------------------
#> (Intercept) | 13.51 | 7.20 | [ 2.56, 33.42] | 1.88 | 0.060
#> mpg [1st degree] | -6.64 | 8.99 | [-27.81, 11.13] | -0.74 | 0.461
#> mpg [2nd degree] | 1.16 | 3.59 | [ -7.91, 8.56] | 0.32 | 0.746
#> cyl | -2.28 | 1.18 | [ -5.58, -0.51] | -1.92 | 0.055
# show Odds Ratios and Wald-method for degrees of freedom
glm(vs ~ poly(mpg, 2) + cyl, data = mtcars, family = binomial()) |>
parameters(exponentiate = TRUE, ci_method = "wald")
#> Parameter | Odds Ratio | SE | 95% CI | z | p
#> ---------------------------------------------------------------------------
#> (Intercept) | 7.38e+05 | 5.31e+06 | [0.55, 9.87e+11] | 1.88 | 0.060
#> mpg [1st degree] | 1.31e-03 | 0.01 | [0.00, 59497.56] | -0.74 | 0.461
#> mpg [2nd degree] | 3.20 | 11.49 | [0.00, 3637.30] | 0.32 | 0.746
#> cyl | 0.10 | 0.12 | [0.01, 1.05] | -1.92 | 0.055
# show Odds Ratios and include model info
glm(vs ~ poly(mpg, 2) + cyl, data = mtcars, family = binomial()) |>
parameters(exponentiate = TRUE, include_info = TRUE)
#> Parameter | Odds Ratio | SE | 95% CI | z | p
#> ----------------------------------------------------------------------------
#> (Intercept) | 7.38e+05 | 5.31e+06 | [12.95, 3.26e+14] | 1.88 | 0.060
#> mpg [1st degree] | 1.31e-03 | 0.01 | [ 0.00, 68459.83] | -0.74 | 0.461
#> mpg [2nd degree] | 3.20 | 11.49 | [ 0.00, 5212.21] | 0.32 | 0.746
#> cyl | 0.10 | 0.12 | [ 0.00, 0.60] | -1.92 | 0.055
#>
#> Model: vs ~ poly(mpg, 2) + cyl (32 Observations)
#> Sigma: 1.000 (df = 28)
#> RMSE : 0.283
#> Tjur's R2: 0.670
Mixed Models
library(lme4)
lmer(Sepal.Width ~ Petal.Length + (1 | Species), data = iris) |>
parameters()
#> # Fixed Effects
#>
#> Parameter | Coefficient | SE | 95% CI | t(146) | p
#> ------------------------------------------------------------------
#> (Intercept) | 2.00 | 0.56 | [0.89, 3.11] | 3.56 | < .001
#> Petal Length | 0.28 | 0.06 | [0.16, 0.40] | 4.75 | < .001
#>
#> # Random Effects
#>
#> Parameter | Coefficient | SE | 95% CI
#> -----------------------------------------------------------
#> SD (Intercept: Species) | 0.89 | 0.46 | [0.33, 2.43]
#> SD (Residual) | 0.32 | 0.02 | [0.28, 0.35]
Mixed Models, without Random Effects Variances
lmer(Sepal.Width ~ Petal.Length + (1 | Species), data = iris) |>
parameters(effects = "fixed")
#> # Fixed Effects
#>
#> Parameter | Coefficient | SE | 95% CI | t(146) | p
#> ------------------------------------------------------------------
#> (Intercept) | 2.00 | 0.56 | [0.89, 3.11] | 3.56 | < .001
#> Petal Length | 0.28 | 0.06 | [0.16, 0.40] | 4.75 | < .001
Mixed Model with Zero-Inflation Model
library(GLMMadaptive)
library(glmmTMB)
data("Salamanders")
model <- mixed_model(
count ~ spp + mined,
random = ~ 1 | site,
zi_fixed = ~ spp + mined,
family = zi.negative.binomial(),
data = Salamanders
)
parameters(model)
#> # Fixed Effects (Count Model)
#>
#> Parameter | Log-Mean | SE | 95% CI | z | p
#> --------------------------------------------------------------
#> (Intercept) | -0.63 | 0.40 | [-1.42, 0.16] | -1.56 | 0.118
#> spp [PR] | -0.99 | 0.70 | [-2.35, 0.38] | -1.41 | 0.157
#> spp [DM] | 0.17 | 0.24 | [-0.29, 0.63] | 0.72 | 0.469
#> spp [EC-A] | -0.39 | 0.35 | [-1.07, 0.29] | -1.13 | 0.258
#> spp [EC-L] | 0.49 | 0.24 | [ 0.02, 0.96] | 2.03 | 0.043
#> spp [DES-L] | 0.59 | 0.23 | [ 0.14, 1.04] | 2.57 | 0.010
#> spp [DF] | -0.11 | 0.24 | [-0.59, 0.37] | -0.46 | 0.642
#> mined [no] | 1.45 | 0.37 | [ 0.73, 2.17] | 3.95 | < .001
#>
#> # Fixed Effects (Zero-Inflation Component)
#>
#> Parameter | Log-Odds | SE | 95% CI | z | p
#> ---------------------------------------------------------------
#> (Intercept) | 0.90 | 0.64 | [-0.35, 2.15] | 1.41 | 0.159
#> spp [PR] | 1.12 | 1.50 | [-1.82, 4.06] | 0.74 | 0.456
#> spp [DM] | -0.95 | 0.82 | [-2.56, 0.65] | -1.17 | 0.244
#> spp [EC-A] | 1.04 | 0.72 | [-0.38, 2.46] | 1.44 | 0.150
#> spp [EC-L] | -0.58 | 0.74 | [-2.03, 0.88] | -0.77 | 0.439
#> spp [DES-L] | -0.91 | 0.78 | [-2.43, 0.61] | -1.18 | 0.239
#> spp [DF] | -2.63 | 2.37 | [-7.27, 2.02] | -1.11 | 0.268
#> mined [no] | -2.56 | 0.63 | [-3.80, -1.32] | -4.06 | < .001
#>
#> # Random Effects Variances
#>
#> Parameter | Coefficient
#> ----------------------------------
#> SD (Intercept: site) | 0.39
#> SD (Residual) | 1.62
Mixed Models with Dispersion Model
library(glmmTMB)
sim1 <- function(nfac = 40, nt = 100, facsd = 0.1, tsd = 0.15, mu = 0, residsd = 1) {
dat <- expand.grid(fac = factor(letters[1:nfac]), t = 1:nt)
n <- nrow(dat)
dat$REfac <- rnorm(nfac, sd = facsd)[dat$fac]
dat$REt <- rnorm(nt, sd = tsd)[dat$t]
dat$x <- rnorm(n, mean = mu, sd = residsd) + dat$REfac + dat$REt
dat
}
set.seed(101)
d1 <- sim1(mu = 100, residsd = 10)
d2 <- sim1(mu = 200, residsd = 5)
d1$sd <- "ten"
d2$sd <- "five"
dat <- rbind(d1, d2)
model <- glmmTMB(x ~ sd + (1 | t), dispformula = ~sd, data = dat)
parameters(model)
#> # Fixed Effects
#>
#> Parameter | Coefficient | SE | 95% CI | z | p
#> -----------------------------------------------------------------------
#> (Intercept) | 200.03 | 0.10 | [ 199.84, 200.22] | 2056.35 | < .001
#> sd [ten] | -99.71 | 0.22 | [-100.14, -99.29] | -458.39 | < .001
#>
#> # Dispersion
#>
#> Parameter | Coefficient | SE | 95% CI | z | p
#> -----------------------------------------------------------------
#> (Intercept) | 1.60 | 0.01 | [1.57, 1.63] | 115.48 | < .001
#> sd [ten] | 0.69 | 0.02 | [0.65, 0.73] | 35.35 | < .001
#>
#> # Random Effects Variances
#>
#> Parameter | Coefficient
#> -------------------------------
#> SD (Intercept: t) | 4.61e-04
#> SD (Residual) |
Bayesian Models
model_parameters()
also works with Bayesian models from
the rstanarm package:
library(rstanarm)
# if you are unfamiliar with the `refresh` argument here, it just avoids
# printing few messages to the console
stan_glm(mpg ~ wt * cyl, data = mtcars, refresh = 0) |>
parameters()
#> Parameter | Median | 95% CI | pd | Rhat | ESS | Prior
#> -------------------------------------------------------------------------------------------
#> (Intercept) | 52.86 | [ 40.98, 63.96] | 100% | 1.003 | 1048.00 | Normal (20.09 +- 15.07)
#> wt | -8.09 | [-12.44, -3.72] | 99.88% | 1.002 | 1256.00 | Normal (0.00 +- 15.40)
#> cyl | -3.58 | [ -5.47, -1.63] | 99.98% | 1.002 | 1120.00 | Normal (0.00 +- 8.44)
#> wt:cyl | 0.73 | [ 0.11, 1.33] | 98.58% | 1.003 | 1068.00 | Normal (0.00 +- 1.36)
Additionally, it also works for models from the brms package.
For more complex models, specific model components can be printed
using the arguments effects
and component
arguments.
library(brms)
data(fish)
set.seed(123)
# fitting a model using `brms`
model <- suppressWarnings(brm(
bf(
count ~ persons + child + camper + (1 | persons),
zi ~ child + camper + (1 | persons)
),
data = fish,
family = zero_inflated_poisson(),
refresh = 0
))
parameters(model, component = "conditional", verbose = FALSE)
#> # Fixed Effects
#>
#> Parameter | Median | 95% CI | pd | Rhat | ESS
#> ----------------------------------------------------------------
#> (Intercept) | -0.87 | [-1.47, -0.29] | 99.50% | 1.013 | 319.00
#> persons | 0.84 | [ 0.65, 1.08] | 100% | 1.022 | 166.00
#> child | -1.15 | [-1.34, -0.97] | 100% | 1.001 | 2287.00
#> camper1 | 0.73 | [ 0.56, 0.92] | 100% | 1.006 | 774.00
parameters(model, effects = "all", component = "all", verbose = FALSE)
#> # Fixed Effects (Count Model)
#>
#> Parameter | Median | 95% CI | pd | Rhat | ESS
#> ----------------------------------------------------------------
#> (Intercept) | -0.87 | [-1.47, -0.29] | 99.50% | 1.013 | 319.00
#> persons | 0.84 | [ 0.65, 1.08] | 100% | 1.022 | 166.00
#> child | -1.15 | [-1.34, -0.97] | 100% | 1.001 | 2287.00
#> camper1 | 0.73 | [ 0.56, 0.92] | 100% | 1.006 | 774.00
#>
#> # Fixed Effects (Zero-Inflation Component)
#>
#> Parameter | Median | 95% CI | pd | Rhat | ESS
#> ----------------------------------------------------------------
#> (Intercept) | -0.65 | [-2.17, 0.73] | 84.92% | 1.003 | 1012.00
#> child | 1.88 | [ 1.23, 2.51] | 100% | 1.003 | 1680.00
#> camper1 | -0.84 | [-1.52, -0.12] | 99.05% | 1.008 | 900.00
#>
#> # Random Effects Variances
#>
#> Parameter | Median | 95% CI | pd | Rhat | ESS
#> ----------------------------------------------------------------------
#> SD (Intercept: persons) | 0.11 | [0.00, 1.12] | 100% | 1.056 | 56.00
#>
#> # Random Effects (Zero-Inflation Component)
#>
#> Parameter | Median | 95% CI | pd | Rhat | ESS
#> ------------------------------------------------------------------------
#> SD (Intercept: persons) | 1.28 | [0.52, 3.43] | 100% | 1.005 | 1039.00
To include information about the random effect parameters (group
levels), set group_level = TRUE
:
parameters(
model,
effects = "all",
component = "conditional",
group_level = TRUE,
verbose = FALSE
)
#> # Fixed Effects
#>
#> Parameter | Median | 95% CI | pd | Rhat | ESS
#> ----------------------------------------------------------------
#> (Intercept) | -0.87 | [-1.47, -0.29] | 99.50% | 1.013 | 319.00
#> persons | 0.84 | [ 0.65, 1.08] | 100% | 1.022 | 166.00
#> child | -1.15 | [-1.34, -0.97] | 100% | 1.001 | 2287.00
#> camper1 | 0.73 | [ 0.56, 0.92] | 100% | 1.006 | 774.00
#>
#> # Random Effects: persons
#>
#> Parameter | Median | 95% CI | pd | Rhat | ESS
#> -----------------------------------------------------------------
#> persons.1 | -5.37e-03 | [-0.41, 0.30] | 55.27% | 1.010 | 596.00
#> persons.2 | 0.02 | [-0.19, 0.37] | 64.65% | 1.005 | 595.00
#> persons.3 | -0.01 | [-0.33, 0.22] | 60.12% | 1.021 | 209.00
#> persons.4 | 2.47e-03 | [-0.44, 0.34] | 53.17% | 1.039 | 95.00
#> (Intercept) | 0.11 | [ 0.00, 1.12] | 100% | 1.056 | 56.00
Structural Models (PCA, EFA, CFA, SEM…)
The parameters package extends the support to structural models.
Principal Component Analysis (PCA) and Exploratory Factor Analysis (EFA)
psych::pca(mtcars, nfactors = 3) |>
parameters()
#> # Rotated loadings from Principal Component Analysis (varimax-rotation)
#>
#> Variable | RC2 | RC3 | RC1 | Complexity | Uniqueness
#> ----------------------------------------------------------
#> mpg | 0.66 | -0.41 | -0.54 | 2.63 | 0.10
#> cyl | -0.62 | 0.67 | 0.34 | 2.49 | 0.05
#> disp | -0.72 | 0.52 | 0.35 | 2.33 | 0.10
#> hp | -0.30 | 0.64 | 0.63 | 2.40 | 0.10
#> drat | 0.85 | -0.26 | -0.05 | 1.19 | 0.21
#> wt | -0.78 | 0.21 | 0.51 | 1.90 | 0.08
#> qsec | -0.18 | -0.91 | -0.28 | 1.28 | 0.06
#> vs | 0.28 | -0.86 | -0.23 | 1.36 | 0.12
#> am | 0.92 | 0.14 | -0.11 | 1.08 | 0.12
#> gear | 0.91 | -0.02 | 0.26 | 1.16 | 0.10
#> carb | 0.11 | 0.44 | 0.85 | 1.53 | 0.07
#>
#> The 3 principal components (varimax rotation) accounted for 89.87% of the total variance of the original data (RC2 = 41.43%, RC3 = 29.06%, RC1 = 19.39%).
We will avoid displaying a graph while carrying out factor analysis:
FactoMineR::FAMD(iris, ncp = 3, graph = FALSE) |>
parameters()
#> # Loadings from Factor Analysis (no rotation)
#>
#> Variable | Dim.1 | Dim.2 | Dim.3 | Complexity
#> -------------------------------------------------------
#> Sepal.Length | 0.75 | 0.07 | 0.10 | 1.05
#> Sepal.Width | 0.23 | 0.51 | 0.23 | 1.86
#> Petal.Length | 0.98 | 1.32e-03 | 1.99e-03 | 1.00
#> Petal.Width | 0.94 | 0.01 | 2.82e-05 | 1.00
#> Species | 0.96 | 0.75 | 0.26 | 2.05
#>
#> The 3 latent factors accounted for 96.73% of the total variance of the original data (Dim.1 = 64.50%, Dim.2 = 22.37%, Dim.3 = 9.86%).
Confirmatory Factor Analysis (CFA) and Structural Equation Models (SEM)
Frequentist
library(lavaan)
model <- lavaan::cfa(" visual =~ x1 + x2 + x3
textual =~ x4 + x5 + x6
speed =~ x7 + x8 + x9 ",
data = HolzingerSwineford1939
)
model_parameters(model)
#> # Loading
#>
#> Link | Coefficient | SE | 95% CI | z | p
#> ------------------------------------------------------------------
#> visual =~ x1 | 1.00 | 0.00 | [1.00, 1.00] | | < .001
#> visual =~ x2 | 0.55 | 0.10 | [0.36, 0.75] | 5.55 | < .001
#> visual =~ x3 | 0.73 | 0.11 | [0.52, 0.94] | 6.68 | < .001
#> textual =~ x4 | 1.00 | 0.00 | [1.00, 1.00] | | < .001
#> textual =~ x5 | 1.11 | 0.07 | [0.98, 1.24] | 17.01 | < .001
#> textual =~ x6 | 0.93 | 0.06 | [0.82, 1.03] | 16.70 | < .001
#> speed =~ x7 | 1.00 | 0.00 | [1.00, 1.00] | | < .001
#> speed =~ x8 | 1.18 | 0.16 | [0.86, 1.50] | 7.15 | < .001
#> speed =~ x9 | 1.08 | 0.15 | [0.79, 1.38] | 7.15 | < .001
#>
#> # Correlation
#>
#> Link | Coefficient | SE | 95% CI | z | p
#> ---------------------------------------------------------------------
#> visual ~~ textual | 0.41 | 0.07 | [0.26, 0.55] | 5.55 | < .001
#> visual ~~ speed | 0.26 | 0.06 | [0.15, 0.37] | 4.66 | < .001
#> textual ~~ speed | 0.17 | 0.05 | [0.08, 0.27] | 3.52 | < .001
Meta-Analysis
parameters()
also works for rma
-objects
from the metafor package.
library(metafor)
mydat <<- data.frame(
effectsize = c(-0.393, 0.675, 0.282, -1.398),
standarderror = c(0.317, 0.317, 0.13, 0.36)
)
rma(yi = effectsize, sei = standarderror, method = "REML", data = mydat) |>
model_parameters()
#> Meta-analysis using 'metafor'
#>
#> Parameter | Coefficient | SE | 95% CI | z | p | Weight
#> -------------------------------------------------------------------------
#> Study 1 | -0.39 | 0.32 | [-1.01, 0.23] | -1.24 | 0.215 | 9.95
#> Study 2 | 0.68 | 0.32 | [ 0.05, 1.30] | 2.13 | 0.033 | 9.95
#> Study 3 | 0.28 | 0.13 | [ 0.03, 0.54] | 2.17 | 0.030 | 59.17
#> Study 4 | -1.40 | 0.36 | [-2.10, -0.69] | -3.88 | < .001 | 7.72
#> Overall | -0.18 | 0.44 | [-1.05, 0.68] | -0.42 | 0.676 |
Plotting Model Parameters
There is a plot()
-method implemented in the see-package.
Several examples are shown in this
vignette.