library(equatiomatic)
# Create a simple linear model
mod2 <- lm(mpg ~ ., mtcars)
When writing dynamic documents in R (either R Markdown or Quarto), it can be useful to display model equations. I recently discovered equatiomatic, a very nice package that can do the job.
Photo by Artturi Jalli on Unsplash
The package can be installed from CRAN using install.packages("equatiomatic")
. To explore the package’s functionalities, we will build a simple linear model using mtcars
data (most examples are taken from the equatiomatic vignette website).
broom::tidy(mod2)
#> # A tibble: 11 × 5
#> term estimate std.error statistic p.value
#> <chr> <dbl> <dbl> <dbl> <dbl>
#> 1 (Intercept) 12.3 18.7 0.657 0.518
#> 2 cyl -0.111 1.05 -0.107 0.916
#> 3 disp 0.0133 0.0179 0.747 0.463
#> 4 hp -0.0215 0.0218 -0.987 0.335
#> 5 drat 0.787 1.64 0.481 0.635
#> 6 wt -3.72 1.89 -1.96 0.0633
#> 7 qsec 0.821 0.731 1.12 0.274
#> 8 vs 0.318 2.10 0.151 0.881
#> 9 am 2.52 2.06 1.23 0.234
#> 10 gear 0.655 1.49 0.439 0.665
#> 11 carb -0.199 0.829 -0.241 0.812
There are different ways to display the model equation. The most basic way is to call the extract_eq()
function. This will display the equation without the fitted coefficients.
extract_eq(mod2)
\[ \operatorname{mpg} = \alpha + \beta_{1}(\operatorname{cyl}) + \beta_{2}(\operatorname{disp}) + \beta_{3}(\operatorname{hp}) + \beta_{4}(\operatorname{drat}) + \beta_{5}(\operatorname{wt}) + \beta_{6}(\operatorname{qsec}) + \beta_{7}(\operatorname{vs}) + \beta_{8}(\operatorname{am}) + \beta_{9}(\operatorname{gear}) + \beta_{10}(\operatorname{carb}) + \epsilon \]
As we can see, this equation is pretty long. It would be best to wrap it over multiple lines. This can be controlled using wrap = TRUE
.
extract_eq(mod2, wrap = TRUE)
\[ \begin{aligned} \operatorname{mpg} &= \alpha + \beta_{1}(\operatorname{cyl}) + \beta_{2}(\operatorname{disp}) + \beta_{3}(\operatorname{hp})\ + \\ &\quad \beta_{4}(\operatorname{drat}) + \beta_{5}(\operatorname{wt}) + \beta_{6}(\operatorname{qsec}) + \beta_{7}(\operatorname{vs})\ + \\ &\quad \beta_{8}(\operatorname{am}) + \beta_{9}(\operatorname{gear}) + \beta_{10}(\operatorname{carb}) + \epsilon \end{aligned} \]
The number of terms per line is controlled with terms_per_line
.
extract_eq(mod2, wrap = TRUE, terms_per_line = 2)
\[ \begin{aligned} \operatorname{mpg} &= \alpha + \beta_{1}(\operatorname{cyl})\ + \\ &\quad \beta_{2}(\operatorname{disp}) + \beta_{3}(\operatorname{hp})\ + \\ &\quad \beta_{4}(\operatorname{drat}) + \beta_{5}(\operatorname{wt})\ + \\ &\quad \beta_{6}(\operatorname{qsec}) + \beta_{7}(\operatorname{vs})\ + \\ &\quad \beta_{8}(\operatorname{am}) + \beta_{9}(\operatorname{gear})\ + \\ &\quad \beta_{10}(\operatorname{carb}) + \epsilon \end{aligned} \]
There is a lot of styling customization that can be performed.
extract_eq(mod2, wrap = TRUE, greek_colors = "red", subscript_colors = "blue")
\[ \begin{aligned} \operatorname{mpg} &= {\color{red}{\alpha}} + {\color{red}{\beta}}_{{\color{blue}{1}}}(\operatorname{cyl}) + {\color{red}{\beta}}_{{\color{blue}{2}}}(\operatorname{disp}) + {\color{red}{\beta}}_{{\color{blue}{3}}}(\operatorname{hp})\ + \\ &\quad {\color{red}{\beta}}_{{\color{blue}{4}}}(\operatorname{drat}) + {\color{red}{\beta}}_{{\color{blue}{5}}}(\operatorname{wt}) + {\color{red}{\beta}}_{{\color{blue}{6}}}(\operatorname{qsec}) + {\color{red}{\beta}}_{{\color{blue}{7}}}(\operatorname{vs})\ + \\ &\quad {\color{red}{\beta}}_{{\color{blue}{8}}}(\operatorname{am}) + {\color{red}{\beta}}_{{\color{blue}{9}}}(\operatorname{gear}) + {\color{red}{\beta}}_{{\color{blue}{10}}}(\operatorname{carb}) + {\color{red}{\epsilon}} \end{aligned} \]
One can use use_coefs = TRUE
to extract the fitted coefficients.
extract_eq(mod2, wrap = TRUE, use_coefs = TRUE)
\[ \begin{aligned} \operatorname{\widehat{mpg}} &= 12.3 - 0.11(\operatorname{cyl}) + 0.01(\operatorname{disp}) - 0.02(\operatorname{hp})\ + \\ &\quad 0.79(\operatorname{drat}) - 3.72(\operatorname{wt}) + 0.82(\operatorname{qsec}) + 0.32(\operatorname{vs})\ + \\ &\quad 2.52(\operatorname{am}) + 0.66(\operatorname{gear}) - 0.2(\operatorname{carb}) \end{aligned} \]
Many types of models are supported by equatiomatic
. Further information can be found on the equatiomatic website.
Session info
#> ─ Session info ───────────────────────────────────────────────────────────────────────────────────────────────────────
#> setting value
#> version R version 4.4.0 (2024-04-24)
#> os Ubuntu 24.04 LTS
#> system x86_64, linux-gnu
#> ui X11
#> language en_CA:en
#> collate en_CA.UTF-8
#> ctype en_CA.UTF-8
#> tz America/Toronto
#> date 2024-05-02
#> pandoc 3.1.3 @ /usr/bin/ (via rmarkdown)
#>
#> ─ Packages ───────────────────────────────────────────────────────────────────────────────────────────────────────────
#> ! package * version date (UTC) lib source
#> P backports 1.4.1 2021-12-13 [?] RSPM (R 4.4.0)
#> P broom 1.0.5 2023-06-09 [?] RSPM (R 4.4.0)
#> P cachem 1.0.8 2023-05-01 [?] RSPM (R 4.4.0)
#> P cli 3.6.2 2023-12-11 [?] RSPM (R 4.4.0)
#> P devtools 2.4.5 2022-10-11 [?] RSPM
#> P digest 0.6.35 2024-03-11 [?] RSPM (R 4.4.0)
#> P dplyr 1.1.4 2023-11-17 [?] RSPM (R 4.4.0)
#> P ellipsis 0.3.2 2021-04-29 [?] RSPM (R 4.4.0)
#> P equatiomatic * 0.3.1 2024-05-02 [?] Github (datalorax/equatiomatic@39e8c3e)
#> P evaluate 0.23 2023-11-01 [?] RSPM (R 4.4.0)
#> P fansi 1.0.6 2023-12-08 [?] RSPM (R 4.4.0)
#> P fastmap 1.1.1 2023-02-24 [?] RSPM (R 4.4.0)
#> P fs 1.6.4 2024-04-25 [?] CRAN (R 4.4.0)
#> P generics 0.1.3 2022-07-05 [?] RSPM (R 4.4.0)
#> P glue 1.7.0 2024-01-09 [?] RSPM (R 4.4.0)
#> P htmltools 0.5.8.1 2024-04-04 [?] RSPM (R 4.4.0)
#> P htmlwidgets 1.6.4 2023-12-06 [?] RSPM
#> P httpuv 1.6.15 2024-03-26 [?] RSPM (R 4.4.0)
#> P jsonlite 1.8.8 2023-12-04 [?] RSPM (R 4.4.0)
#> P knitr 1.46 2024-04-06 [?] RSPM (R 4.4.0)
#> P later 1.3.2 2023-12-06 [?] RSPM (R 4.4.0)
#> P lifecycle 1.0.4 2023-11-07 [?] RSPM (R 4.4.0)
#> P magrittr 2.0.3 2022-03-30 [?] RSPM (R 4.4.0)
#> P memoise 2.0.1 2021-11-26 [?] RSPM (R 4.4.0)
#> P mime 0.12 2021-09-28 [?] RSPM (R 4.4.0)
#> P miniUI 0.1.1.1 2018-05-18 [?] RSPM (R 4.4.0)
#> P pillar 1.9.0 2023-03-22 [?] RSPM (R 4.4.0)
#> P pkgbuild 1.4.4 2024-03-17 [?] RSPM (R 4.4.0)
#> P pkgconfig 2.0.3 2019-09-22 [?] RSPM (R 4.4.0)
#> P pkgload 1.3.4 2024-01-16 [?] RSPM
#> P processx 3.8.4 2024-03-16 [?] RSPM (R 4.4.0)
#> P profvis 0.3.8 2023-05-02 [?] RSPM
#> P promises 1.3.0 2024-04-05 [?] RSPM (R 4.4.0)
#> P ps 1.7.6 2024-01-18 [?] RSPM (R 4.4.0)
#> P purrr 1.0.2 2023-08-10 [?] RSPM (R 4.4.0)
#> P quarto * 1.4 2024-03-06 [?] RSPM
#> P R.cache 0.16.0 2022-07-21 [?] RSPM
#> P R.methodsS3 1.8.2 2022-06-13 [?] RSPM
#> P R.oo 1.26.0 2024-01-24 [?] RSPM
#> P R.utils 2.12.3 2023-11-18 [?] RSPM
#> P R6 2.5.1 2021-08-19 [?] RSPM (R 4.4.0)
#> P Rcpp 1.0.12 2024-01-09 [?] RSPM (R 4.4.0)
#> P remotes 2.5.0 2024-03-17 [?] RSPM
#> P renv 1.0.7 2024-04-11 [?] RSPM (R 4.4.0)
#> P rlang 1.1.3 2024-01-10 [?] RSPM (R 4.4.0)
#> P rmarkdown 2.26 2024-03-05 [?] RSPM (R 4.4.0)
#> P rstudioapi 0.16.0 2024-03-24 [?] RSPM
#> P sessioninfo 1.2.2 2021-12-06 [?] RSPM
#> P shiny 1.8.1.1 2024-04-02 [?] RSPM (R 4.4.0)
#> P stringi 1.8.3 2023-12-11 [?] RSPM (R 4.4.0)
#> P stringr 1.5.1 2023-11-14 [?] RSPM (R 4.4.0)
#> P styler * 1.10.3 2024-04-07 [?] RSPM
#> P tibble 3.2.1 2023-03-20 [?] RSPM (R 4.4.0)
#> P tidyr 1.3.1 2024-01-24 [?] RSPM (R 4.4.0)
#> P tidyselect 1.2.1 2024-03-11 [?] RSPM (R 4.4.0)
#> P urlchecker 1.0.1 2021-11-30 [?] RSPM
#> P usethis 2.2.3 2024-02-19 [?] RSPM
#> P utf8 1.2.4 2023-10-22 [?] RSPM (R 4.4.0)
#> P vctrs 0.6.5 2023-12-01 [?] RSPM (R 4.4.0)
#> P xfun 0.43 2024-03-25 [?] RSPM (R 4.4.0)
#> P xtable 1.8-4 2019-04-21 [?] RSPM (R 4.4.0)
#> P yaml 2.3.8 2023-12-11 [?] RSPM (R 4.4.0)
#>
#> [1] /tmp/RtmpC4S8Ab/renv-use-libpath-2e3df224e3b7d5
#> [2] /home/filoche/.cache/R/renv/sandbox/linux-ubuntu-noble/R-4.4/x86_64-pc-linux-gnu/a71ef467
#>
#> P ── Loaded and on-disk path mismatch.
#>
#> ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────