--- title: "Inferential Tests and Assumptions" description: > Understand the default tests selected by gtstats, their indications, automatic checks, and assumptions that require study-design judgement. output: rmarkdown::html_vignette vignette: > %\VignetteIndexEntry{Inferential Tests and Assumptions} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} --- ```{r setup, include=FALSE} knitr::opts_chunk$set(collapse = TRUE, comment = "#>", eval = TRUE) library(gtstats) ``` `gtstats` uses conservative, beginner-friendly defaults. Automatic selection can inspect the data, but it cannot determine whether observations are independent or whether the design and denominator answer the intended clinical question. Those decisions remain the analyst's responsibility. ## Quantify the magnitude separately Use `effect_size()` when the question is how large a difference or association is. Its default output is deliberately smaller than `compare_groups()`: ```{r effect-size} to_flextable(effect_size(mtcars, variable = mpg, group = am)) ``` The automatic measure follows the comparison structure: - two continuous groups: Hedges' g, with a confidence interval; - two-group rank comparison: rank-biserial correlation; - more than two continuous groups: omega-squared; - multi-group rank comparison: epsilon-squared; - categorical association: Cramer's V. For a two-group effect, the Contrast column explicitly names the grouping variable and uses its displayed order: first group minus second group. Positive and negative standardized or rank effects therefore have an unambiguous direction. Cramer's V and omnibus measures describe association or overall variation and have no direction. Interval method information is retained in the notes; Hedges' g intervals are labelled as approximate large-sample intervals. An explicit method remains available when the scientific question requires it: ```{r effect-size-rank} to_flextable(effect_size( mtcars, variable = mpg, group = am, method = "rank_biserial" )) ``` Generic magnitude labels are excluded by default. Set `interpretation = TRUE` only when a conventional teaching label is useful; the table then states that this is not a threshold for clinical importance. For risk ratios, odds ratios, and risk differences, use `crosstabs()` so that the exposure and event direction remain explicit. ## Default selection policy `compare_groups(test = "auto")` follows these fixed rules. The selected test is never hidden: it is printed in the result and recorded with its rule and inputs in `$method`, `$diagnostics`, and `$notes`. | Comparison | What auto checks | Test selected | |---|---|---| | Continuous, two independent groups | Marked skewness within each group; `var_equal` | Welch t-test by default; Student's t-test when `var_equal = TRUE`; Wilcoxon rank-sum only if one or more groups have marked skewness | | Continuous, three or more independent groups | Marked skewness within each group; `var_equal` | Welch ANOVA by default; classical ANOVA when `var_equal = TRUE`; Kruskal-Wallis if one or more groups have marked skewness | | Continuous, paired (two occasions) | Marked skewness of within-pair differences | Paired t-test if not flagged; Wilcoxon signed-rank if flagged | | Continuous, paired (3+ occasions) | Marked skewness at each occasion | Repeated-measures ANOVA with Greenhouse-Geisser-corrected degrees of freedom if not flagged; Friedman test if flagged | | Ordinal, independent | Expected cell counts | Pearson chi-square when no expected count is below 1 and no more than 20% are below 5; Fisher's exact otherwise | | Ordinal, paired | Outcome is ordered | Wilcoxon signed-rank (two occasions) or Friedman (3+ occasions) | | Binary or nominal categorical, independent | Expected cell counts | Pearson chi-square when no expected count is below 1 and no more than 20% are below 5; Fisher's exact otherwise | | Binary, paired | Paired design and binary outcome | McNemar test (two occasions) or Cochran's Q test (3+ occasions) | The continuous-variable switch means **marked** absolute sample skewness (default cut-off 1), not any asymmetry and not a normality-test p-value. Shapiro-Wilk is supporting information only and does not alone switch the test. `add_p()` uses the same rules. ## Ordinal values: make the meaning explicit `compare_groups()` retains an `ordered` factor's ordinal classification, but for an **independent Table 1 comparison** it uses chi-square/Fisher to compare the distribution of all levels. Request `test = "wilcox"` or `test = "kruskal"` if the clinical question is specifically about the ordered ranks. A numeric variable with a few values (for example `0`, `1`, `2`, `3` visits or cancer stages coded `1`--`4`) is deliberately treated as a categorical/count-coded variable unless its order is explicitly declared. This avoids silently treating a clinical code as a numerical scale. Convert a true ordered variable before comparing it: ```r data$stage <- ordered(data$stage, levels = c(1, 2, 3, 4)) compare_groups(data, variable = stage, group = arm) # categorical distribution compare_groups(data, variable = stage, group = arm, test = "wilcox") # rank shift ``` `describe_data()` makes this distinction visible: explicit ordered factors are shown as `ordinal`; small integer-coded variables receive a possible ordinal/count-coded flag for review against the data dictionary. It does not change the analysis type automatically. Other automatic defaults are: | Question | Default | |---|---| | Estimate one proportion | Exact binomial confidence interval | | Correlate two continuous variables | Pearson for approximately symmetric variables; otherwise Spearman | | Estimate an event rate | Exact Poisson confidence interval | ## Proportions are estimates, not automatically tests `proportion_stats()` estimates a proportion and Wilson score confidence interval. It does not test whether groups differ. ```{r proportion} to_flextable(proportion_stats(mtcars, var = vs, by = am)) ``` To compare categorical distributions, use `compare_groups()`, `add_p()`, or `crosstabs()`. ```{r categorical} to_flextable(compare_groups(mtcars, variable = vs, group = am)) to_flextable(crosstabs(mtcars, row = am, col = vs)) ``` In automatic mode, expected cell counts are calculated. Fisher's exact test is selected when an expected count is below 1 or more than 20% of expected cells are below 5; otherwise chi-square is used. Larger sparse tables use Fisher's test with a Monte Carlo p-value. Returned objects expose the expected counts and the minimum expected count. The analyst must still confirm: - observations are independent; - each observation contributes to one cell; - categories are mutually exclusive; - row and column levels have been defined in the intended direction. For paired binary observations, supply an identifier and use McNemar's test: ```{r mcnemar} to_flextable(compare_groups( paired_data, variable = symptom_present, group = visit, paired = TRUE, id = id )) ``` ## Continuous outcomes Welch's t-test is the two-group parametric default because it does not require equal variances. Welch ANOVA is the corresponding default for three or more groups. When equal variances are justified in a prespecified analysis plan, `var_equal = TRUE` changes the non-skewed independent automatic route to Student's t-test or classical ANOVA. It does not run, infer, or prove an equal-variance hypothesis test. Use `assess_variance()` to make the observed group spread visible before interpreting a comparison. It reports SDs, variances, and largest/smallest spread ratios and displays the median-centred Levene test by default. Bartlett is available as optional supporting information. These tests are never gatekeepers and do not change the automatic choice. ```{r variance-diagnostics} to_flextable(assess_variance(mtcars, vars = mpg, by = am)) to_flextable(assess_variance(mtcars, vars = mpg, by = am, test = "none")) to_flextable(assess_variance(mtcars, vars = mpg, by = am, test = "bartlett")) ``` The same observed-spread diagnostic is retained in an independent continuous `compare_groups()` result. It is descriptive context, not a test-selection rule: Welch t-tests and Welch ANOVA do not require equal variances. The value of `var_equal` is a transparent user choice, not a data-driven variance test. ```{r continuous} to_flextable(compare_groups( mtcars, variable = mpg, group = am, test = "auto" )) to_flextable(compare_groups(mtcars, variable = mpg, group = cyl)) to_flextable(compare_groups(mtcars, variable = mpg, group = cyl, test = "anova")) ``` Distribution guidance primarily uses skewness. Shapiro-Wilk results are supporting information and are not used alone to select a test. Analysts should also inspect outliers and plots. To see the exact automatic decision for one analysis, inspect the saved result: ```{r auto-audit} result <- compare_groups(mtcars, variable = mpg, group = am) result$method$selection_rule result$method$selection_inputs diagnostics_stats(result) ``` Wilcoxon rank-sum and Kruskal-Wallis tests compare ranks. Interpreting them specifically as median comparisons requires broadly similar distribution shapes across groups. For paired continuous analyses, distribution guidance is applied to the within-pair differences rather than each measurement occasion separately. ## Summary-table p-values `add_p()` uses the same automatic selection policy as `compare_groups()`. Distribution guidance is enabled by default. ```{r add-p} summary_table(mtcars, by = am, include = c(mpg, wt, vs), overall = TRUE) |> add_p() |> to_flextable() ``` Tests can be prespecified per variable: ```{r add-p-explicit} summary_table(mtcars, by = am, include = c(mpg, wt, vs)) |> add_p( test = c( mpg = "welch_t", wt = "wilcox", vs = "fisher" ), distribution_check = FALSE ) |> to_flextable() ``` To use the equal-variance parametric route deliberately: ```{r equal-variance-auto} to_flextable(compare_groups(trial_data, change_score, group = arm, var_equal = TRUE)) ``` The table footnote records tests used and reminds readers that independence must be confirmed from the study design. ## Correlation Automatic correlation selection uses marginal distribution shape, but this cannot confirm the shape of the relationship. Inspect a scatterplot: - Pearson requires an approximately linear relationship. - Spearman requires a monotonic relationship. With `method = "auto"`, `correlation()` uses Pearson only when both marginal absolute sample skewness values are below 1; otherwise it uses Spearman. This is a transparent default, not proof that the relationship is linear or monotonic. Inspect `plot_correlation()` before reporting the coefficient. `diagnostics_stats()` records the two skewness values, selected rule, and the number of complete finite pairs used. - Both require independent observation pairs without dominating influential observations. For exploratory work with several continuous variables, supply `vars` instead of `x` and `y`. One method is deliberately used throughout the matrix, avoiding a confusing mixture of Pearson and Spearman coefficients. Each pair may have a different denominator when values are missing, so inspect `$summary` before reporting selected results. ```{r correlation-matrix} matrix_result <- correlation( mtcars, vars = c(mpg, disp, hp, wt), display = "estimate_p", adjust = "holm" ) to_flextable(matrix_result) plot_correlation(matrix_result) ``` The heatmap shows direction and magnitude, not importance or causality. Multiplicity adjustment is available for exploratory p-values, but a matrix does not replace a prespecified research question. ## Rates `rate_stats()` estimates rates with exact Poisson confidence intervals. Confirm that: - events are valid counts; - person-time or exposure time is positive and correctly accumulated; - observations or event processes are suitably independent; - a Poisson process is a reasonable approximation. Counts per 100 people at a single time point are proportions, not incidence rates, unless genuine observation time is represented. ## Inspect what was checked Inferential objects retain transparent metadata: ```{r inspect} result <- compare_groups(mtcars, variable = vs, group = am) result$inferential result$method result$assumptions result$diagnostics result$denominators result$notes ``` `$inferential` records the selected test and reason. `$method` contains detected variable types and method metadata. `$assumptions` distinguishes automatic checks from requirements that must be confirmed from the study design. `$diagnostics` records check results, values, thresholds and interpretation. `$denominators` records total, non-missing and missing observations together with the numerator, denominator, group and rule used. `$notes` remains a short human-readable explanation. Use the inspection helpers for a consistent tibble or formatted table: ```{r inspect-helpers} assumptions_stats(result) diagnostics_stats(result) denominators_stats(result) denominators_stats(result, format = "tibble") ``` These audit helpers are intentionally separate from the publication table: - `assumptions_stats()` records what the method assumes, including items that require design or clinical judgement rather than a software check. - `diagnostics_stats()` shows numerical checks and automatic decisions in plain language; use `view = "audit"` for the underlying technical codes. - `denominators_stats()` shows the analysed observations, missing values, numerators and denominators behind reported percentages, rates and risks; `view = "audit"` returns the underlying field names. Use them to review an analysis before reporting it; they are not normally included in a manuscript table.