---
title: "Using the gtstats App"
description: "A beginner-friendly manual for the menu-driven gtstats Shiny app."
output: rmarkdown::html_vignette
vignette: >
  %\VignetteIndexEntry{Using the gtstats App}
  %\VignetteEngine{knitr::rmarkdown}
  %\VignetteEncoding{UTF-8}
---

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

<style>
.app-shot {
  border: 2px dashed #9a9a96;
  border-radius: 10px;
  background: #f7f7f4;
  color: #4a4a47;
  margin: 1.25rem 0 2rem 0;
  padding: 2.2rem 1.25rem;
  text-align: center;
}
.app-shot strong { display: block; color: #1c1c1e; margin-bottom: .35rem; }
.app-shot code { color: #7a3028; }
</style>

# gtstats App Manual

The `gtstats` app is a menu-driven companion to the package. It is designed
for users who want to understand a dataset, create publication-ready tables,
run common group comparisons and correlation analyses, and generate
reproducible R code without first
memorising every argument.

The app does not replace a reproducible analysis script. Its best use is:

1. Load or upload data.
2. Work through the analysis one tab at a time.
3. Review the publication-ready result and its audit information.
4. Copy or download the generated R code.
5. Run and save that code in RStudio or a Quarto document.

Each analysis includes a **Code** panel with **Copy code** and **Download .R**
buttons. The app is intended to teach the workflow while making the final
analysis reproducible and shareable.

## Launch the app

Install and load gtstats, then run:

```r
library(gtstats)
gtstats_app()
```

When started from RStudio, the default is the RStudio Viewer. Outside RStudio,
the app opens in a browser during an interactive R session. To explicitly use
your browser:

```r
gtstats_app(launch.browser = TRUE)
```

To start the local app without opening a window automatically:

```r
gtstats_app(launch.browser = FALSE)
```

## Close the app safely

While a Shiny app is open, the R console displays text such as:

```text
Listening on http://127.0.0.1:6783
```

This is normal: R is running the local app server. Use the **Close app** button
in the bottom-right corner of the app to end it cleanly and return to the R
prompt. Avoid interrupting it with RStudio's Stop button.

If R ever enters a `Browse[1]>` prompt after an interrupted session, type:

```r
Q
```

and press Enter.

## App dependencies

The app is only launched when `gtstats_app()` is called, so users who prefer
ordinary R code do not need its optional dependencies.

| Purpose | Package |
|---|---|
| App interface | `shiny` |
| RStudio Viewer support | `rstudioapi` where available |
| Table display and export | `gt`, `flextable` |
| Excel upload | `rio` (optional) |

For Excel input, install `rio` once:

```r
install.packages("rio")
```

# Recommended app workflow

The tabs are deliberately ordered to follow a safe statistical workflow.

1. **Data** — choose a teaching dataset, a data frame already in the R environment, or upload a file.
2. **Data Prep** — optionally make safe, reversible changes before analysis.
3. **Understand** — inspect types, completeness, distribution, and spread.
4. **Summary table** — create the descriptive table for a report.
5. **Epi table** — estimate outbreak and surveillance measures using an explicit event and denominator.
6. **Customise table** — refine the completed Summary or epidemiology table without changing results.
7. **Compare groups** — answer one focused inferential question.
8. **Correlation** — analyse a continuous pair or build a correlation matrix.
9. **Crosstabs** — inspect categorical association and 2×2 measures.
10. **History** — see which analyses were run during this session.
11. **Help** — revisit the safe beginner workflow.

The app will not run a summary table, comparison, correlation, or cross-tab until you press the
relevant action button. This prevents accidental analysis while the app is
loading or while a browser restores an earlier session.

The original imported dataset is active automatically. Opening Data Prep does
not silently replace it. After making changes, click **Use prepared data** only
when you want later tabs to analyse the working copy; otherwise analyses carry
forward the original data.

On a phone or narrow screen, use the menu icon in the top-right to open the
full tab list. The numbered workflow strip remains visible below it and can be
swiped sideways; no analysis tab is hidden or removed on smaller screens.

# Data tab

<div class="app-shot">
<strong>Screenshot 1 — App overview and Data tab</strong>
Replace this block with a wide screenshot showing the top menu, numbered
workflow, teaching-dataset selector, upload control, active-data message, and
Close app button.<br>
Suggested file: <code>vignettes/images/app-01-overview-data.png</code>
</div>

Use the **Data** tab first. Choose a labelled teaching dataset, select a data
frame or tibble that already exists in the current R environment, or upload a
file. **Refresh data-frame list** detects objects created after the app was
opened. Only data-frame-like objects are offered, which prevents accidental
selection of models, functions, or vectors.

Uploads support CSV, Excel (`.xlsx`/`.xls`), R data (`.rds`), Stata (`.dta`),
and SPSS (`.sav`). Excel, Stata, and SPSS files use the optional `rio` package.
Environment selection is intended for the locally launched app; a remotely
hosted app cannot inspect objects in a visitor's desktop R session.

# Data Prep tab

<div class="app-shot">
<strong>Screenshot 2 — Data Prep command bar and preview</strong>
Show the explicit preparation menus, structured action form, before/after
preview, change log, Undo/Redo, and Use prepared data button.<br>
Suggested file: <code>vignettes/images/app-02-data-prep.png</code>
</div>

**Data Prep** is optional. It is for small, auditable changes before analysis,
not a replacement for a full data-management workflow. The imported dataset is
kept unchanged; each action changes an independent working copy.

The command bar lists every available action explicitly. Click the task you
need, complete the structured fields that appear, then click **Apply this
change**. The current version provides eight common operations:

| Operation | Use it for | Safety check |
|---|---|---|
| Rename variable | Clearer variable names | Blank, duplicate, and invalid R names are rejected |
| Recode values | Give every recorded value a clear label, for example `0/1` to `No/Yes` | The mapping grid shows source and new labels side by side; ordered mode uses the displayed order |
| Set type and order | Make values categorical, ordered categorical, numeric, or text | The display-order grid appears only for ordered categorical values; every level must have one different position |
| Manage missing values | Convert recorded codes such as `999` or `Unknown` to `NA`, or show existing `NA` values as a labelled category | The app reports affected cells and warns that a Missing category changes analysis |
| Create calculation | Adjust one variable, combine two numeric variables, or calculate a ratio with a powered denominator (for example BMI) | Source variables are retained; preview shows usable rows |
| Create groups | Build a two-, three-, or four-group variable from one source variable | Give every group a label; conditions are checked top to bottom and the first match wins |
| Filter observations | Keep records meeting one or two inclusion criteria | A second condition is optional; preview shows kept, excluded, and unknown counts |
| Keep variables | Choose the columns for a smaller analysis dataset | Searchable multi-select, Keep all, and Clear selection controls; Undo restores removed columns |

The **Quick starts** buttons are fill-only helpers. **Age groups** proposes a
two-group age variable using a 65-year cut-off; **0/1 to No/Yes** opens a
matching binary recode when a variable coded exactly `0` and `1` is found;
**BMI-style calculation** sets up `numerator / (denominator ^ 2)`; and
**99/999 to missing** opens the missing-code workflow. None of these buttons
applies a change. They are deliberately starting points, so verify the selected
variable, coding, units, cut-offs, and labels before pressing **Apply this
change**.

For numeric grouping, choose equal to, not equal to, greater/less than,
greater/less than or equal to, **between (inclusive)**, or **outside a range**.
Range rules show a second field for the upper bound. Between means
`x >= lower & x <= upper`; outside means `x < lower | x > upper`. Both bounds
must be numeric, the lower bound cannot exceed the upper bound, and range rules
are unavailable for non-numeric variables. The preview shows each proposed
group's count and blocks an Apply action if any group would be empty. The final
group is always everyone else, and rules are evaluated from top to bottom.

Before applying, the panel states the expected impact: for example, how many
values will be recoded, how many codes will become missing, or how many rows a
filter will keep. For recoding, missing-value changes, group creation, and
filtering, it also shows a compact **Before you apply** table with the exact
values or row counts expected to change. The right-hand preview and the
**Change log** update immediately after you click **Apply this change**.
Use **Undo**, **Redo**, or **Reset all** to reverse work safely.

When an action uses a categorical variable, the panel also shows its exact
recorded values and offers **Copy values**. Recode values creates a mapping grid
with one row per observed value and pre-fills each new label with its existing
value. Edit only the labels that need changing. This avoids guessing whether a
dataset records a value as `Yes`, `yes`, `Y`, or `1`. Tick **Treat as ordered
categorical, in the order shown** only if that order has a genuine meaning.
For numeric variables, it shows the range, number of unique values, and any
short list of observed values.

When ready, choose one of these deliberately:

- **Continue without changes** makes all later tabs use the original data.
- **Use prepared data** makes all later tabs use the working copy.

The **Reusable code** panel records the applied actions. Copy or download this
code and use it as the starting point for a reproducible R script. Data Prep
does not evaluate arbitrary user-supplied R code.

Use **Download prepared data** to save the current working dataset as CSV,
Excel, RDS, or Stata. CSV and RDS work without additional packages; Excel and
Stata export use the optional `rio` package.

The **History** tab also provides **Download complete R script**. It combines
the data import, applied Data Prep changes, and only the analyses run during
that session. For an uploaded file, it uses a clear file-path placeholder
rather than the temporary upload path used by the app.

| Choice | Best use |
|---|---|
| Birth-weight example | Table 1, independent group comparisons, and 2×2 epidemiology |
| Three-arm trial | Three-group comparisons, rates, and categorical outcomes |
| Paired-data example | Learning the structure of paired analyses |
| Upload a CSV or Excel file | Your own analysis dataset |

## Uploading files

For CSV files, select the file and, if needed, use **Keep text columns as
text**. For Excel files (`.xlsx` or `.xls`), enter a worksheet name or number
when the relevant data are not on the first sheet.

Uploaded data remain in the current browser session only. They are not written
to the package or to a remote server.

## Preview and data dictionary

The **Preview** panel shows the first eight rows. Check it before proceeding:

- Are column names correct?
- Did numeric variables import as numeric values?
- Are Yes/No and category labels readable?
- Are blank strings actually meaningful categories, or should they be recoded?

The **Data dictionary** panel is a concise working overview. It shows the
source name, label, detected type, completeness, number of unique values, and
range or observed levels.

The app displays an observed empty category (`""`) as **`(blank)`** in tables.
This is distinct from missing data (`NA`). It is safe for exploration, but a
meaningful label should usually be created before final reporting.

## Reusable data code

The bottom code card shows the matching data-loading code. For example, the
birth-weight example generates:

```r
data("birthwt", package = "gtstats")
data <- birthwt
```

Copy this code first when creating a permanent R script.

# Understand tab

<div class="app-shot">
<strong>Screenshot 3 — Understand the data</strong>
Show Describe data, Distribution, and Variance controls, the plot selector,
one diagnostic table, and its download controls.<br>
Suggested file: <code>vignettes/images/app-03-understand.png</code>
</div>

The **Understand** tab has two jobs: give a compact overview of the data and
inspect selected continuous variables before choosing their descriptive display.
Its controls are arranged side by side: dataset overview on the left and
distribution/spread assessment on the right. Results use separate **Overview**,
**Distribution**, **Variance**, and **Plot** tabs, so wide tables and figures do
not form one long page.

## Describe data

Click **Describe data** to run `describe_data()`. The result identifies likely
continuous, binary, categorical, ordinal, and possible coded variables. It
also gives completeness and a compact value summary.

Start here before making a Table 1 or a comparison. In particular, confirm that
a numerical code is really continuous rather than a category or an ordinal
scale.

## Assess distribution

Select one or more continuous variables under **Distribution / spread**, then
optionally choose a grouping variable and click **Assess distribution**.

The result reports:

- usable observations, missing values, and non-finite values;
- sample skewness and a readable shape band;
- Shapiro-Wilk p-values as supporting information; and
- a suggested descriptive presentation.

The recommendation is for **descriptive reporting**, not test selection.
Shapiro-Wilk is sensitive to sample size; interpret it alongside skewness,
plots, and subject-matter knowledge.

Turn on **Create visual distribution diagnostics** to inspect any selected
variable as a histogram, density plot, Q-Q plot, or boxplot. Change the plot
type without rerunning the assessment, then download the current view as PNG
or PDF. Advanced controls expose the Shapiro-Wilk switch, skewness threshold,
minimum subgroup size, and precision used by `assess_distribution()`.

## Show spread by group

Check **Also assess spread by group** only when a grouping variable is selected.
The app will also run `assess_variance()` and show group SDs, variances, and
spread ratios. These are descriptive diagnostics. They do not impose an
equal-variance requirement: Welch methods are the package's parametric default
for independent groups.

## Code panel

The Understand code card contains the exact `describe_data()`,
`assess_distribution()`, and, when selected, `assess_variance()` calls. Copy
this into a script if these checks informed a reporting decision.

# Summary table tab

<div class="app-shot">
<strong>Screenshot 4 — Summary table ribbon and persistent preview</strong>
Show the Foundation–Design ribbon, Create / update table button, publication
preview with download buttons, and the Table recipe rail.<br>
Suggested file: <code>vignettes/images/app-04-summary-ribbon.png</code>
</div>

The **Summary table** workspace behaves like a familiar document editor. Its
ribbon contains five explicit tabs while the table preview remains in the same
place:

1. **Foundation** keeps the current data, variable selection, grouping variable and Overall column together.
2. **Statistics** controls continuous summaries, categorical presentation, denominators, missing values and layout.
3. **P-values** adds inferential tests and exposes transparent Auto settings and test-specific exceptions.
4. **Add** layers CIs, total N, a selected proportion, a rate, or a custom row.
5. **Design** changes appearance without changing the statistics.

Downloads sit beside the persistent preview rather than in a separate workflow
tab. Expand **Reusable R code** beneath the preview to copy or download the
complete recipe for RStudio.

The recipe rail confirms the active data, selected variables, column structure,
added layers, and theme. Changing a control does not destroy the current table:
click **Create / update table** when the revised recipe is ready.

## Choose a group

**Group columns by** is optional. Select `low` in the birth-weight example to
create one column per birth-weight outcome. The selected group is automatically
removed from the variable tickboxes; it should define the columns, not appear
as one of the rows.

## Select variables

Search for variables in the compact multi-select, or use **Select all** /
**Clear**. The line beneath it reports how many variables are selected and
previews variables still available. Removing a variable with × does not delete
it from the data: click **Add variables** to reopen the complete searchable
list and add it again. You can mix
continuous, binary, categorical, and ordered variables in one selection. The
app calls `summary_table()` once and lets gtstats detect their types.

For binary variables, **Binary variables** can retain both levels or show one
compact event row. When one row is selected, the app displays an event-level
selector for every selected binary variable. It uses the second declared level
by default, but the user can explicitly choose, for example, `Yes` for smoking
and `No` for hypertension. The generated script records these choices with
`show_dichotomous` and `value`.

There is no need to separately select “continuous variables” and “categorical
variables.” Use one meaningful set of summary-table variables.

## Optional ingredients

The ingredient section exposes the builder helpers without requiring users to
write a pipeline manually:

| Ingredient | GUI options | Generated function |
|---|---|---|
| Total N | Label and first/last position | `add_total()` |
| Selected proportion | Variable, event level, label, display, CI level/method, precision | `add_proportion()` |
| Rate | Event count, person-time, label, multiplier, time label, CI and precision | `add_rate()` |
| Custom row | Label, optional level, Overall and group-specific text | `add_row()` |

The Add ribbon keeps specialist rows distinct from ordinary summaries. A
selected proportion highlights one clinically important event; it is not
needed merely to add CIs to existing categorical levels.

For example, choose Summary table, group by `smoke`, place Overall first, use
Separate columns, untick ordinary summaries, and add the `low = Low birth
weight` proportion to generate:

```r
summary_table(
  data,
  by = smoke,
  overall = "first",
  layout = "separate"
) |>
  add_proportion(
    var = low,
    level = "Low birth weight",
    display = "n_percent"
  )
```

## Summary-statistic overrides

The app does not create a long row of dropdowns for every selected variable.
Unlisted continuous variables use **Recommended** automatically. Add only
exceptions to the compact override box, one per line:

```text
age = mean_sd
lwt = median_iqr
bwt = mean_ci
```

Supported summary values are `recommended`, `mean_sd`, `mean_ci`,
`median_iqr`, and `both`. Quotes and commas are not required. Blank lines and
lines beginning with `#` are ignored. **Insert example** uses selected
continuous variables; **Clear overrides** returns every variable to
Recommended. A live message reports how many overrides were recognised.

For `mean_ci`, a cell is displayed concisely as `mean (lower–upper)`. The
footnote defines the interval as a 95% CI (or the selected confidence level),
so “95% CI” is not repeated inside every table cell.

## Presentation controls

| Control | Meaning |
|---|---|
| Overall column | No overall column, or an Overall column first/last |
| Summary-statistic overrides | Optional exceptions; unlisted continuous variables use Recommended |
| Categorical display | n (%), n/N (%), n only, or percentage only |
| Categorical columns | Keep n (%) together, or separate n and % for categorical-only tables without CIs |
| Percentage denominator | Column, row, or the entire dataset |
| Overall categorical display | Automatic, n (%), n/N (%), n only, or percentage only |
| Missing values | `ifany`, `always`, and `no` control only whether a missingness row is shown and retain non-missing denominators; `as_category` treats Missing as a displayed category included in categorical percentages |
| Decimal places | Number of displayed decimal places |

Choose the percentage denominator intentionally. **Within each column** answers
“what percentage of this group has this level?” and is the usual Table 1
choice. **Within each row** answers a different question: how a level is
distributed across the displayed groups.

When row percentages and an Overall column are combined, **Automatic** shows
Overall categorical counts and grouped row percentages. This prevents a
whole-sample percentage from appearing to use the same denominator as the
grouped cells. Users can override it when their reporting plan explicitly
requires another Overall display. With separate categorical columns, the app
omits the unused Overall percentage child column rather than leaving it blank.

## Build the table layer by layer

The Summary table ribbon follows the same onion-like model as the R API:

1. Use **Foundation** to confirm the data, select variables, group columns and place Overall.
2. Use **Statistics** to choose summaries, missing-value display and layout.
3. Use **P-values** only when the table needs comparisons; Auto remains transparent and overridable.
4. Use **Add** to layer confidence intervals globally or only for selected variables, then add specialist rows only when they answer the report question.
5. Use **Design** to finish the publication table; download the result or its R script directly from the preview.

Selecting confidence intervals generates a visible `add_ci()` layer. The app
does not hide that choice inside `summary_table()`. Categorical levels receive
proportion intervals, continuous means receive mean intervals, and median-only
summaries remain unchanged.

```r
summary_table(
  birthwt_data,
  by = low,
  include = c(age, lwt, race, smoke),
  overall = "first",
  layout = "separate"
) |>
  add_ci(vars = c(age, race))
```

## Add p-values

Check **Add p-values (when grouped)** if a p-value for each selected variable
is appropriate for your table. A grouping variable is required. The app uses
`add_p()` with its documented automatic selection policy. Once p-values are
enabled, the **P-value test overrides** box appears. Unlisted variables use
Auto. Add only exceptions:

```text
age = welch_t
lwt = wilcox
race = fisher
bwt = none
```

Use `none` when a displayed variable should remain descriptive without a
p-value. The app validates variable names, duplicate entries, supported option
names, and compatibility with the detected variable type. Errors identify the
specific line and list valid choices. Generated code uses a named `method`
vector and an `include` selection when any variable is set to `none`.

## Customise appearance

Choose a default, journal, classic, minimal, or compact theme. Optional title,
subtitle, font size, bold labels, footnotes, and alternate-row shading are
applied through `customise_table()`. The preview and every downloaded table use
the same styling choices.

## Preview, export, and code

Every visible table in the app—data preview, data dictionary, dataset
description, diagnostics, summary table, comparison audits, crosstabs, and
history—has download buttons for DOCX, HTML, PDF, and RTF. PDF needs a working
browser/webshot setup; DOCX or HTML are the easiest choices for most users.

Open the **Code** panel to copy or download the complete `summary_table()`
pipeline and every selected layer, including the base summaries, `add_ci()`,
`add_p()`, `add_total()`, `add_proportion()`, `add_rate()`, `add_row()`, and
`customise_table()`.
This is the route from a point-and-click table to a reproducible manuscript
table.

# Epi table tab

<div class="app-shot">
<strong>Screenshot — Epi table recipe</strong>
Show Data structure, Ingredients and Reporting, together with the persistent
preview, denominator audit and generated code.<br>
Suggested file: <code>vignettes/images/app-epi-table.png</code>
</div>

This workspace is deliberately separate from Summary table. A Summary table
describes participants; this workflow estimates disease occurrence and must
make the numerator and denominator explicit.

1. Choose **One row per person/record** for a line list or **Numerator and denominator columns** for aggregate surveillance data.
2. Choose proportion, prevalence, attack rate or incidence rate and its reporting scale.
3. Optionally group by a ward, site, exposure or another meaningful stratum.
4. For a line list, select outcomes and explicitly choose the event value for each one. For aggregate data, map the numerator and denominator columns.
5. Review the denominator explanation before running the table.
6. Add p-values only when the question compares groups. Add epidemiological effect measures only for exactly two groups.

Confidence intervals are always present: Wilson is the default for risk-like
measures, exact binomial is optional, and incidence rates use exact Poisson
intervals. The generated code records every event, denominator, scale and
optional comparison. `$denominators`, `$p_values`, and `$effects` remain
available for audit.

The app prevents a case-only line list from being presented as an attack rate.
When only cases are present, switch to aggregate data and provide the eligible
population denominator.

# Customise table tab

<div class="app-shot">
<strong>Screenshot 5 — Customise the completed table</strong>
Show the carried-forward Summary table beside theme, labels, spanner, borders,
density, font, colours, footnotes, p-value style, and export controls.<br>
Suggested file: <code>vignettes/images/app-05-customise.png</code>
</div>

Use this tab when a table's presentation needs to match a manuscript, journal,
report, or local wording convention. It follows the same post-processing idea
as the gtregression app.

Choose the source at the top of the tab:

- **Completed Summary table** carries forward the most recently generated
  `summary_table()` result.
- **Current data are final calculated results** treats every current row and
  column as a final value. It does not recalculate descriptive summaries or
  p-values. Do not choose this route for participant-level raw data.

The second route is useful after `dplyr::summarise()` or when an analyst has
received a calculated results sheet. Generated code wraps the data with
`as_stats_table(data)` before applying `customise_table()`, so the workflow is
fully reproducible.

For already summarised data, tick **Calculate a confidence interval from
aggregate columns** only when the data contain the required ingredients. Pick
the calculation type, then map its columns: successes/total for a proportion,
events/exposure for a rate, mean/SD/N for a mean, or estimate/SE for a normal
interval. The app previews the completed table and generates the matching
`as_stats_table() |> add_ci()` code. It never guesses these meanings from a
column name.

The most recently completed Summary table is carried forward and displayed
automatically. If no Summary table exists, either return to the preceding tab
or deliberately choose the already-summarised-data route.

1. Review the Summary table already displayed in the preview.
2. Optionally provide a title, subtitle, or additional note.
3. Relabel columns, variable/row labels, or category levels using one
   `current = new` mapping per line.
4. Choose a theme, font size, label emphasis, footnotes, or row shading.
5. Optionally hide named columns.
6. Click **Apply table changes**.

The controls are grouped by purpose so beginners can work from top to bottom:

| Group | Available controls | What they affect |
|---|---|---|
| Theme | Default/journal/classic/minimal/compact | Overall visual preset; app previews use gt and Office downloads use the appropriate export renderer |
| Headings | Title, subtitle, spanning header | Table caption and grouped column heading |
| Wording | Column, row, and level mappings | Displayed labels only; source data remain unchanged |
| Notes | Source note, extra footnotes, show/hide package footnotes | Explanatory material below the table |
| Typography | Font, font size, bold labels | Readability and emphasis |
| Layout | Standard/compact/spacious density and table width | Row spacing and overall table dimensions |
| Rules and colour | Horizontal/all/minimal borders, accent colour, row striping and stripe colour | Publication styling |
| Column control | Left/centre/right alignment, hide, bold, or italic columns | Fine-grained completed-column formatting |
| P-values | Threshold/fixed/scientific style, digits, threshold, optional `p =` | Display only; the selected tests and numeric p-values do not change |

Use **compact** density for a long manuscript table and **standard** for most
reports. The package already uses smaller footnote text, so footnotes remain
visually subordinate to the data. Use **Show footnotes** unless the same
definitions are supplied in the manuscript caption or methods.

The original Summary-table result remains unchanged. Only its display is modified. The preview
and DOCX, HTML, PDF, and RTF downloads therefore contain the same estimates,
confidence intervals, denominators, and p-values as the selected source table.

The **Code** panel creates the source table and then applies
`customise_table()`. Copy or download that code rather than relying on an
unrecorded series of clicks.

Example mappings are:

```text
Overall = All participants
age = Maternal age (years)
Yes = Present
No = Absent
```

Column hiding is presentational only. Hiding a p-value column does not remove
the test from the result object or change the analysis.

# Compare groups tab

<div class="app-shot">
<strong>Screenshot 6 — Compare groups</strong>
Show outcome/group selection, Auto versus explicit test control, paired
options, effect size, publication table, and Audit panel.<br>
Suggested file: <code>vignettes/images/app-06-compare.png</code>
</div>

Use **Compare groups** for one focused inferential question—not to replace a
descriptive Table 1.

1. Choose the **Variable to compare** (the outcome).
2. Choose the categorical **Compare across groups** variable.
3. Leave **Test** as Auto or explicitly select a planned test.
4. Optionally request an effect size.
5. Click **Compare groups**.

Variable and group must be different. The app starts with a sensible pair in
the birth-weight data (`age` by `low`).

## Test control

**Auto** is the recommended starting point when there is no prespecified test.
Its policy is visible in the package documentation and result notes:

| Data structure | Automatic method |
|---|---|
| Continuous, two independent groups | Welch t-test by default; Student's t-test with `var_equal = TRUE`; Wilcoxon only if marked skewness is flagged |
| Continuous, 3+ independent groups | Welch ANOVA by default; classical ANOVA with `var_equal = TRUE`; Kruskal-Wallis only if marked skewness is flagged |
| Continuous, paired | Paired t-test/Wilcoxon signed-rank for two occasions; repeated-measures ANOVA/Friedman for 3+ occasions |
| Ordinal | Chi-square/Fisher for independent level distributions; Wilcoxon signed-rank for two paired occasions or Friedman for 3+ paired occasions. Specify Wilcoxon/Kruskal explicitly for an independent rank-based ordinal question. |
| Binary/nominal categorical | Chi-square when no expected count is below 1 and no more than 20% are below 5; Fisher exact when sparse |
| Binary, paired | McNemar for two occasions; Cochran's Q for 3+ occasions |

Marked skewness uses absolute sample skewness at least 1. Shapiro-Wilk and
lesser asymmetry remain supporting information; neither changes Auto alone.
For categorical and independent ordinal outcomes, Fisher is selected when an
expected count is below 1 or more than 20% are below 5; otherwise chi-square
is used.

The app also exposes the paired methods: McNemar (two binary occasions),
Cochran's Q (three or more binary occasions), repeated-measures ANOVA, and
Friedman. Turn on **Repeated measurements from the same participant** and
select the participant ID before running any paired comparison. Use an explicit
choice only when it is justified by the study design or an analysis plan.

For **Auto**, the app also offers **equal variances are justified**. This sets
`var_equal = TRUE`: it switches only a non-skewed independent continuous auto
comparison to Student's t-test or classical ANOVA. It does not perform a
variance test and does not alter paired, categorical, ordinal, or rank-based
comparisons.

## Result and Audit panels

The **Result** panel gives the publication-ready comparison table and explains
what auto selected. The **Audit** panels are important:

| Audit tab | What it shows | What you should do |
|---|---|---|
| Diagnostics | Calculated details such as expected counts or distribution context | Check for sparse data and unexpected patterns |
| Assumptions | Automatic checks and design checks | Confirm user-check items from the study design |
| Denominators | Observations used by the calculation | Confirm the analytical population is appropriate |

Use the **Code** panel to retain the exact comparison in your analysis script.

# Correlation tab

<div class="app-shot">
<strong>Screenshot 7 — Correlation and matrix visualisation</strong>
Show the pair/matrix switch, method choice, correlation table, heatmap, plot
appearance controls, and generated code.<br>
Suggested file: <code>vignettes/images/app-07-correlation.png</code>
</div>

Use **Correlation** for relationships between continuous variables. Choose
**One pair** for a conventional coefficient and scatterplot, or **Correlation
matrix** for several variables.

For one pair:

1. Choose two different continuous variables.
2. Select Auto, Pearson, or Spearman.
3. Choose the plotted trend and whether its confidence band is shown.
4. Click **Create correlation output**.

Under **Advanced plot appearance**, pair plots can customise point and trend
colours, axis labels, caption, confidence level, and base font size. Matrix
heatmaps can customise negative, zero, and positive correlation colours.

For a matrix:

1. Tick at least two continuous variables.
2. Choose lower, upper, or full layout. Lower triangle is the publication
   default; upper triangle places the longest row at the top.
3. Preserve the selected order, sort labels alphabetically, or cluster similar
   absolute correlation patterns. Input order is best for a prespecified
   publication; clustering is exploratory.
4. Choose whether cells contain the coefficient alone, adjusted p-value,
   pairwise n, both p and n, or a confidence interval.
5. Optionally hide the diagonal and shade the publication table.

The **Plot** panel shows the matching scatterplot or heatmap and can be
downloaded as PNG or PDF. The publication table and all three Audit tables can
be downloaded as DOCX, HTML, PDF, or RTF. The **Code** panel reproduces both
the `correlation()` and `plot_correlation()` calls.

The app reports how many continuous variables are selected. At more than 12 it
warns that the matrix may be suitable for exploration but too wide for a
publication. **Tidy CSV** downloads the underlying pair-level estimates,
p-values, adjusted p-values, confidence intervals, and denominators. When
pairwise sample sizes differ, a visible warning directs you to the Denominators
tab. Less frequently used ordering, adjustment, diagonal, and shading controls
are kept under **Advanced matrix options**. **Reset options** restores the safe
defaults without running an analysis.

# Comparison plots

The **Compare groups** tab can create the figure that accompanies its
inferential result. Leave **Create comparison plot** selected for the beginner
route. Auto chooses an appropriate visual for the variable; experienced users
can request a boxplot or bar chart, switch categorical plots between counts and
proportions, show or hide observations and the p-value, edit labels and
caption, choose a colour palette, and change the base font size. The figure is
downloadable as PNG or PDF, and the Code panel includes the matching
`plot_compare()` call so the GUI figure can be reproduced in a script.

Auto uses Pearson throughout a matrix only when every selected variable has
absolute sample skewness below 1; otherwise it uses Spearman throughout. This
does not establish linearity or monotonicity. Review the plot, pairwise
denominators, influential observations, subject-matter meaning, and the fact
that correlation does not imply causation.

# Crosstabs tab

<div class="app-shot">
<strong>Screenshot 8 — Crosstabs and epidemiological measures</strong>
Show row/column selectors, percentage choices, totals, association test, and a
2x2 result containing OR, RR, and risk difference.<br>
Suggested file: <code>vignettes/images/app-08-crosstabs.png</code>
</div>

Use **Crosstabs** for two categorical variables.

1. Choose **Rows (exposure)**.
2. Choose **Columns (outcome)**.
3. Choose column, row, and/or total percentages.
4. Choose Auto, chi-square, Fisher exact, or no association test.
5. Click **Create crosstab**.

For a 2×2 table, the result includes RR, OR, and RD by default, in addition to
the association test and Cramer's V. For larger R×C tables, it gives the
cross-tab and association statistics, but not 2×2 risk measures.

If both row and column percentages are selected, cells are labelled so their
denominator is clear. The generated code contains `percent = c("row",
"column")`, which can be reused directly.

# History tab

The **History** tab records actions run during the current app session:

- Describe data
- Assess distribution
- Create summary table
- Compare groups
- Create a correlation table and plot
- Create crosstab

The **Complete R script** panel can be copied or downloaded and contains the
data source, applied preparation steps, and analyses run so far. The history is
a session log, not a permanent audit database. It clears when the
app closes, or when you click **Clear history**. Use it to orient yourself while
exploring; use copied/downloaded code for the permanent analysis record.

# Help tab

The **Help** tab repeats the safe beginner order:

1. Inspect the data.
2. Check selected continuous variables before interpreting comparisons.
3. Build a summary table using one consistent presentation per variable.
4. Use Compare groups for a focused inferential question.
5. Review the output and generated code before reporting.

# Saving outputs

<div class="app-shot">
<strong>Screenshot 9 — Download and reproduce</strong>
Show the DOCX/HTML/PDF/RTF controls together with Copy code and Download .R.
This should be the final image in the app tour.<br>
Suggested file: <code>vignettes/images/app-09-export-code.png</code>
</div>

Every result tab offers table downloads. Use them as follows:

| Format | Good for | Notes |
|---|---|---|
| DOCX | A Word manuscript | Best general choice for reporting |
| HTML | Viewing or sharing in a browser | Preserves the table appearance |
| RTF | Basic word-processing interchange | Useful when DOCX is not required |
| PDF | A fixed-layout copy | Requires a local browser/webshot setup |
| `.R` code | Reproducible analysis | Recommended for every final analysis |

The copy buttons use your browser clipboard. If a browser blocks clipboard
access, use **Download .R** instead.

# Troubleshooting

## The app does not open

```r
install.packages("shiny")
gtstats_app()
```

If it opens in an external browser and you prefer RStudio, run it from an
interactive RStudio session. You can also choose explicitly:

```r
gtstats_app(launch.browser = rstudioapi::viewer)
```

## Excel upload gives an error

Install `rio`, restart the app, and try again:

```r
install.packages("rio")
```

## A table or comparison is blank

Select the variables required by that tab and click its blue action button.
The app intentionally does not calculate Table 1, comparisons, or crosstabs on
startup.

## A variable seems to have the wrong type

Return to **Data** and check the preview and Data dictionary. In your permanent
script, explicitly convert categories to factors and ordered scales to
`ordered()` factors. Numeric clinical codes should not be interpreted as
continuous without checking their meaning.

## I see `(blank)` in a result

The uploaded data contain an observed empty string. This is not an app error:
gtstats displays it safely as `(blank)`. Decide whether it means “unknown”,
“not recorded”, or a true category, then recode it in your analysis script
before final reporting.

## Chrome or a browser crashes

Run the app in the RStudio Viewer where possible. A browser is only needed for
the local interface and, on some systems, PDF export. HTML and DOCX downloads
do not require a browser screenshot engine.

# Best practice

Use the app to learn, explore, and produce a first publication-ready output.
Use the generated R code as the durable record of the analysis. Before final
reporting, ensure that the data preparation, category meanings, missing-data
policy, statistical choices, and exports are reproducible outside the app.
