All-in-one tables for regressions, with each modelled effect beside its observed one
Source:R/tab_reg.R
tab_reg.RdFits one regression model per column and returns a tabxplor table of the per-family effect
measure — a linear mean difference (gaussian), odds ratios (binomial), incidence-rate
ratios (poisson), one odds-ratio column per outcome category (nominal 3+ level), a
cumulative odds ratio (ordinal) — one row per predictor level, grouped by predictor, with
the observed (crude) effect beside each adjusted one. Each cell stores its estimate, interval
and p-value, so the table prints with stars, greys what is not significant, and exports like any
tabxplor crosstab.
Usage
tab_reg(
data,
outcome,
predictors = NULL,
tab_vars = NULL,
wt = NULL,
family = "auto",
link = "auto",
measure = "auto",
effect = "auto",
outcome_level = NULL,
trials = NULL,
empirical = TRUE,
n = NULL,
color = "measure",
color_signif = NULL,
stars = TRUE,
ref = NULL,
multiplier = "2sd",
shape = NULL,
stats = "auto",
conf_level = NULL,
na = c("drop_by_outcome", "drop_by_model", "drop_all", "keep_for_predictors"),
display = NULL,
digits = 0,
cleannames = NULL,
subtext = "",
caption = NULL,
...
)Arguments
- data
A data frame, or a prebuilt survey design (
survey::svydesign()). A design's weights, clustering, stratification and calibration drive the estimation, andwtis ignored.- outcome
<
tidy-select> The outcome variable(s) — bare names, quoted names, or any selection helper, exactly as intab()— or a model formula (the escape hatch; leavepredictorsunset). Several names give one effect column per outcome; with apredictorslist, a single name is required.reg_formulas()shows what was fitted.- predictors
<
tidy-select> The predictors of one model — or a named list, one model per element, its name labelling the column, each element selected on its own (list(m1 = c(race, age), m2 = starts_with("inc"))), which is how models are compared. LeaveNULLwhenoutcomeis a formula. A bare name is a column ofdatafirst, then an object, so a variable holding names works withoutall_of().a*bis an interaction, R's own spelling, bare or quoted — "a's effect, allowed to vary with b". Two categorical variables give one row per cell of the pair; a continuousagives its slope within each level ofb. An interaction supplies both its variables, so do not list them beside it, which is what makes "with and without" an ordinary model comparison.a:b, which drops the main effects, is refused. See the regression vignette.- tab_vars
<
tidy-select> Optional. One grouping variable — the same argument astab()'s: one sub-table per group, the same model(s) fitted within each level. Two readings of "does this effect hold in every subgroup?" come with it:color = "between_groups"colours and tests each effect against the first group's, row by row, andstats = c(..., "group_interaction")adds the aggregated test, once per predictor. For an interaction between two PREDICTORS of one model, write it inpredictorsasa*binstead.- wt
<
tidy-select> Optional. One weight column, switching to design-based survey estimation (survey::svyglm()). For clustering, stratification, a finite-population correction or calibration, build the design withsurvey::svydesign()and pass it asdata. Seevignette("tabxplor-weights").- family
The model family, resolved per outcome so several outcomes with different families can share one table.
"auto"(default) detects each one and says so: a binary outcome gives"binomial", an ordered 3+ level"ordinal", a nominal 3+ level"multinomial", any other numeric"gaussian"— a genuine count is yours to name. Or set it:"gaussian"(linear),"binomial"(logistic),"poisson"/"quasipoisson"(counts),"multinomial","ordinal". A scalar applies to every outcome; a vector aligned tooutcome, or a named vector keyed by outcome (e.g.c(income = "poisson", satisfied = "binomial")), sets one family per outcome. Mixed families need a characterpredictors.It answers one question — what kind of number the outcome is — and never picks a link behind your back: on a binary outcome
family = "poisson"is refused, naming the two things it could have meant,link = "ratio"andmeasure = "ratio".- link
Which measure the model estimates — the only argument that changes the model. A link is a measure (the one a model gives you directly), so it takes
measure's own words:"auto"(default) — the family's own: logistic for a binary outcome, linear for a quantity, Poisson for a count."odds_ratio"— the logit fit (binomial, multinomial, ordinal)."ratio"— the log link: the modified Poisson on a binary outcome (a conditional risk ratio), Poisson on a count, Poisson pseudo-likelihood on a continuous one."difference"— the identity link; on a binary outcome the risk difference. It can fail to converge, and the linear probability model then takes over, with a message.
Reach for it when you want the model's coefficient to be that measure; to report a measure without changing the model, set
measureinstead."log"is the one word the two arguments do not share: here the log link, onmeasurea spelling of"raw_coefficient".- measure
Which measure of deviation is reported — a deviation being how far a group sits from the reference, the measure which of the ways of expressing it you read. The one argument most readers ever set, and the one that never changes the model.
"auto"(default) is the model's own. The full word is canonical, the discipline's acronym a synonym:"odds_ratio"("OR") — the odds of the outcome, times what."ratio"("RR","IRR","RoM") — how many times as likely, as frequent, as large. Reach for it when the outcome is common, where an odds ratio is far from the risk ratio people hear in it, and because a risk ratio stays comparable across nested models."difference"("RD","diff") — how much more, in the outcome's own units."raw_coefficient"("coef","log", ...) — the model's own coefficient, un-transformed.
On an ordered outcome the first three read the whole predicted distribution rather than one category, so they stay in one column: Somers'
Dand the win ratio. Where the measure IS the model's own it is read off the coefficients, otherwise from its predictions — so it is available whichever model you fit."auto"never lands on a predicted odds ratio, a specialist quantity to be asked for by name. Callreg_measures()to see what an outcome offers.- effect
Where the reported number comes from, once the model and the measure are fixed.
"auto"(default) needs no thought: the model's own coefficients when the reported measure is the model's, its predictions otherwise. The other values name a reading:"conditional"— read off the coefficients ("holding the other predictors constant"). Only wheremeasureis the model's own; otherwise the abort names the two cures."marginal"— the average marginal effect: the model's prediction for every observed person, averaged. Comparable across models (Mood 2010), and always available."at_reference"— the same at one profile, every other predictor at its reference.
The contrast is a marker on the measure in the header, so the acronym stays the one thing to look up:
Model_OR,Model_mRR,Model_refRD. The observed companion carries the measure alone (Obs_RR), a univariable effect having no adjustment to be marginal over.- outcome_level
Which level of the outcome to single out, as a named vector keyed by outcome name —
outcome_level = c(married = "Married"). It is the twin ofref:refnames the level you compare AGAINST,outcome_levelthe one you MODEL.binomial: the level whose probability is estimated; it becomes the column header. Defaults to the outcome's first level. A 0/1 numeric outcome may be named either way.
multinomial: the baseline category the other categories' columns are compared to.
ordinal and numeric outcomes: refused, with the reason.
- trials
Grouped-binomial (summed-score) outcomes only. The number of items behind the score, fitting
cbind(score, trials - score)as a binomial.NULL(default) fits an ordinary binary logit; an integer (or a vector named by outcome) sets the item count;TRUEuses each outcome's observed maximum. Requiresfamily = "binomial".- empirical
Show the observed, unadjusted (crude) effect beside each modelled one — the same quantity fitted with a single predictor, on exactly the same people. The distance between the two is what adjustment changed, read left to right; it is the feature the package exists for.
TRUE(the default) orFALSE; three spellings say where it goes, and in every one but"no"it is stored in theobsfield and read by$obs,color = "adjustment",forest_plot()and the hover tooltip:TRUE— a crude column beside the model one, except where that would double a table already wide (tab_varsgroups, a 3+ level outcome), which take"tooltip"."column"— always the column, per outcome category if that is what it takes."tooltip"— computed, printed nowhere. The narrowest table."cell"— inside the model cell,(1/1.69) 1/1.63***.displayoverrides it.
The two columns are the same column twice: same estimand, same colour ladder, one legend block. Each cell prints the effect with the level it sits on — the observed percentage or mean on the crude side, the adjusted prediction on the model side. A continuous predictor has no levels, so its crude cell is the univariable slope, which assumes linearity: check that with
shapefirst.- n
How many people the table is about.
NULL(default) readsoptions(tabxplor.n)—"range", which adds anncolumn holding the unadjusted count behind each predictor level, on the model's own complete cases. Where several models rest on different people it prints the whole range (5 139-9 862), so an unequal base cannot pass unnoticed;"min"shows the smallest count only,"no"none. Continuous predictors are left blank: their count is the model N, the first footer row.- color, color_signif
Colouring of the effect cells.
color = "measure"(default,TRUEequivalently) grades each cell on its own measure, so the ladder follows what the column estimates;color = FALSEturns colouring off.color_signifis the significance policy —NULL(default) is"grey_non_signif"here, wheretab()defaults to"ignore".What is left to choose is what each effect is compared to.
coloris positional,c(text, background), socolor = c("measure", "adjustment")answers "how strong is this effect?" and "how much did the model change it?" in one glance:"adjustment"— how far each modelled effect sits from its observed (crude) counterpart: what adjusting for the other predictors did to it. It turnsempirical = TRUEon. Set its thresholds withset_color_breaks()(adj_ratio,adj_diff,adj_diff_std)."between_groups"— withtab_vars, how far each group's effect sits from the first group's: a per-predictor reading of effect modification.
The two are mutually exclusive, and each always tests its own gap: a gap whose interval covers zero is greyed whatever
color_signifsays — so a cell can be filled while neither estimate carries a star, which is correct rather than odd. A conditional odds ratio is not collapsible, so there the colours stay descriptive and are not tested. Read a coloured cell as "adjustment moved this effect", not as "this variable is a confounder". See the regression vignette.- stars
Logical (default
TRUEfor regression tables, where significance stars are standard). WhenFALSE, the per-cell p-value is dropped and no stars are shown (colours still read the interval).- ref
The reference every effect is measured from — one argument, one meaning per kind of predictor. For a factor it is the level the others are compared against (a level name, or
"first"(default) /"last"); for a continuous predictor the value it is anchored at (a number, or"mean"(default),"median","min","max").Anchoring a continuous predictor does not change its own effect — a slope is the same wherever you start reading it from — but it does move the Constant row; its own row says where the anchor sits,
per SD/13.5 (at mean/42.4). The default is the mean because zero is usually outside the data: nobody is 0 years old.ref,multiplierandshapeshare one grammar: a value on its own is the default for every predictor it can apply to, a named one overrides that variable —ref = c("median", "last", race = "Black").For the level of the outcome, see
outcome_level:refnames the level you compare AGAINST,outcome_levelthe one you MODEL.- multiplier
How a continuous predictor's effect is scaled — the unit its row reports. One unit is rarely a readable amount (a one-year change in
agebarely moves the odds), so the default is two standard deviations: roughly the span a binary predictor's own contrast covers, which is what makes a continuous row and a factor row comparable at a glance (Gelman 2008). Values:"2sd"(default),"sd", or a number of units (10= per decade). Same grammar asref:multiplier = c("sd", age = 10).The estimate, its interval and the observed companion all scale together; the p-value does not move. Because the default is not 1, a continuous predictor's
Model_*cell does not equalexp(coef(glm(...)))unless you passmultiplier = 1.- shape
How a continuous predictor enters the model, when one straight line is not enough. The
Linearityfooter row and the little curve drawn in the predictor'sncell tell you whether a line is enough; this argument is how you fix it without leaving the framework. Same grammar asmultiplierandref—shape = "quintiles"cuts every continuous predictor,shape = c(age = "quadratic")only that one, and anything unnamed stays linear:"linear"one slope (the default).
"quintiles"/"quartiles"/ an integerkcut into
kquantile groups, so the predictor becomes an ordinary factor: one estimate per group, its own observed companion, counts and colours per group — the non-linearity becomes visible in the printed numbers. Start here; it is the most readable answer."sd_bands"cut at the mean and one standard deviation either side — the classic low / average / high reading, whose cut points mean the same thing across sub-samples, where quantiles move with each one. The bands are not balanced: prefer quantiles when the group sizes matter.
"quadratic"adds a curvature term, so the predictor takes two rows — the slope at the mean, and whether it flattens or accelerates away from it.
"log"/"sqrt"fit
log(x)/sqrt(x)instead ofx— diminishing returns.
Example:
shape = c(age = "quadratic", income = "log"). The observed companion is fitted with the same shape, so the comparison stays like with like. It is the vocabularytab()takes (shape_numeric_var()) plus"quadratic", which is a model term.- stats
The statistics shown in the model-summary footer (one block per model).
"auto"(default) uses the per-family set — R square, adjusted R square, the overall F-test and the residual SD for a linear model, the likelihood-ratio test against the null model, McFadden's pseudo-R square, AIC and BIC otherwise — plus the default model checks (see below). A weighted model shows the survey-appropriate set. Pass a character vector to pick them:"n","lr_null","mcfadden_r2","aic","bic","phi","r2","r2_adj","f_model","sigma","global","interaction","group_interaction","linearity","proportionality","dispersion","influence","collinearity";"all"for everything, orNULL/FALSE/"no"to hide the footer.Model comparison happens by default wherever it means anything — when
predictorsis a list of several models. Where each nests in the next, every model is tested against the previous one; otherwise each against the first."compare_sequential"and"compare_baseline"(optionally naming the model) override that, and naming any footer statistic drops it.Three tests are asked for by name:
"global", one overall test per predictor — "is this variable associated with the outcome at all?", which a block of stars against a reference category cannot answer;"interaction", whether each crossed pair inpredictorsis real or the additive model is enough; and"group_interaction", one aggregated effect-modification test per predictor acrosstab_varsgroups.- conf_level
Confidence level for the intervals.
NULL(default) readsoptions(tabxplor.conf_level)— 0.95. It drives every interval, the significance stars, the greying undercolor_signifand the model-versus-observed gap interval, and each column records the level it was built at.- na
Which rows each model is fitted on — the grain at which missing values are dropped.
"drop_by_outcome"(default) gives every model of one outcome the same complete-case population, which is what makes the comparisons honest: the observed columns are computed on exactly the model's rows, and nested models get equal N."drop_by_model"lets each model use its own complete cases — more rows, at the price of comparability."drop_all"shares one population across the whole call."keep_for_predictors"drops nothing but a missing outcome: every predictor keeps its missing values as an ordinaryNAlevel, with its own row, count and effect — often the fastest way to find out whether non-response is itself patterned. A number has no level to put them in, so a numeric predictor that has any is cut into bands.- display
What each effect cell shows —
tab()'s display grammar, same names, same meaning, on every family and on the crude column as well as the model one.NULL(default) shows the plain estimate, or, withempirical, the estimate with the level it sits on beside it. The whole vocabulary — the named layouts, the{}templates and the per-token precision"{est:3} ({base:1})"— is in tabxplor-display; the ones this table uses most are"est_ci"(1/2.22*** [1/2.47;1/1.99]),"est_base"(1/2.22 (32.8%)),"est_coef"and"base_est_mdiff"/"base_est_mratio", which read the same comparison the other way. The Constant row holds the quantity the column's effects operate on, so it is read in one step: a baseline odds on an odds-ratio column, the level itself on an additive one.displayis post-hoc: every quantity it can name is already stored, so choosing a layout never triggers a computation and never changes a number —set_display()on a built table gives the same result. It never changes the estimand, which ismeasure's job alone.- digits
The number of decimals. A single integer sets every cell (
0, the default, means "each measure's own"), and a measure finer than the level it sits on keeps its own precision. Name a display field to set just that one, an aside included —digits = c(ratio = 3),digits = c(1, or = 3); a template may carry its own,display = "{est:3} ({base:1})". Left alone, a column reading in the outcome's own units (a mean, a mean difference) follows that outcome's magnitude, so a six-figure salary prints no decimals and a rate prints two;digits =always raises it back.- cleannames
Logical. If
TRUE, strips numeric prefixes from factor levels for display. UsesgetOption("tabxplor.cleannames")whenNULL.- subtext
Optional character. A note shown below the table.
- caption
A title for the table, stored on it and carried into every export. Without one a regression table titles itself from the model it shows.
- ...
One rarely-typed argument, plus internal plumbing.
ci_method— how the interval and p-value are computed: the same argument, and the same named-vector grammar, as intab(), whose fifth slot is this producer's."wald"(default) matches standard software output and is the only option for weighted models;"profile"uses the profile-likelihood interval and the likelihood-ratio test — more accurate near separation, unweighted binomial / poisson only.Every argument removed or renamed while
tab_reg()was in development is still accepted here, and gives an error naming its replacement rather than R's bare "unused argument". The dot-prefixed names are the jamovi live-cache plumbing, not user arguments.
Details
To learn what such a table says, read
Reading a
regression (vignette("tabxplor-reading-a-regression")); to look something up, the
regression vignette
(vignette("tabxplor-reg")).
New to regressions with tabxplor? A first model needs three arguments: data, outcome and
predictors. The model follows the outcome's type — a two-level factor gives logistic odds
ratios, a numeric a linear mean difference, a count Poisson rate ratios, a 3+ level
factor multinomial or ordinal odds ratios — so you rarely set family by hand.
The estimand is a cascade: family -> link -> measure -> effect, where "auto" means
follow from the left. family says what kind of number the outcome is; link which measure
the model estimates (a link is a measure, so it takes the same words); measure which one
is reported; effect where that number comes from. Set any one and everything to its right
re-derives, so most tables set none of them — and the one most people ever set is measure.
A coefficient exists only where the reported measure IS the model's own. Ask for another and
it is worked out from the model's predictions instead, averaged over the sample. So
measure = "ratio" on a binary outcome gives a marginal risk ratio from the logistic fit, while
link = "ratio" fits the modified Poisson and gives its conditional one — two different
quantities, and now two different arguments.
Model checks
Beside the fit statistics the footer carries five model checks, each naming an assumption and
the instrument that measured it: Linearity and Proportionality (p-values) say whether the
estimate means what it claims, Dispersion whether the intervals are wide enough,
Influence whether one respondent carries the result, Collinearity why the intervals are
wide. Four are shown by default; stats = "linearity" adds the fifth, and shape is the cure
for what it flags. reg_check_plots() draws them all. What each one asks, and how to read it:
the regression
vignette.
Out of scope
tab_reg() covers linear, logistic, Poisson, multinomial and ordinal models, with survey designs.
Three families of models are deliberately not supported, and are unlikely to be: survival /
Cox models, mixed / multilevel models, and pooling over multiply-imputed datasets. Fit
those with their own packages.
The header acronyms
A column header names the measure; the contrast is a marker on it —
no marker for a conditional effect, m for a marginal one, ref at the reference
profile — and measure = "log" wraps it (Model_mRR, Model_refRD,
Model_log(OR)). The observed companion carries the measure alone (Obs_RR).
OR— odds ratio (binomial, multinomial)cumOR— cumulative odds ratio (ordinal)RR— risk ratio (binomial, multinomial)RD— risk difference (binomial, multinomial)IRR— incidence-rate ratio (poisson)RoM— ratio of means (gaussian)diff— mean difference (gaussian, poisson)D— Somers' D (ordinal)WR— win ratio (ordinal)
References
Clogg, C. C., Petkova, E. & Haritou, A. (1995). Statistical Methods for Comparing Regression
Coefficients between Models. American Journal of Sociology, 100(5), 1261-1293 — the
comparison color = "adjustment" implements.
Zou, G. (2004). A Modified Poisson Regression Approach to Prospective Studies with Binary Data.
American Journal of Epidemiology, 159(7), 702-706 — link = "ratio".
Altman, D. G. & Bland, J. M. (2003). Interaction revisited: the difference between two estimates.
BMJ, 326, 219 — the color = "between_groups" test.
See also
reg_formulas() shows the formula each column was fitted with, and reg_measures()
what an outcome can be modelled as.
forest_plot() draws the finished table — every effect with its interval, its stars
and its colour, and (with empirical = TRUE) the observed effect beside it with the margin of
error of the gap. reg_check_plots() draws the model checks. tabxplor-display says what a
cell can show, tab() builds cross-tables.
Examples
# The shape table a continuous predictor draws under the footer is noise in an example:
.opt <- options(tabxplor.shape_table = "no")
# Logistic: the odds of being released, adjusted, beside the observed (crude) odds ratio.
tab_reg(car_arrests, "released", c("colour", "checks"))
#> ℹ "released": binary outcome detected -> `family = "binomial"` (logit).
#> This message is displayed once per session.
#> | predictors | Model fit | released |
#> |:---------------|:-----------------------------|---------:|
#> | colour, checks | N | 5 226 |
#> | | Dispersion (robust/model SE) | 1.02 |
#> | | Collinearity (max VIF) | 1.01 |
#> | | Influence (max dfbetas) | 0.06 |
#> | | LR vs null | <0.01% |
#> | | McFadden R2 | 0.076 |
#> | | AIC | 4 420 |
#> | | BIC | 4 440 |
#>
#> # A tabxplor tab: 4 × 5
#> # Outcome: released
#> # Groups: var [3]
#> var levels n Obs_OR Model_OR
#> <n> <(obs%) OR> <OR (adj%)>
#> 1 Constant Reference profile 6.51*** (87%)
#>
#> 2 colour White 3 938 (86%) 1 1 (85%)
#> 3 colour Black 1 288 (74%) 1/2.11*** 1/1.72*** (77%)
#>
#> 4 checks per 3.08 (2SD), at 1.64 (mean) 1/3.71*** 1/3.47***
#> # Model: logistic regression; OR: odds ratio (vs the reference category); obs%: observed proportion; adj%: adjusted/predicted proportion.
#> # Obs_OR, Model_OR: OR (ref.): 1/4 1/2 1/1.5 1/1.2 1.2 1.5 2 4 [grey: non-significant or under ×1.2]
#> # ***: significantly different from the reference category (in bold) at the 99% confidence level (from 1 for the Constant); **: at the 95% level; *: at the 90% level; no star: not significant.
# \donttest{
# Linear: a mean difference in dollars.
tab_reg(car_salaries, "salary", c("sex", "discipline", "rank"))
#> | predictors | Model fit | salary |
#> |:-----------------|:-----------------------------|----------:|
#> | sex, discipline, | N | 397 |
#> | rank | Dispersion (robust/model SE) | 1.00 |
#> | | Collinearity (max VIF) | 1.02 |
#> | | Influence (max dfbetas) | 0.22 |
#> | | F | <0.01% |
#> | | R2 | 0.447 |
#> | | Adjusted R2 | 0.441 |
#> | | Residual SD | 22 640.99 |
#>
#> # A tabxplor tab: 8 × 5
#> # Outcome: salary
#> # Groups: var [4]
#> var levels n Obs_diff Model_diff
#> <n> <(obs mean) diff> <diff (adj mean)>
#> 1 Constant Reference profile 6 68 224
#>
#> 2 sex Female 39 (101 002) 0 0 (109 656)
#> 3 sex Male 358 (115 090) +14 088*** +4 492 (114 148)
#>
#> 4 discipline A 181 (108 548) 0 0 (106 248)
#> 5 discipline B 216 (118 029) +9 480*** +13 709*** (119 957)
#>
#> 6 rank AsstProf 67 ( 80 776) 0 0 ( 79 733)
#> 7 rank AssocProf 64 ( 93 876) +13 100*** +13 723*** ( 93 456)
#> 8 rank Prof 266 (126 772) +45 996*** +47 403*** (127 136)
#> # Model: linear regression; diff: mean difference (vs the reference category); obs mean: observed mean; adj mean: adjusted/predicted mean.
#> # Obs_diff, Model_diff: diff in SD (ref.): -0.8 -0.4 -0.2 -0.1 +0.1 +0.2 +0.4 +0.8 [grey: non-significant or under ±0.1 SD]
#> # ***: significantly different from the reference category (in bold) at the 99% confidence level; **: at the 95% level; *: at the 90% level; no star: not significant.
# A count outcome: incidence-rate ratios.
tab_reg(car_arrests, "checks", c("colour", "employed"), family = "poisson")
#> | predictors | Model fit | checks |
#> |:-----------------|:-----------------------------|-------:|
#> | colour, employed | N | 5 226 |
#> | | Dispersion (robust/model SE) | 1.23 |
#> | | Pearson dispersion (phi) | 1.40 |
#> | | Collinearity (max VIF) | 1.02 |
#> | | Influence (max dfbetas) | 0.07 |
#> | | LR vs null | <0.01% |
#> | | McFadden R2 | 0.030 |
#> | | AIC | 18 058 |
#> | | BIC | 18 078 |
#>
#> # A tabxplor tab: 5 × 5
#> # Outcome: checks
#> # Groups: var [3]
#> var levels n Obs_IRR Model_IRR
#> <n> <(obs mean) ratio> <ratio (adj mean)>
#> 1 Constant Reference profile 3 200 1.3
#>
#> 2 colour White 3 938 (1.5) 1 1 (1.5)
#> 3 colour Black 1 288 (2.1) ×1.41*** ×1.34*** (2.0)
#>
#> 4 employed Yes 4 111 (1.4) 1 1 (1.5)
#> 5 employed No 1 115 (2.4) ×1.63*** ×1.57*** (2.3)
#> # Model: Poisson regression; IRR: incidence-rate ratio (vs the reference category); obs mean: observed mean; adj mean: adjusted/predicted mean.
#> # Obs_IRR, Model_IRR: IRR (ref.): ÷4 ÷2 ÷1.15 ×1.15 ×2 ×4 [grey: non-significant or under ×1.15]
#> # ***: significantly different from the reference category (in bold) at the 99% confidence level; **: at the 95% level; *: at the 90% level; no star: not significant.
# `measure` reports another measure WITHOUT changing the model: a MARGINAL risk ratio,
# averaged over the sample, still from the logistic fit.
tab_reg(car_arrests, "released", c("colour", "checks"), measure = "ratio")
#> | predictors | Model fit | released |
#> |:---------------|:-----------------------------|---------:|
#> | colour, checks | N | 5 226 |
#> | | Dispersion (robust/model SE) | 1.02 |
#> | | Collinearity (max VIF) | 1.01 |
#> | | Influence (max dfbetas) | 0.06 |
#> | | LR vs null | <0.01% |
#> | | McFadden R2 | 0.076 |
#> | | AIC | 4 420 |
#> | | BIC | 4 440 |
#>
#> # A tabxplor tab: 4 × 5
#> # Outcome: released
#> # Groups: var [3]
#> var levels n Obs_RR Model_mRR
#> <n> <(obs%) ratio> <ratio (adj%)>
#> 1 Constant Population average 5 226 83%
#>
#> 2 colour White 3 938 (86%) 1 1 (85%)
#> 3 colour Black 1 288 (74%) ÷1.16*** ÷1.10*** (77%)
#>
#> 4 checks per 3.08 (2SD), at 1.64 (mean) ÷1.40*** ÷1.36***
#> # Model: logistic regression; mRR: marginal risk ratio (the ratio of adjusted proportions, sample-averaged); obs%: observed proportion; adj%: adjusted/predicted proportion.
#> # Obs_RR, Model_mRR: RR (ref.): ×2 [grey: non-significant or under ×2]
#> # ***: significantly different from the reference category (in bold) at the 99% confidence level; **: at the 95% level; *: at the 90% level; no star: not significant.
# `link` changes the model: the CONDITIONAL risk ratio of a modified-Poisson fit.
tab_reg(car_arrests, "released", c("colour", "checks"), link = "ratio")
#> | predictors | Model fit | released |
#> |:---------------|:-----------------------------|---------:|
#> | colour, checks | N | 5 226 |
#> | | Dispersion (robust/model SE) | 1.00 |
#> | | Collinearity (max VIF) | 1.02 |
#> | | Influence (max dfbetas) | 0.06 |
#> | | Wald vs null | <0.01% |
#>
#> # A tabxplor tab: 4 × 5
#> # Outcome: released
#> # Groups: var [3]
#> var levels n Obs_RR Model_RR
#> <n> <(obs%) ratio> <ratio (adj%)>
#> 1 Constant Reference profile 84%
#>
#> 2 colour White 3 938 (86%) 1 1 (85%)
#> 3 colour Black 1 288 (74%) ÷1.16*** ÷1.11*** (77%)
#>
#> 4 checks per 3.08 (2SD), at 1.64 (mean) ÷1.26*** ÷1.24***
#> # Model: modified Poisson regression; RR: risk ratio (vs the reference category); obs%: observed proportion; adj%: adjusted/predicted proportion.
#> # Obs_RR, Model_RR: RR (ref.): ×2 [grey: non-significant or under ×2]
#> # ***: significantly different from the reference category (in bold) at the 99% confidence level; **: at the 95% level; *: at the 90% level; no star: not significant.
# A named list of predictor sets: one column per model, compared in the footer.
tab_reg(car_salaries, "salary",
list("sex alone" = "sex",
"+ field" = c("sex", "discipline"),
"+ rank" = c("sex", "discipline", "rank")),
empirical = FALSE)
#> | Model fit | sex alone | | + field | | + rank |
#> |:-----------------------------|----------:|:-:|----------:|:-:|----------:|
#> | N | 397 | | 397 | | 397 |
#> | Dispersion (robust/model SE) | 0.87 | | 1.00 | | 1.00 |
#> | Collinearity (max VIF) | | | 1.00 | | 1.02 |
#> | Influence (max dfbetas) | 0.32 | | 0.29 | | 0.22 |
#> | F | 0.567% | | 0.0159% | | <0.01% |
#> | R2 | 0.019 | | 0.043 | | 0.447 |
#> | Adjusted R2 | 0.017 | | 0.039 | | 0.441 |
#> | Residual SD | 30 034.61 | | 29 699.35 | | 22 640.99 |
#> | F vs previous | | | 0.172% | | <0.01% |
#>
#> # A tabxplor tab: 8 × 6
#> # Outcome: salary
#> # Groups: var [4]
#> var levels n `sex alone` `+ field` `+ rank`
#> <n_range> <diff> <diff> <diff>
#> 1 Constant Reference profile 6-39 101 002 95 914 68 224
#>
#> 2 sex Female 39 0 0 0
#> 3 sex Male 358 +14 088*** +14 029*** +4 492
#>
#> 4 discipline A 181 0 0
#> 5 discipline B 216 +9 449*** +13 709***
#>
#> 6 rank AsstProf 67 0
#> 7 rank AssocProf 64 +13 723***
#> 8 rank Prof 266 +47 403***
#> # Model: linear regression of salary; diff: mean difference (vs the reference category).
#> # diff in SD (ref.): -0.8 -0.4 -0.2 -0.1 +0.1 +0.2 +0.4 +0.8 [grey: non-significant or under ±0.1 SD]
#> # ***: significantly different from the reference category (in bold) at the 99% confidence level; **: at the 95% level; *: at the 90% level; no star: not significant.
# A continuous predictor cut into groups, on French survey data:
tab_reg(questionr_hdv, "cinema", c("qualif", "age"), shape = c(age = "quartiles"))
#> ℹ "cinema": binary outcome detected -> `family = "binomial"` (logit).
#> This message is displayed once per session.
#> | predictors | Model fit | cinema |
#> |:------------|:-----------------------------|-------:|
#> | qualif, age | N | 1 653 |
#> | | Dispersion (robust/model SE) | 1.07 |
#> | | Collinearity (max VIF) | 1.03 |
#> | | Influence (max dfbetas) | 0.22 |
#> | | LR vs null | <0.01% |
#> | | McFadden R2 | 0.160 |
#> | | AIC | 1 904 |
#> | | BIC | 1 958 |
#>
#> # A tabxplor tab: 12 × 5
#> # Outcome: cinema
#> # Groups: var [3]
#> var levels n Obs_OR Model_OR
#> <n> <(obs%) OR> <OR (adj%)>
#> 1 Constant Reference profile 49 6.26*** (86%)
#>
#> 2 qualif Cadre 260 (65%) 1 1 (67%)
#> 3 qualif Ouvrier specialise 203 (22%) 1/6.63*** 1/9.39*** (23%)
#> 4 qualif Ouvrier qualifie 292 (25%) 1/5.67*** 1/7.72*** (26%)
#> 5 qualif Technicien 86 (43%) 1/2.50*** 1/3.73*** (40%)
#> 6 qualif Profession intermediaire 160 (46%) 1/2.25*** 1/2.76*** (47%)
#> 7 qualif Employe 594 (44%) 1/2.39*** 1/3.40*** (42%)
#> 8 qualif Autre 58 (47%) 1/2.17*** 1/3.28*** (43%)
#>
#> 9 age 18 to 34 368 (62%) 1 1 (62%)
#> 10 age 35 to 47 457 (55%) 1/1.33** 1/1.43** (54%)
#> 11 age 48 to 59 432 (32%) 1/3.39*** 1/3.90*** (32%)
#> 12 age 60 to 97 396 (18%) 1/7.37*** 1/9.45*** (18%)
#> # Model: logistic regression; OR: odds ratio (vs the reference category); obs%: observed proportion; adj%: adjusted/predicted proportion.
#> # Obs_OR, Model_OR: OR (ref.): 1/4 1/2 1/1.5 1/1.2 1.2 1.5 2 4 [grey: non-significant or under ×1.2]
#> # ***: significantly different from the reference category (in bold) at the 99% confidence level (from 1 for the Constant); **: at the 95% level; *: at the 90% level; no star: not significant.
# }
options(.opt)