Guided Statistics
Start with a question, see what the data can support, and keep the evidence visible. These 39 tools explain their clues instead of silently choosing an analysis for you.
Use stat.explore to see centre, spread, shape, missing values, and observations worth reviewing.
Use stat.scan to find data-quality, design, and association clues before fitting a model.
Use stat.decision_map to connect the scientific question and experimental unit to possible approaches.
A safe first pass
Import the statistics package as stat. The public functions below are readable wrappers around runtime builtins. They return ordinary records, so you can inspect the numbers and explanations rather than accepting a hidden decision.
import "statistics" as stat
let values = [12.1, 12.4, 12.8, 13.0, 13.2, 13.5, 29.0]
let result = stat.explore(values, {name: "protein concentration"})
println(stat.explain(result))
println(stat.distribution_ascii(values))
result.review_flags
The examples on this page are copyable package examples. The raw stats_* names shown in the tables are implementation-level builtins; application code should normally use stat.*.
What the guidance does not do
It does not prove normality, independence, causation, randomization, or a missing-data mechanism. It never deletes observations, transforms values, or selects a model automatically. Treat every recommendation as a prompt to check against how the data were collected.
1. Understand one numeric variable
Begin here when you have one measurement such as expression, concentration, age, or read depth.
| Public function | Runtime builtin | Use it to… |
|---|---|---|
stat.explore(values, options?) | stats_explore | Summarize centre, spread, shape, missingness, and review flags. |
stat.means(values, options?) | stats_means | Compare arithmetic, geometric, harmonic, trimmed, RMS, median, and mode with compatible spread choices. |
stat.shape(values, options?) | stats_shape | Inspect skewness, kurtosis, peaks, and normal Q-Q alignment without declaring a diagnosis. |
stat.distribution_clues(values, options?) | stats_distribution_clues | Compare compatible normal, log-normal, Poisson, and negative-binomial clues using likelihood and AIC. |
stat.uncertainty(values, options?) | stats_uncertainty | Compute seeded bootstrap intervals for summaries, differences, or correlations. |
stat.preview_transform(values, method, options?) | stats_transform_preview | Compare before and after log, log1p, square-root, z-score, robust, or min-max transformation. |
stat.preprocessing(values, options?) | stats_preprocess | Find observable data-quality issues and see non-applied preprocessing alternatives. |
stat.distribution_plot(values, options?) | stats_distribution_plot | Draw observations, histogram, mean, median, IQR, SD bands, and outlier flags. |
stat.distribution_ascii(values, options?) | stats_distribution_ascii | Show the same distribution clues in a terminal-safe chart. |
stat.normal_qq_plot(values, options?) | stats_normal_qq_plot | Compare ordered values with normal-distribution quantiles in SVG or ASCII. |
Centre and spread belong together
| When values behave like… | Useful centre | Useful spread |
|---|---|---|
| Roughly symmetric, additive measurements | Arithmetic mean | SD |
| Skewed or heavy-tailed measurements | Median | IQR or MAD |
| Positive multiplicative changes | Geometric mean | Geometric SD or fold interval |
| Rates with a common numerator | Harmonic mean | Report the individual rates and design context |
| Category frequency | Mode | Counts or proportions |
Variance is the average squared distance from the mean; SD is its square root and is in the original unit. Neither is “left” or “right.” On a symmetric bell-shaped distribution, mean ± 1, 2, and 3 SD are useful visual landmarks. They are not universal outlier rules for skewed data.
2. Audit a whole table and its design
| Public function | Runtime builtin | Use it to… |
|---|---|---|
stat.profile(data, options?) | stats_profile | Inspect types, summaries, missingness, duplicates, ranges, and declared design roles. |
stat.scan(data, options?) | stats_scan | Run a bounded first pass with prioritized, evidence-linked next steps. |
stat.overview_ascii(data, options?) | stats_overview_ascii | Read a compact whole-table overview in the CLI. |
stat.missingness(data, options?) | stats_missingness | Inspect missing values by row, column, pair, and optional group. |
stat.missingness_plot(data, options?) | stats_missingness_plot | Visualize missingness in SVG or ASCII. |
stat.design_check(data, options?) | stats_design_check | Review repeated units, imbalance, duplicate subject/time rows, and batch/group confounding clues. |
stat.associations(data, options?) | stats_associations | Screen bounded numeric and categorical effect-size associations. |
stat.report(data, options?) | stats_report | Create a self-contained HTML or Markdown data-health report with provenance. |
stat.guide(report, context?) | stats_guide | Add the scientific question and experimental-unit context to a report. |
stat.explain(report, detail?) | stats_explain | Render quick, learning, or audit-level plain text. |
stat.decision_map(options?) | stats_decision_map | Browse question-led analysis alternatives without automatic selection. |
let audit = stat.scan(data, {
subject_column: "patient_id",
group_column: "treatment",
batch_column: "sequencing_batch"
})
println(stat.overview_ascii(data))
println(stat.explain(audit))
audit.recommendations
Column roles are declared by you; BioLang does not infer experimental units or randomization from convenient column names. Missingness patterns are investigation clues, not proof that data are MCAR, MAR, or MNAR.
3. Compare groups, relationships, and categories
| Public function | Runtime builtin | Use it to… |
|---|---|---|
stat.compare(values, groups, options?) | stats_compare | Compare per-group evidence and see compatible analysis alternatives. |
stat.relationship(x, y, options?) | stats_relationship | Inspect complete pairs, Pearson/Spearman association, and a regression line. |
stat.categorical(values, options?) | stats_categories | Count levels, proportions, modes, missingness, and rare-level clues. |
stat.group_plot(values, groups, options?) | stats_group_plot | Draw group observations and robust summaries in SVG or ASCII. |
stat.relationship_plot(x, y, options?) | stats_relationship_plot | Draw a scatterplot and fitted line in SVG or ASCII. |
stat.categorical_plot(values, options?) | stats_categorical_plot | Draw frequency bars in SVG or ASCII. |
Correlation describes association, not causation. A small p-value does not tell you whether an effect is important, whether groups were independent, or whether the study design was unbiased.
4. Omics and dependent data
| Public function | Runtime builtin | Use it to… |
|---|---|---|
stat.normalization_guide(matrix, options?) | stats_normalization_guide | Audit a dense or sparse matrix and see domain-aware normalization alternatives. |
stat.omics_profile(matrix, options?) | stats_omics_profile | Profile bulk RNA-seq, single-cell, proteomics, metabolomics, microbiome, or generic matrices without densifying sparse input. |
stat.weighted_summary(values, weights, options?) | stats_weighted_summary | Inspect weighted centre/spread, effective sample size, and weight concentration. |
stat.time_series_diagnostics(values, options?) | stats_time_series_diagnostics | Inspect trend, autocorrelation, Ljung-Box, and first differences in an ordered regular series. |
stat.cluster_diagnostics(values, clusters, options?) | stats_cluster_diagnostics | Estimate one-way ICC, cluster-size imbalance, and approximate information loss. |
5. Check fitted models
| Public function | Runtime builtin | Use it to… |
|---|---|---|
stat.linear_diagnostics(x, y, options?) | stats_linear_diagnostics | Inspect residual form, spread, Q-Q, order, and influence for a simple linear model. |
stat.linear_diagnostic_plot(x, y, options?) | stats_linear_diagnostic_plot | Draw residual-versus-fitted or residual Q-Q diagnostics. |
stat.multiple_linear_diagnostics(predictors, outcome, options?) | stats_multiple_linear_diagnostics | Check encodings, interactions, VIF, influence, intervals, and held-out error. |
stat.robust_linear_diagnostics(predictors, outcome, options?) | stats_robust_linear_diagnostics | Compare Huber and ordinary least-squares coefficients as a sensitivity analysis. |
stat.glm_diagnostics(predictors, outcome, options?) | stats_glm_diagnostics | Diagnose binomial or Poisson fits, including convergence, dispersion, influence, and calibration or zero-count clues. |
stat.random_intercept_model(predictors, outcome, clusters, options?) | stats_random_intercept_model | Fit fixed effects plus one declared random intercept and report pooling and variance components. |
stat.cox_diagnostics(time, event, predictors, options?) | stats_cox_diagnostics | Fit a Cox model and inspect intervals, likelihood, baseline hazard, concordance, and residual clues. |
Model checks that matter
- Check
convergedbefore interpreting a GLM. A non-converged logistic fit can still return misleading coefficients. random_intercept_modeldoes not fit random slopes, nested effects, or crossed effects.- The Cox Schoenfeld screen is descriptive; it is not a formal replacement for
cox.zph. - Diagnostics can reveal tension with a model, but cannot repair a weak study design.
Raw builtins versus the public API
The runtime performs deterministic full-data calculations under the stats_* names. The package wrappers keep user code short and stable. For example, stat.explore calls stats_explore, and stat.glm_diagnostics calls stats_glm_diagnostics. Use the raw name only when developing or testing the runtime itself.
Where to go next
- Use Math & Statistics for direct summaries, hypothesis tests, probability functions, and mathematical operations.
- Use the Practical Biostatistics book for visual, concept-first learning.
- Keep the returned record with your analysis so the evidence, options, backend, and limitations remain auditable.