The equatiomatic package (Anderson, Heiss, & Sumners, 2026) provides
a general mechanism for converting fitted statistical models into LaTeX
equations, via the function extract_eq(). For any model
class that has a broom::tidy() method,
extract_eq() can generate both the symbolic form of the
model equation and a version with fitted coefficient values substituted
in.
The nestedLogit package (Fox
& Friendly, 2026) supports extract_eq() for
objects of class "nestedLogit" through a dedicated S3
method, extract_eq.nestedLogit. Because a nested logit
model is represented internally as a collection of binary logit
sub-models — one for each dichotomy — extract_eq()
generates a separate equation for each dichotomy and returns them as a
named list.
To use these features, load both packages:
We use the Womenlf data (Fox,
Weisberg, & Price, 2026), which records the labor-force
participation of married women and is included in the
carData package. The three-category response
partic (not working, part-time, full-time) is decomposed
into two nested binary dichotomies:
Calling extract_eq() on a "nestedLogit"
object with submodel = "name" returns the equation for a
single dichotomy in symbolic (Greek-letter) form, labeled by its name.
The equation renders automatically in R Markdown and Quarto
documents.
\[ \log\left[ \frac { P( \operatorname{work} ) }{ 1 - P( \operatorname{work} ) } \right] = \alpha + \beta_{1}(\operatorname{hincome}) + \beta_{2}(\operatorname{children}_{\operatorname{present}}) \]
\[ \log\left[ \frac { P( \operatorname{full} ) }{ 1 - P( \operatorname{full} ) } \right] = \alpha + \beta_{1}(\operatorname{hincome}) + \beta_{2}(\operatorname{children}_{\operatorname{present}}) \]
A new version of equatiomatic (v. 0.4.6) implements a
logit_notation argument to simply the display of the LHS of
these equations as logit [P()] rather than
log [P() / 1 - P()].
\[ \operatorname{logit}\left[ P(\operatorname{full}) \right] = \alpha + \beta_{1}(\operatorname{hincome}) + \beta_{2}(\operatorname{children}_{\operatorname{present}}) \]
extract_eq() optionsThere are a wide variety of options you can pass to
extract_eq() to control the details of how the equations
are rendered in LaTeX. These include:
use_coefs: Use the model estimates in the equations
instead of symbols, a nice way to display a fitted modelgreek_colors, var_colors,
subscript_colors and others.ital_vars: Logical, defaults to FALSE.
Should the variable names not be wrapped in the
\operatorname{} command so they appear in Roman text?Passing use_coefs = TRUE substitutes the fitted
coefficient values into the equations.
\[ \log\left[ \frac { \widehat{P( \operatorname{work} )} }{ 1 - \widehat{P( \operatorname{work} )} } \right] = 1.34 - 0.04(\operatorname{hincome}) - 1.58(\operatorname{children}_{\operatorname{present}}) \]
\[ \log\left[ \frac { \widehat{P( \operatorname{full} )} }{ 1 - \widehat{P( \operatorname{full} )} } \right] = 3.48 - 0.11(\operatorname{hincome}) - 2.65(\operatorname{children}_{\operatorname{present}}) \]
The greek_colors and var_colors arguments
control the color of the Greek coefficient symbols and the variable
names, respectively. This can help distinguish the structural parameters
from the predictors when displaying equations in presentations or
documents.
\[ \log\left[ \frac { P( \operatorname{work} ) }{ 1 - P( \operatorname{work} ) } \right] = {\color{blue}{\alpha}} + {\color{blue}{\beta}}_{1}(\operatorname{hincome}) + {\color{blue}{\beta}}_{2}(\operatorname{children}_{\operatorname{present}}) \]
The color arguments accept any R color name or hex code, and can be a
vector to color each symbol differently. var_colors needs a
named vector of the variable names.
extract_eq(wlf.nested,
greek_colors = c("black", "blue", "blue"),
var_colors = c(hincome = "red", children="darkgreen"),
submodel = "work")\[ \log\left[ \frac { P( \operatorname{work} ) }{ 1 - P( \operatorname{work} ) } \right] = {\color{black}{\alpha}} + {\color{blue}{\beta}}_{1}({\color{red}{\operatorname{hincome}}}) + {\color{blue}{\beta}}_{2}({\color{darkgreen}{\operatorname{children}}}_{\operatorname{present}}) \]
The individual binary logit sub-models (objects of class
"glm") can also be passed directly to
extract_eq(). This can be useful when you want to work with
a single dichotomy in isolation.
\[ \log\left[ \frac { P( \operatorname{..y} = \operatorname{1} ) }{ 1 - P( \operatorname{..y} = \operatorname{1} ) } \right] = \alpha + \beta_{1}(\operatorname{hincome}) + \beta_{2}(\operatorname{children}_{\operatorname{present}}) \]
Note that the response is rendered as ..y — the internal
variable name used when fitting the sub-model — rather than as a
meaningful label. The extract_eq() method for a
"nestedLogit" model fixes this infelicity.
Each equation returned by extract_eq() is an object of
class "equation" (from equatiomatic), which is
a character string containing the LaTeX source. This renders
automatically in R Markdown and Quarto documents. To access the raw
LaTeX — for example to paste it into a paper or to render it with
another tool such as katex — use
as.character():
cat(as.character(extract_eq(wlf.nested, submodel = "work")), "\n\n")
#> \log\left[ \frac { P( \operatorname{work} ) }{ 1 - P( \operatorname{work} ) } \right] = \alpha + \beta_{1}(\operatorname{hincome}) + \beta_{2}(\operatorname{children}_{\operatorname{present}})
cat(as.character(extract_eq(wlf.nested, submodel = "full")), "\n")
#> \log\left[ \frac { P( \operatorname{full} ) }{ 1 - P( \operatorname{full} ) } \right] = \alpha + \beta_{1}(\operatorname{hincome}) + \beta_{2}(\operatorname{children}_{\operatorname{present}})gators dataThe gators data (built into nestedLogit)
records the primary food choice of alligators — Other, Fish, or
Invertebrates — as a function of body length. The three-category
response is decomposed into two dichotomies using
logits():
data(gators)
gators.dichots <- logits(
other = dichotomy("Other", c("Fish", "Invertebrates")),
fish_inv = dichotomy("Fish", "Invertebrates")
)
gators.dichots
#> other: {Other} vs. {Fish, Invertebrates}
#> fish_inv: {Fish} vs. {Invertebrates}
gators.nested <- nestedLogit(food ~ length,
dichotomies = gators.dichots,
data = gators)Note that the dichotomy name fish_inv contains an
underscore. Because _ is the subscript operator in LaTeX,
extract_eq() replaces it with . in the
displayed equation (the submodel argument still uses the
original R name).
\[ \log\left[ \frac { P( \operatorname{other} ) }{ 1 - P( \operatorname{other} ) } \right] = \alpha + \beta_{1}(\operatorname{length}) \]
\[ \log\left[ \frac { P( \operatorname{fish.inv} ) }{ 1 - P( \operatorname{fish.inv} ) } \right] = \alpha + \beta_{1}(\operatorname{length}) \]
With fitted coefficients:
\[ \log\left[ \frac { \widehat{P( \operatorname{other} )} }{ 1 - \widehat{P( \operatorname{other} )} } \right] = 3.13 - 0.57(\operatorname{length}) \]
\[ \log\left[ \frac { \widehat{P( \operatorname{fish.inv} )} }{ 1 - \widehat{P( \operatorname{fish.inv} )} } \right] = 4.32 - 2.48(\operatorname{length}) \]