Skip to contents

Fits one model per candidate predictor (the univariable screen) and renders them as a single table with one row block per predictor. With multivariable = TRUE (default), the full model containing all predictors is merged side by side under "Univariable" / "Multivariable" column groups – the standard presentation of applied epidemiology (the gtsummary::tbl_uvregression() + tbl_merge() workflow).

Usage

table_regression_uv(
  data,
  outcome,
  predictors,
  method = c("lm", "glm", "coxph"),
  family = stats::binomial(),
  multivariable = TRUE,
  complete_cases = FALSE,
  show_columns = c("n", "b", "ci", "p"),
  show_intercept = FALSE,
  title = NULL,
  ...
)

Arguments

data

A data frame.

outcome

The outcome column (unquoted name, tidyselect). For method = "coxph", a Surv(time, status) expression evaluated in data (the tbl_uvregression convention).

predictors

Candidate predictor columns (tidyselect, e.g. c(age, sex, education) or where(is.numeric)). The outcome column(s) are dropped from the selection automatically.

method

"lm" (default), "glm", or "coxph" (requires the survival package; estimates render as HRs with exponentiate = TRUE).

family

A stats::family for method = "glm", in any of the three forms stats::glm() accepts: a family object (binomial()), its name ("binomial"), or the bare constructor (binomial). Default binomial(), so method = "glm" alone is the logistic screen; supplying family without method selects the glm screen directly (a family can only mean that). Refused for method = "coxph", and gaussian() with the identity link is refused too: use method = "lm" for the linear screen. With method = "lm", any non-gaussian family is refused the same way (use method = "glm"), and a supplied gaussian() is ignored with a classed warning – the linear screen already fits it.

multivariable

Logical, default TRUE: merge the full model (all predictors together) as a second column group.

complete_cases

Logical, default FALSE. TRUE restricts ALL models to the rows complete on outcome + every predictor (common-sample comparison); the reduction is disclosed in the table note.

show_columns

Passed to table_regression(). Default c("n", "b", "ci", "p") – the tbl_uvregression column set; "n" is the per-predictor sample size. The multivariable group carries no N column (its single n is a fit-statistics row, as in the reference layouts). For binary outcomes, add "n_events" for outcome event counts as events/N per factor level (each column group counts on its own estimation sample). For method = "lm", add "r2" (and/or "adj_r2") for the share of outcome variance each predictor explains on its own – see Variance explained below. For method = "coxph", the RMST / risk-difference families ("rmst", "risk_diff", ...) work with an explicit numeric tau / at_time shared by every column: each univariable fit runs its own boot_n-replicate bootstrap, and the multivariable group reports the covariate-adjusted estimand from the full fit. tau = "minmax" is refused (per-fit horizons would make the column incomparable across predictors).

show_intercept

Display the (Intercept) rows? Default FALSE – the opposite of table_regression()'s default, because each univariable fit carries its own nuisance intercept. See Intercepts.

title

Table title; NULL (default) builds "Univariable and multivariable <type> regression: <outcome>".

...

Passed to table_regression() (exponentiate, vcov, cluster, p_adjust, digits, labels, output, ...). nested is not meaningful for a screen and is refused. cluster must be a single vector with one value per row of data; it is aligned to each fit's own estimation sample automatically.

Value

See table_regression() (same output contract).

Sample sizes

By default each univariable model is fit on its own complete cases, so N varies across predictors – that is what the N column discloses (shown on the first row of each block), and a table note states it whenever the Ns differ. The multivariable model is fit on the complete cases of all its variables (its n appears in the fit-statistics rows). Pass complete_cases = TRUE to restrict every model – univariable and multivariable – to the common complete-case sample.

Variance explained

show_columns = c("n", "b", "ci", "p", "r2") adds an \(R^2\) column to the screen (method = "lm"): each predictor block reports its own model's \(R^2\), on the first row of the block like N. It answers what a coefficient and its interval cannot – how much of the outcome the predictor accounts for – and often shows that a firmly established association still explains a small share of the variance. Add "adj_r2" for the adjusted form. On the multivariable side the \(R^2\) is one number for the whole model, so it stays in the fit-statistics rows (where it is shown by default) instead of being repeated down a column. Not available for method = "glm" or "coxph": outside least squares only competing pseudo-\(R^2\) measures exist, and spicy asks you to name the one you want (show_fit_stats = "pseudo_r2_mcfadden").

Multiplicity

p_adjust (passed through to table_regression()) treats the whole univariable screen as ONE family (all screened coefficients together); the multivariable model is its own family, as in any multi-model table.

Why the default screen is linear

The default method = "lm" fits the linear screen: R's canonical model, and – when the outcome is continuous – the estimand with the most direct reading. If the outcome looks binary under this default, the screen proceeds as a linear probability model and says so in a classed warning: LPM coefficients are probability differences, comparable across models and samples in a way that odds ratios are not (Mood, 2010), but the model's built-in heteroskedasticity calls for vcov = "HC3". A two-level factor (or logical) outcome is coded 0/1 on its second level – the glm convention – and the warning names the modeled probability; an outcome with more observed levels is refused (a multinomial outcome has no linear screen). The classical epidemiological screen is one argument away: method = "glm" (with the default family = binomial()) gives the logistic screen, and supplying any family selects the glm screen directly.

Intercepts

Hidden by default on both sides (each univariable fit has its own nuisance intercept), matching gtsummary::tbl_regression()'s intercept = FALSE default. Pass show_intercept = TRUE to display them: each univariable block then opens with its own fit's (Intercept) row, and the multivariable model shows its intercept as in any table_regression() table.

References

Batra, N. et al. (Eds.) (2021). The Epidemiologist R Handbook, Univariate and multivariable regression. https://epirhandbook.com/en/new_pages/regression.html

Mood, C. (2010). Logistic regression: Why we cannot do what we think we can do, and what we can do about it. European Sociological Review, 26(1), 67-82. doi:10.1093/esr/jcp006

Sjoberg, D.D., Whiting, K., Curry, M., Lavery, J.A., & Larmarange, J. (2021). Reproducible summary tables with the gtsummary package. The R Journal, 13(1), 570-580.

Examples

# \donttest{
table_regression_uv(
  sochealth,
  outcome    = smoking,
  predictors = c(age, sex, education),
  family     = binomial(),
  exponentiate = TRUE
)
#> Ordered factor(s) detected. Polynomial contrasts (the R default for `ordered()`) decompose the factor into orthogonal trend components: `.L` = linear, `.Q` = quadratic, `.C` = cubic, `^k` = degree k. Coefficients are trends across the ordered levels, NOT per-level effects against a reference.
#>  To display per-level (treatment) effects, refit with `factor(x, ordered = FALSE)` or set `options(contrasts = c("contr.treatment", "contr.treatment"))`.
#> This message is displayed once per session.
#> Univariable and multivariable logistic regression: smoking
#> 
#>                              Univariable                Multivariable     
#>                    ───────────────────────────────  ───────────────────── 
#>  Variable          N     OR      95% CI       p      OR        95% CI    
#> ─────────────────┼────────────────────────────────────────────────────────
#>  age              1175  1.01  [1.00, 1.01]   .292     1.01  [1.00, 1.02] 
#>  sex:                                                                    
#>    Female (ref.)     –   –         –         –         –         –       
#>    Male           1175  0.95  [0.72, 1.26]   .713     0.96  [0.73, 1.28] 
#>  education:                                                              
#>    .L             1175  0.53  [0.40, 0.70]  <.001     0.53  [0.40, 0.69] 
#>    .Q                   1.03  [0.81, 1.29]   .832     1.02  [0.81, 1.29] 
#> ╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌
#>  n                                                 1175                  
#>  R² (McFadden)                                        0.02               
#>  R² (Nagelkerke)                                      0.03               
#>  AIC                                               1200.9                
#> 
#>                    Multi… 
#>                    ────── 
#>  Variable         p (OR) 
#> ─────────────────┼────────
#>  age                .214 
#>  sex:                    
#>    Female (ref.) 
#>    Male             .800 
#>  education:              
#>    .L              <.001 
#>    .Q               .852 
#> 
#> Note. Logistic regression models.
#> Std. errors: classical (Fisher information).
#> OR = odds ratio.
#> Coefficients exponentiated and displayed as OR; CI bounds exponentiated.
#> Ordered factor `education`: polynomial trends (.L = linear, .Q = quadratic).

# Linear screen with the share of variance each predictor
# explains on its own (the multivariable model reports its own
# R-squared in the fit-statistics rows).
table_regression_uv(
  sochealth,
  outcome      = wellbeing_score,
  predictors   = c(age, sex, bmi),
  show_columns = c("n", "b", "ci", "p", "r2")
)
#> Univariable and multivariable linear regression: wellbeing_score
#> 
#>                                  Univariable                 Multiv… 
#>                    ────────────────────────────────────────  ─────── 
#>  Variable          N      B        95% CI        p     R²      B    
#> ─────────────────┼───────────────────────────────────────────────────
#>  age              1200   0.04  [-0.02,  0.10]   .177  0.00     0.07 
#>  sex:                                                               
#>    Female (ref.)     –    –          –          –      –        –   
#>    Male           1200   3.89  [ 2.13,  5.64]  <.001  0.02     4.27 
#>  bmi              1188  -0.60  [-0.83, -0.36]  <.001  0.02    -0.67 
#> ╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌
#>  n                                                          1188    
#>                                              0.04 
#>  Adj. R²                                                       0.04 
#> 
#>                        Multivariable     
#>                    ───────────────────── 
#>  Variable           95% CI (B)    p (B) 
#> ─────────────────┼───────────────────────
#>  age              [ 0.01,  0.13]   .023 
#>  sex:                                   
#>    Female (ref.)        –          –    
#>    Male           [ 2.52,  6.02]  <.001 
#>  bmi              [-0.91, -0.44]  <.001 
#> 
#> Note. Linear regression models.
#> Std. errors: classical (OLS).
#> Each univariable model is fit on its own complete cases; N varies by predictor (1188-1200).
# }