---
title: "Start here: a simple gtstats workflow"
description: "Understand data, make a publication-ready descriptive table, and compare groups."
output: rmarkdown::html_vignette
vignette: >
  %\VignetteIndexEntry{Start here: a simple gtstats workflow}
  %\VignetteEngine{knitr::rmarkdown}
  %\VignetteEncoding{UTF-8}
---

```{r setup, include=FALSE}
knitr::opts_chunk$set(collapse = TRUE, comment = "#>", eval = TRUE)
library(gtstats)
```

# The workflow

gtstats is designed around one practical sequence:

1. **Understand** the data with `describe_data()`.
2. **Assess** selected continuous variables with `assess_distribution()` and,
   for grouped data, `assess_variance()`.
3. **Describe** participants with `summary_table()`.
4. **Compare** one variable across groups with `compare_groups()`.
5. **Inspect** assumptions, diagnostics, and denominators when needed.
6. **Render or export** only when you want to customise the finished output.

The main functions print publication-ready flextables by default. Rendering is
not an analysis step: use `customise_table()` for finishing touches and
`to_gt()` only when an HTML-focused gt table is required.

## Install and load

```{r install, eval=FALSE}
# Development version until the package is on CRAN
remotes::install_github("ThinkDenominator/gtstats")
library(gtstats)
data("birthwt", package = "gtstats")
```

## 1. Understand a dataset

```{r first-look}
overview <- describe_data(birthwt)
to_flextable(overview)
overview$issues
```

The printed table is a compact first look. `$issues` is deliberately separate
so an ordinary data overview is not cluttered with cautions that do not apply.

## Built-in teaching datasets

Use the labelled datasets included with gtstats when learning the workflow or
sharing reproducible examples:

```r
data(
  "birthwt", "trial_data", "paired_data", "outbreak_data",
  "surveillance_data", package = "gtstats"
)
```

`birthwt` is a real low-birth-weight study dataset. `trial_data` is a
three-arm synthetic clinical trial designed to demonstrate Welch ANOVA,
Kruskal-Wallis, chi-square, Fisher exact, correlation, and rates.
`paired_data` is long-format paired follow-up data for paired t-tests,
Wilcoxon signed-rank, and McNemar tests. Each help page contains its data
dictionary and examples.
`outbreak_data` is CDC's classic Oswego foodborne-outbreak line list, while
`surveillance_data` is an archived CDC weekly hospital-admission extract. They
demonstrate the line-list and aggregate-data routes of `epi_table()`.

## Prefer a guided interface?

`gtstats_app()` is an optional Shiny companion for learners and collaborators
who prefer a menu-driven starting point. It can load a built-in teaching
dataset or a CSV/Excel file, show a working data dictionary, then guide the
user through data description, distribution and spread checks, summary tables,
outbreak and surveillance tables, group comparisons, correlations, and
crosstabs. It can also preserve an already calculated results data frame as a
publication table. Every analysis page displays the corresponding R code with
copy and `.R` download buttons, while result tables can be downloaded as Word,
HTML, PDF, or RTF. The optional `rio` package enables Excel import.

```r
# Run once if Shiny is not installed
install.packages("shiny")
install.packages("rio") # only needed for Excel files

gtstats_app()
```

The GUI is not a substitute for a reproducible script: copy the displayed code
into an R script or Quarto document before final reporting. While the app is
open, the R console displays `Listening on ...`; this is normal. Click **Close
app** in the bottom-right corner of the interface to end the local session
cleanly and return to the R prompt.

Choose the route from what each row represents:

| Your data | Use | Why |
|---|---|---|
| One row per participant or observation | `summary_table()` | Descriptive statistics still need calculating |
| Outbreak line list or surveillance numerator/denominator data | `epi_table()` | Events, denominators, rates, or risks still need calculating |
| One row per final result, calculated elsewhere | `as_stats_table()` | Preserve every supplied value and only format the table |

## 2. Assess distribution for descriptive reporting

```{r assess}
distribution <- assess_distribution(birthwt, vars = c(age, lwt), by = low)
to_flextable(distribution)
distribution$recommendations
```

This function is restricted to continuous numeric variables. It uses
skewness, data quality, and Shapiro-Wilk as supporting information to guide
descriptive presentation. It does not choose an inferential test.

When groups are being compared, inspect their observed spread separately:

```{r assess-variance}
variance <- assess_variance(birthwt, vars = c(age, lwt), by = low)
to_flextable(variance)
```

`assess_variance()` presents one row per variable: each group's usable `n`, SD,
and variance, the observed SD and variance ratios, Levene p, and a short
interpretation. These
are descriptive diagnostics, not a test-selection rule: Welch methods do not
require equal variances.

## How Auto chooses an inferential test

The automatic algorithm is deliberately visible and can always be overridden:

| Data structure | Auto route |
|---|---|
| Continuous, 2 independent groups | Welch t-test when no marked skew is flagged; Student's t-test only with `var_equal = TRUE`; Wilcoxon rank-sum when marked skew is flagged |
| Continuous, 3+ independent groups | Welch ANOVA when no marked skew is flagged; classical ANOVA only with `var_equal = TRUE`; Kruskal-Wallis when marked skew is flagged |
| Continuous, paired | Paired t-test or repeated-measures ANOVA when no marked skew is flagged; Wilcoxon signed-rank or Friedman when flagged |
| Independent categorical or ordinal | Chi-square when expected-count guidance is met; Fisher exact when an expected count is below 1 or more than 20% are below 5 |
| Paired binary | McNemar for 2 occasions; Cochran's Q for 3+ occasions |

The skewness threshold—not the Shapiro-Wilk p-value alone—controls the
continuous rank-based switch. Levene and Bartlett results are descriptive
support and never change Auto. Inspect the recorded reason with
`diagnostics_stats()` or `result$method$selection_rule`. The full explanation
is in [Inferential tests and assumptions](inferential-tests.html).

## 3. Create a Table 1

```{r table-one}
table_one <- summary_table(
  birthwt,
  by = low,
  include = c(age, lwt, race, smoke),
  overall = "last"
) |>
  add_p()

to_flextable(table_one)
```

By default, categorical percentages use non-missing observations. If Missing
is a meaningful reported category that should contribute to the denominator,
choose `missing = "as_category"`. This is different from merely showing a
missingness row with `"ifany"` or `"always"`; see [Missing data and
denominators](missing-data-denominators.html) before using it.

Add optional rows only when they answer a specific reporting need:

```{r optional-rows}
table_one |>
  add_proportion(var = smoke, level = "Yes", label = "Smoking prevalence", ci = TRUE) |>
  add_total() |>
  to_flextable()
```

## 4. Compare one variable

```{r compare}
comparison <- compare_groups(birthwt, variable = lwt, group = low)
to_flextable(comparison)
```

For a transparent audit trail:

```{r audit}
assumptions_stats(comparison)
diagnostics_stats(comparison)
denominators_stats(comparison)
```

## 5. Customise and export

```{r export, eval=FALSE}
table_one |>
  customise_table(
    title = "Table 1. Vehicle characteristics",
    theme = "journal"
  ) |>
  save_output("table-1.docx", path = tempdir())
```

Before reporting any percentage or inference, read [Missing data and denominators](missing-data-denominators.html). For a full clinical example, continue to the [birth-weight case study](birthweight-case-study.html).
