Models fitted to a complex survey design with
survey::svyglm() are supported. Declare the design, fit the
model to it and pass the fit: the variance is the design-based one the
fit carries, and the intervals and tests are referred to a t and an F on
the degrees of freedom of the design, as survey itself
reports them. The interaction is tested by the Rao-Scott working
likelihood ratio test that survey::anova() takes over two
nested fits, the ordinary likelihood ratio test having no meaning for a
design-weighted pseudo-likelihood; test = "wald" gives the
F test survey::regTermTest() reports. vcov and
cluster are refused for such a fit, the clustering being
part of the design. The counts beside the rows are the unweighted
numbers of people in the sample, taken over the rows the fit gave weight
to, so a design that was subset() counts the subset. The
report names the standard errors as design-based, and the R code tab of
foresty_app() writes the same test in survey’s
own terms.
A quasibinomial family with a logit link is read as
an odds ratio, as a binomial one is. It was left as a
coefficient, drawn about zero, though the report already called the
model a logistic regression.
An F test of the interaction is written with both of its degrees
of freedom, F = 8.93 on 1 and 113 df, in
summary(), the HTML report and the app.
foresty_data(color = ) names a column of the data
saying what color each row is drawn in, which is how a figure drawn from
a table colors the rows it chooses rather than the ones a rule would
have chosen. color_by in foresty_layout()
works the color out from the labels, which it can do for a figure that
came off a model and its levels; a table of estimates carries whatever
the author put in it, so it says instead. The column holds either the
colors themselves – "red", "#B24745" – or the
names of categories, drawn in the layout’s colors one color
per name; which of the two it is, is read off the values rather than
asked for again, and a column holding some of each is refused where it
was named. The mark, its interval and the summary diamond are all drawn
in it, the reference level of a categorical exposure stays hollow, and
no legend is drawn, every row being labelled already.
First release. Published on CRAN on 2026-09-12.
foresty_app() provides a Shiny interface for
interactively selecting exposures, modifiers, contrasts, colors, and
plot layouts. Its R code tab writes the code twice over: the
foresty calls that drew the figures, and the same estimates
worked out in base R and the car package with nothing from
this package in them – the interaction term, the linear combination of
the coefficients each subgroup estimate is, and the joint test beside
it. For a multinomial fit that linear combination is a difference of
blocks of coefficients, one block per equation, and the script writes
that out too.foresty_data() draws the same figure – the forest plot
and the table of numbers beside it, aligned row for row, in any of the
journal styles – from estimates you already have: a
data.frame, tibble or data.table
with one row per row of the figure. It is the entry point for numbers
that did not come out of a model this package can read: a meta-analysis,
a table being redrawn from a paper, a model fitted by something
else.glm(), lm(),
survival models, and lme4 models, with robust
and cluster-robust standard errors through sandwich.MASS::polr() and
nominal outcomes through nnet::multinom(). A multinomial
fit holds one equation per non-reference level of the outcome, so the
figure carries one row per level. outcome_reference says
which level they are all read against and
outcome_reference_row draws that level as a row of its own.
The interaction is tested jointly across the equations, so its p-value
is a chunk test spending one degree of freedom for each coefficient the
interaction added.822 vs 468 people and 125 vs 59
events, those being the groups its odds ratio was estimated from. A
multinomial row, which compares two levels of the outcome, reads
637 vs 1,050 under the sizes and drops the events column,
which would have repeated the first of them.
foresty_layout(counts = "row") holds the row’s own group
alone, as before. The rows that compare no two groups of people – a step
along a continuous exposure, and the reference rows – are
unchanged.?foresty_main:
they are taken over the rows the model was fitted to, so a complete case
on the outcome, the exposure and the covariates. The figures whose rows
compare two groups say which two under the plot in
foresty_app() and under the table of estimates in
foresty_report(), and say of a multinomial fit that the
estimate did not come out of those two groups alone. The figure itself
is unchanged, so the downloads are what they always were.summary(), as.data.frame(),
broom::tidy(), broom::glance(),
coef(), vcov(), predict(),
formula(), and nobs() are supported for
foresty results.