---
title: "table_or - Publication-ready odds ratio tables"
vignette: >
  %\VignetteIndexEntry{table_or - publication-ready odds ratio tables}
  %\VignetteEngine{quarto::html}
  %\VignetteEncoding{UTF-8}
knitr:
  opts_chunk:
    collapse: true
    comment: '#>'
---

```{r}
#| label: setup
library(plotor)
set.seed(123) # reproducibility
```

## Overview

`table_or()` automates the creation of publication-ready odds ratio tables from logistic regression models. This vignette shows how to:

- Generate **programmatic tibble output** for downstream analysis and reporting

- Create **formatted HTML tables** with {gt} for manuscripts and reports

- **Customise** confidence levels, anonymisation and styling

- **Export** tables for publication

## When to use this function

Use `table_or()` when you need to:

- Present logistic regression results in a standardised, publication-ready format

- Create tables that comply with reporting guidelines, (e.g., STROBE guidelines for observational studies)

- Combine or compare results across multiple models

- Ensure consistent interpretation guidance for readers (via footnotes)

- Balance transparency with data privacy (via anonymisation options)

## Quick example - minimal workflow
```{r}
#| label: model
# create a small example dataset
rows <- 400
df <- data.frame(
  outcome = rbinom(n = rows, size = 1, prob = 0.25) |> 
    factor(labels = c("Healthy", "Disease")),
  age = rnorm(n = rows, mean = 50, sd = 12),
  sex = sample(x = 0:1, size = rows, replace = TRUE) |> 
    factor(labels = c("Female", "Male")),
  smoke = sample(x = 0:2, size = rows, replace = TRUE) |> 
    factor(labels = c("Never", "Former", "Current"))
)

# fit a logistic regression model
m <- glm(
  formula = outcome ~ age + sex + smoke,
  family = "binomial",
  data = df
)
```

## Programmatic output (tibble)

Use the tibble output for downstream manipulation, reporting or combining results across models.

```{r}
#| label: tibble

table_or(m, output = "tibble")
```

Key columns returned: 

- **label**: Variable name or predictor group (e.g., "age", "sex", "smoke")

- **level**: Specific level or term shown for the row (numeric variable name or factor level label)

- **rows**: Number of observations used to estimate the row (rows in the model / data subset for that term)

- **outcome**: Count of outcome events (cases) observed for that row / level

- **outcome_rate**: Proportion of observations with the outcome (outcome / rows)

- **class**: Data type of the predictor shown in this row (e.g., "numeric", "factor")

- **estimate**: Model coefficient on the link (log-odds) scale; NA for comparator / reference rows

- **std.error**: Standard error of the coefficient estimate

- **statistic**: Test statistic for the coefficient (e.g., z or t value from the model)

- **p.value**: Two-sided p-value for the coefficient test

- **conf.low**: Lower bound of the confidence interval for the odds ratio (exponentiated coefficient)

- **conf.high**: Upper bound of the confidence interval for the odds ratio (exponentiated coefficient)

- **signfiicance**: Human-readable summary of statistical evidence (e.g., "Not significant", "Significant" or "Comaparator")

- **comparator**: Indicates reference / comparator rows (e.g., "1" for the first level of factors)

Estimates are shown as coefficients on the log-odds scale (estimate / std.error / statistic / p.value) with confidence intervals presented for exponentiated results (conf.low / conf.high).

### Interpreting the results

- **OR > 1**: increased odds of the outcome

- **OR < 1**: decreased odds of the outcome

- **OR = 1**: No association

- **Confidence interval crosses 1.0**: not statistically significant

## Formatted HTML table (gt)

Create a publication-ready table using gt formatting.
```{r}
#| label: gt

table_or(m, output = "gt")
```

### What the gt output includes

The HTML table includes:

- **Formatted odds ratios** with confidence intervals

- **Mini forest plot** visualising effect sizes

- **Comprehensive footnotes** that help readers interpret results

### Understanding the footnotes

The footnotes clarify:

- **Interpretation of OR values**: explaining that values below 1 indicate inverse relationships and above 1 indicate positive relationships

- **Variable type handling**: showing how categorical variables (reference vs comparison levels) and numeric variables (per-unit change) are presented differently

- **Significance rule**: making clear that confidence intervals crossing 1.0 are presented differently

- **Precision**: specifying that values are shown to 4 significant figures

- **Metric definitions**: ensureing readers understand OR, SE, p-value and CI without external references


## Common customisations

### Change confidence level

Report 90% confidence intervals for sensitivity analysis or different reporting standards:

```{r}
#| label: customise - confidence level

table_or(m, output = "tibble", conf_level = 0.90)
```

### Anonymise counts for sensitive data

Improve data privacy by rounding counts to the nearest five and suppressing counts below ten. This is useful when working with sensitive dataset under strict information governance requirements:

```{r}
#| label: customise - anonymise counts

table_or(m, output = "tibble", anonymise_counts = TRUE)
```

### Combine results from multiple models

Compare models by binding tibble outputs:

```{r}
#| label: customise - combine

# fit a second model
m2 <- glm(
  formula = outcome ~ age + sex,
  family = "binomial",
  data = df
)

# combine results
combined_results <-
  dplyr::bind_rows(
    dplyr::bind_cols(model = "Model 1", table_or(m)),
    dplyr::bind_cols(model = "Model 2", table_or(m2))
  )

head(combined_results)
```

## Exporting tables

### Export to HTML file

```{r}
#| label: export - html
#| eval: false

gt_table <- table_or(m, output = "gt")
gt::gtsave(data = gt_table, filename = "odds_ratios.html")
```

### Export to Word document

```{r}
#| label: export - word
#| eval: false

gt_table <- table_or(m, output = "gt")
gt::gtsave(data = gt_table, filename = "odds_ratios.docx")
```

### Export to CSV (tibble)

```{r}
#| label: export - csv
#| eval: false

readr::write_csv(x = table_or(m), file = "odds_ratios.csv")
```

### Tips for publication

- **Choose your output format wisely**: use "tibble" for flexibility and downstream analysis; use "gt" for direct inclusion in manuscripts or reports

- **Select relevant columns**: not all columns are needed for publication; consider your audience and journal requirements

- **Check the confidence interval rule**: always verify that your signifiance conslusions match the CI crossing rule (CI does not cross 1.0 = significant)

- **Report the confidence level**: specify whether you're using 95% (default), 90% or another confidence level

- **Use anonymisation for sensitive data**: when sharing tables with restricted data, use `anonymise_counts = TRUE`

## Conclusion

The `table_or()` function automates the creation of publication-ready odds ratio tables from logistic regression models, eliminating manual calculation and formatting while ensuring consistent presentation of results with appropriate statistical annotations.

## See also

- `vignette("plot_or")` - detailed plotting options and themes

- `vignette("check_or")` - diagnostics and case studies

- `gt::gt()` - formatted table creation
