Fit the direct CIF regression, then pass the result to
tbl_regression(). The example uses the anonymized diabetes
cohort from the overview. Effects compare low fruit intake with the
reference group at 8 years; age and sex enter the nuisance model. See
the direct regression vignette for model assumptions and estimation
details.
library(cifmodeling)
library(gtsummary)
data(diabetes.complications)
report_data <- diabetes.complications
report_data$fruitq1 <- factor(report_data$fruitq1, levels = c(0, 1),
labels = c("Other intake", "Low intake"))
attr(report_data$fruitq1, "label") <- "Fruit intake"
fit <- polyreg(Event(t, epsilon) ~ age + sex, exposure = "fruitq1",
code.exposure.ref = "Other intake", data = report_data, time.point = 8,
effect.measure1 = "RR", effect.measure2 = "RR")
retinopathy_table <- tbl_regression(fit, exponentiate = TRUE)
retinopathy_table| Characteristic | RR1 | 95% CI | p-value |
|---|---|---|---|
| Fruit intake | |||
| Other intake | — | — | |
| Low intake | 1.42 | 1.17, 1.73 | <0.001 |
| 1 RR for event 1 at time 8 | |||
| Abbreviation: CI = Confidence Interval | |||
The default event is event 1, diabetic retinopathy. The table reports exponentiated effect estimates and their saved confidence limits. Standard errors and test statistics remain on the coefficient’s log scale. The reference row describes the contrast; it is not an additional estimated coefficient. These observational estimates do not by themselves establish a causal effect of fruit intake.
Select event 2 explicitly to report macrovascular complications. The numeric results, exposure labels and effect-measure heading all follow the selected event.
macrovascular_table <- tbl_regression(fit, exponentiate = TRUE, event = "event2")
tbl_merge(list(retinopathy_table, macrovascular_table),
tab_spanner = c("**Retinopathy**", "**Macrovascular complications**"))| Characteristic |
Retinopathy
|
Macrovascular complications
|
||||
|---|---|---|---|---|---|---|
| RR1 | 95% CI | p-value | RR2 | 95% CI | p-value | |
| Fruit intake | ||||||
| Other intake | — | — | — | — | ||
| Low intake | 1.42 | 1.17, 1.73 | <0.001 | 1.03 | 0.61, 1.73 | >0.9 |
| 1 RR for event 1 at time 8 | ||||||
| 2 RR for event 2 at time 8 | ||||||
| Abbreviation: CI = Confidence Interval | ||||||
For a tidy data frame containing both events, use
generics::tidy(fit, event = "both"). Publication regression
tables select one event at a time and are combined with
tbl_merge().
Choose the effect measure during estimation, not while formatting the
table. RR compares cumulative incidence probabilities, OR compares their
odds, and SHR is the subdistribution hazard ratio parameterization. At a
fixed time, the latter is the ratio of -log(1 - CIF)
values; it is not a cause-specific hazard ratio. The following tables
use the same exposure comparison and 8-year target, with three different
effect-measure models.
fit_or <- polyreg(Event(t, epsilon) ~ age + sex, exposure = "fruitq1",
code.exposure.ref = "Other intake", data = report_data, time.point = 8,
effect.measure1 = "OR", effect.measure2 = "OR")
fit_shr <- polyreg(Event(t, epsilon) ~ age + sex, exposure = "fruitq1",
code.exposure.ref = "Other intake", data = report_data, time.point = 8,
effect.measure1 = "SHR", effect.measure2 = "SHR")
tbl_merge(list(tbl_regression(fit, exponentiate = TRUE),
tbl_regression(fit_or, exponentiate = TRUE),
tbl_regression(fit_shr, exponentiate = TRUE)),
tab_spanner = c("**RR model**", "**OR model**", "**SHR model**"))| Characteristic |
RR model
|
OR model
|
SHR model
|
||||||
|---|---|---|---|---|---|---|---|---|---|
| RR1 | 95% CI | p-value | OR2 | 95% CI | p-value | SHR3 | 95% CI | p-value | |
| Fruit intake | |||||||||
| Other intake | — | — | — | — | — | — | |||
| Low intake | 1.42 | 1.17, 1.73 | <0.001 | 1.66 | 1.23, 2.24 | <0.001 | 1.53 | 1.20, 1.95 | <0.001 |
| 1 RR for event 1 at time 8 | |||||||||
| 2 OR for event 1 at time 8 | |||||||||
| 3 SHR for event 1 at time 8 | |||||||||
| Abbreviation: CI = Confidence Interval | |||||||||
The two events can also use different effect measures. Headings are
read from the fitted estimand information; no effect
measure is inferred from the size of a coefficient.
fit_mixed <- polyreg(Event(t, epsilon) ~ age + sex, exposure = "fruitq1",
code.exposure.ref = "Other intake", data = report_data, time.point = 8,
effect.measure1 = "RR", effect.measure2 = "SHR")
tbl_merge(list(tbl_regression(fit_mixed, exponentiate = TRUE),
tbl_regression(fit_mixed, exponentiate = TRUE, event = "event2")),
tab_spanner = c("**Retinopathy**", "**Macrovascular complications**"))| Characteristic |
Retinopathy
|
Macrovascular complications
|
||||
|---|---|---|---|---|---|---|
| RR1 | 95% CI | p-value | SHR2 | 95% CI | p-value | |
| Fruit intake | ||||||
| Other intake | — | — | — | — | ||
| Low intake | 1.42 | 1.17, 1.73 | <0.001 | 1.03 | 0.60, 1.77 | >0.9 |
| 1 RR for event 1 at time 8 | ||||||
| 2 SHR for event 2 at time 8 | ||||||
| Abbreviation: CI = Confidence Interval | ||||||
With unchanged inference settings, the table extracts the fitted
intervals. This also applies to stored bootstrap intervals: they are not
replaced by Wald limits during exponentiation. To retain the fitted
confidence level explicitly, pass
conf.level = fit$conf.int. A request for a different level
uses the existing supported reconstruction, or fails if the saved method
cannot provide that level without refitting, as with BCa limits.
tbl_regression(fit, exponentiate = TRUE, conf.level = fit$conf.int,
label = list(fruitq1 ~ "Low fruit intake versus other intake"))| Characteristic | RR1 | 95% CI | p-value |
|---|---|---|---|
| Low fruit intake versus other intake | |||
| Other intake | — | — | |
| Low intake | 1.42 | 1.17, 1.73 | <0.001 |
| 1 RR for event 1 at time 8 | |||
| Abbreviation: CI = Confidence Interval | |||
For direct extraction, generics::tidy(fit) retains
log-scale estimates. Use exponentiate = TRUE for ratios.
The broom convention uses logical conf.int and numeric
conf.level; the older numeric conf.int
argument remains accepted by tidy.polyreg() for
compatibility. There is no need to modify the saved fit or supply a
custom tidier to produce these tables.
Use the standard gtsummary conversions. Replace the temporary filenames with the intended destination when saving the final report.