A production-quality Python library for ANOVA, Multiple Linear Regression, hypothesis testing, and Bayesian inference with structured output, simultaneous inference, and FWER control.
Project description
statscore
statscore is a production-quality Python statistical analysis library built for correctness, usability, and transparency. It implements the full classical inference pipeline — ANOVA, normal distribution testing, multiple linear regression, and Bayesian inference — with a consistent structured-output design philosophy: every function returns a typed dataclass with a .summary() method for formatted console output and a .plot() method that returns a matplotlib.Figure.
The library is designed to be used three ways: as a Python API importable in scripts and notebooks, as an interactive CLI requiring no programming, and as a browser UI built on Streamlit. All three interfaces call the same underlying statistical engine, so results are always identical regardless of how you access them.
Table of Contents
- Project Overview
- Statistical Methods
- Design Philosophy
- Installation
- Interfaces
- Quick Start
- Package Structure
- API Reference
- Mathematical Background
- Development
Project Overview
Statistical analysis software often falls into one of two camps: full-featured platforms (R, SPSS, SAS) that are hard to integrate into software pipelines, or Python libraries (statsmodels, scipy.stats) with inconsistent APIs, raw tuple return values, and outputs that require significant post-processing. statscore occupies the space between them.
What it covers:
| Domain | Methods |
|---|---|
| Analysis of Variance | One-way and two-way ANOVA; sum-of-squares decomposition; MLE estimation; F-tests |
| Multiple Comparison Procedures | Bonferroni, Šidák, Scheffé, Tukey corrections; simultaneous CIs; family-wise error rate (FWER) control |
| Normal Distribution Testing | Z-test, one/two-sample t-test, paired t-test, chi-squared variance test, F-test for variances; one- and two-sided alternatives |
| Multiple Linear Regression | OLS estimation; TSS partition; full regression summary table; simultaneous CIs; confidence regions; general hypothesis tests; prediction intervals |
| Bayesian Conjugate Inference | Normal-Normal, Normal-Gamma, Beta-Binomial, Gamma-Poisson; closed-form posteriors; credible intervals |
| Bayesian MCMC | General-purpose Metropolis-Hastings sampler; Normal data and linear regression models; trace plots; KDE posteriors; acceptance rate diagnostics |
| Model Diagnostics | Shapiro-Wilk normality test; Levene's variance homogeneity test; leverage, standardized residuals, Cook's D; mean confidence intervals |
| Visualization | Scatter+fit, residuals vs fitted, normal Q-Q, ANOVA box plots, CI forest plots, Bayesian density plots, MCMC trace+KDE panels |
| Data I/O | Load .csv, .tsv, .xlsx, .xls, .json via a single load_data call |
What makes it different:
- Every function returns a typed dataclass — never a raw tuple, never a dict, never a plain number. You always know what you're working with.
- Every result has
.summary()(formatted table to stdout) and.plot()(matplotlib Figure) built in. - The CLI gives access to all 21 analyses without writing a single line of Python. Data can be entered inline or loaded from files.
- The Streamlit browser UI provides a point-and-click interface to the same functions, with live plots that update as parameters change.
- All categorical parameters use enums —
AlternativeHypothesis.TWO_SIDED, not the string"two-sided". Typos are caught at import time, not at runtime. - The library is tested with 205 tests covering edge cases, mathematical correctness, and CLI behaviour.
Statistical Methods
Analysis of Variance (ANOVA)
ANOVA partitions total variability in a dataset into components attributable to different sources and tests whether those sources explain a statistically significant amount of variation.
One-Way ANOVA tests whether I ≥ 2 group means are equal. The model is X_{ij} = μ + α_i + ε_{ij} where ε_{ij} ~ N(0, σ²). The total sum of squares SS_T = SS_Between + SS_Within is partitioned, and the F-statistic F = MS_Between / MS_Within follows an F(I−1, n−I) distribution under H₀.
Two-Way ANOVA extends this to two crossed factors A (I levels) and B (J levels) with K ≥ 2 replicates per cell. The model X_{ijk} = μ + α_i + β_j + δ_{ij} + ε_{ijk} decomposes SS_T into main effects SS_A, SS_B, the interaction SS_AB, and error SS_E. Each source is tested independently.
Multiple Comparisons control the family-wise error rate when testing multiple contrasts simultaneously. A contrast c is a linear combination of group means with Σcᵢ = 0. statscore implements Bonferroni (per-comparison α/m), Šidák (1−(1−α)^{1/m}), Scheffé (F-distribution based, valid for all contrasts), and Tukey (Studentised range, optimal for all pairwise). The BEST method automatically selects whichever gives the narrowest valid intervals.
Normal Distribution Significance Testing
Six tests for normal-population parameters:
- Z-test: H₀: μ = μ₀ with σ known. Statistic Z = (x̄ − μ₀)/(σ/√n) ~ N(0,1).
- One-sample t-test: H₀: μ = μ₀ with σ unknown. Statistic T = (x̄ − μ₀)/(s/√n) ~ t(n−1).
- Two-sample t-test: Pooled (equal variances assumed) or Welch (unequal variances, Welch–Satterthwaite df).
- Paired t-test: T = d̄/(s_d/√n) ~ t(n−1) on pairwise differences.
- Chi-squared variance test: H₀: σ² = σ₀². Statistic Q = (n−1)s²/σ₀² ~ χ²(n−1).
- F-test for variances: H₀: σ₁² = σ₂². Statistic F = s₁²/s₂² ~ F(n₁−1, n₂−1).
All six tests support TWO_SIDED, LESS, and GREATER alternatives.
Multiple Linear Regression
statscore implements the full OLS inference pipeline for Y = Xβ + ε, ε ~ N(0, σ²I):
- Estimation: β̂ = (X^TX)^{−1}X^Ty, σ̂² unbiased = RSS/(n−p)
- Goodness of fit: R² = RegSS/TSS, adj R² = 1 − (1−R²)(n−1)/(n−p)
- Full summary table: coefficients, standard errors, t-statistics, p-values, significance stars, CIs — equivalent to R's
summary(lm(...)) - Simultaneous CIs: Scheffé-based confidence intervals for all β_i simultaneously (FWER control)
- Confidence regions: ellipsoidal CR for any linear transformation Cβ
- General hypothesis test: H₀: Cβ = c₀ using F = (Cβ̂−c₀)^T[C(X^TX)^{−1}C^T]^{−1}(Cβ̂−c₀)/(r·σ̂²) ~ F(r, n−p)
- Simultaneous prediction intervals: Scheffé or Bonferroni intervals for m new observations simultaneously
Bayesian Inference — Conjugate Models
When the prior and likelihood belong to a conjugate family, the posterior has a known closed form. statscore implements four conjugate models:
| Model | Prior | Likelihood | Posterior |
|---|---|---|---|
| Normal-Normal | μ ~ N(μ₀, σ²/κ₀), σ² known | X | N(μₙ, σ²/κₙ) |
| Normal-Gamma | (μ,τ) ~ NG(μ₀, κ₀, α₀, β₀) | X ~ N(μ,1/τ) | Normal-Gamma(μₙ, κₙ, αₙ, βₙ) |
| Beta-Binomial | p ~ Beta(α₀, β₀) | k | p ~ Bin(n,p) |
| Gamma-Poisson | λ ~ Gamma(α₀, β₀) | xᵢ ~ Poisson(λ) | Gamma(α₀+Σxᵢ, β₀+n) |
All four return credible intervals and prior/posterior density plots.
Bayesian Inference — MCMC
For models with no tractable conjugate posterior, statscore provides a Metropolis-Hastings sampler (run_mcmc) that accepts any log-posterior function. Two ready-made models are included:
mcmc_normal_mean_unknown_var: joint posterior of (μ, σ) for Normal data with Normal prior on μ and Inverse-Gamma prior on σ². Parameters constrained to (0,∞) are sampled in log-space to keep proposals Gaussian.mcmc_linear_regression: posterior of (β₀,…,β_{p−1}, σ) for Y = Xβ + ε with Normal priors on β and Inverse-Gamma on σ². Chains are OLS-initialised to reduce burn-in.
Results include trace plots, KDE posterior density panels, posterior mean/std, and HPD credible intervals.
Diagnostics
- Shapiro-Wilk test: W-statistic normality test, returns Q-Q plot
- Levene's test: Centre-of-residuals test for homogeneity of variance across groups
- Regression diagnostics: leverage h_{ii}, standardized residuals, Cook's D; flags high-leverage (h > 2p/n) and influential points (D > 4/n); four-panel diagnostic plot
- Mean CI: z-interval (σ known) or t-interval (σ unknown) for the population mean
Design Philosophy
Every function returns a typed dataclass. This means you can always introspect fields with tab-completion, pass results between functions, or write generic code that works with any test result. There are no raw tuples, no dicts with magic string keys, and no output you have to parse.
.summary() and .plot() are universal. Every result object provides both. This makes the API consistent: once you know how to use one function, you know how to use all of them.
Enums instead of strings. All categorical parameters (AlternativeHypothesis, CorrectionMethod, PredictionMethod, TwoWayTestFactor) use enums. This gives you IDE autocomplete, makes typos a TypeError rather than a silent wrong result, and lets code be read without memorising magic strings.
Strict layered architecture. The codebase is organised into dependency layers (utils → methods → plots/io/cli) with no circular imports. Domain modules never import from each other unless explicitly justified. Plot logic lives inside result.plot() methods rather than as standalone functions (except for a handful of shared utilities).
Three interfaces, one engine. The Python API, CLI, and Streamlit browser UI all call the same statscore.methods.* functions. If a result looks different between interfaces, there is a bug. The consistency is enforced by the typed API — the CLI cannot accidentally pass wrong types.
Installation
# From PyPI
pip install statscore
# From source (with dev dependencies)
git clone https://github.com/furkankyildirim/statscore.git
cd statscore
pip install -e ".[dev]"
Requirements: Python ≥ 3.9 · NumPy ≥ 1.21 · SciPy ≥ 1.7 · pandas ≥ 1.3 · matplotlib ≥ 3.5 · openpyxl ≥ 3.0
For the browser UI: pip install "statscore[ui]"
Interfaces
Python API
All public symbols are importable from the top-level package. Nothing requires knowing internal module paths.
from statscore import (
# ANOVA
anova1_partition_tss, anova1_test_equality,
anova1_ci_linear_combs, anova1_test_linear_combs,
anova2_partition_tss, anova2_mle, anova2_test_equality,
bonferroni_correction, sidak_correction,
# Testing
z_test_mean, t_test_mean, t_test_two_sample,
t_test_paired, chi2_test_variance, f_test_variances,
# Regression
mult_lr_least_squares, mult_lr_partition_tss,
regression_summary, mult_norm_lr_simul_ci,
mult_norm_lr_test_general, mult_norm_lr_pred_ci,
# Bayesian
bayes_normal_mean_known_var, bayes_normal_mean_unknown_var,
bayes_beta_binomial, bayes_gamma_poisson,
run_mcmc, mcmc_normal_mean_unknown_var, mcmc_linear_regression,
# Diagnostics
shapiro_wilk_test, levene_test,
regression_diagnostics, mean_confidence_interval,
# I/O
load_data,
# Enums
AlternativeHypothesis, CorrectionMethod,
PredictionMethod, TwoWayTestFactor,
)
Interactive CLI
statscore # after pip install
python -m statscore # or directly
A 21-item numbered menu covering all analyses. Data can be entered as space/comma-separated numbers, loaded from a file, or pasted as a semicolon-separated matrix (1,2,3; 4,5,6; 7,8,9). After every analysis, the CLI optionally saves plots to PNG files.
================================================================
statscore — Statistical Toolbox (v0.0.3)
Type a number to select a method, or 'q' to quit.
================================================================
── ANOVA ──────────────────────────────────────────────────
[1] One-Way ANOVA (F-test, ANOVA table)
[2] Two-Way ANOVA (Factor A / B / Interaction)
[3] Multiple Comparisons (Bonferroni/Scheffe/Tukey/Sidak)
── Significance Tests ─────────────────────────────────────
[4] Z-test for Mean (sigma known)
[5] One-Sample t-test
[6] Two-Sample t-test (pooled or Welch)
[7] Paired t-test
[8] Chi-squared Test for Variance
[9] F-test for Variances
── Regression ─────────────────────────────────────────────
[10] Simple Linear Regression
[11] Multiple Linear Regression (full inference suite)
[12] Regression Diagnostics (Leverage / Cook's D)
── Diagnostics ────────────────────────────────────────────
[13] Normality Check (Shapiro-Wilk + Q-Q plot)
[14] Variance Homogeneity (Levene)
[15] Confidence Interval for Mean
── Bayesian Inference — Conjugate Priors ──────────────────
[16] Bayesian Inference — Normal (known variance)
[17] Bayesian Inference — Normal-Gamma (unknown variance)
[18] Bayesian Inference — Beta-Binomial (success prob.)
[19] Bayesian Inference — Gamma-Poisson (count rate)
── Bayesian Inference — MCMC ──────────────────────────────
[20] Bayesian MCMC — Normal mean & variance
[21] Bayesian MCMC — Linear Regression
================================================================
Browser UI
The browser UI lives in statscore/app/__init__.py and is launched via the statscore-ui console script, which bakes in the correct Streamlit flags automatically (headless mode, XSRF protection, 50 MB upload cap, minimal toolbar).
# Recommended — install with UI extra and use the console script
pip install "statscore[ui]"
statscore-ui
# Or run directly with Streamlit (requires streamlit>=1.30)
pip install streamlit
streamlit run statscore/app/__init__.py
# Opens at http://localhost:8501
Six pages share a loaded dataset via session state:
| Page | Content |
|---|---|
| Data Input | Upload CSV/TSV/XLSX/JSON or paste data; live describe() preview; shared across pages |
| ANOVA | One-way (ANOVA table, box plots, F-distribution); Two-way (I×J×K cell entry, full decomposition table) |
| Significance Tests | All 6 tests; metric cards; reject/fail banner; distribution plot with shaded rejection region |
| Regression | Design matrix + y; coefficient table with significance stars; R²/adj-R²/Sₑ/F cards; scatter+fit, residuals, Q-Q, Cook's D |
| Bayesian Inference | Normal-Normal and Normal-Gamma conjugate; prior/posterior density with credible interval |
| Multiple Comparisons | Contrast matrix input; Scheffé/Tukey/Bonferroni/Šidák/Best; CI forest plot and test chart |
Quick Start
One-Way ANOVA
import numpy as np
from statscore import anova1_partition_tss, anova1_test_equality, plot_anova_groups
groups = [
np.array([28, 23, 14, 27, 31]), # Group A
np.array([33, 36, 34, 29, 24]), # Group B
np.array([18, 21, 20, 22]), # Group C (control)
]
# Partition total variability
p = anova1_partition_tss(groups)
print(f"SS_between={p.SS_between:.2f} SS_within={p.SS_within:.2f} SS_total={p.SS_total:.2f}")
# F-test for equality of group means
result = anova1_test_equality(groups, alpha=0.05)
result.summary()
# ═══════════════════════════════════════════════════════
# One-Way ANOVA Table
# ═══════════════════════════════════════════════════════
# Source df SS MS F
# ───────────────────────────────────────────────────────
# Between 2 276.11 138.05 5.57
# Within 11 272.75 24.80
# ───────────────────────────────────────────────────────
# Total 13 548.86
# ═══════════════════════════════════════════════════════
# F critical (α=0.05): 3.9823 p-value: 0.0214
# Decision: Reject H0
# ═══════════════════════════════════════════════════════
result.plot().savefig("anova1.png")
plot_anova_groups(groups, group_labels=["A", "B", "Control"]).savefig("groups.png")
Multiple Comparisons
from statscore import anova1_ci_linear_combs, anova1_test_linear_combs, CorrectionMethod
import numpy as np
C = np.array([[1,-1,0], [0,1,-1], [1,0,-1]]) # pairwise contrasts
# Simultaneous CIs — auto-select narrowest valid method
ci = anova1_ci_linear_combs(groups, alpha=0.05, C=C, method=CorrectionMethod.BEST)
ci.summary()
ci.plot().savefig("simul_ci.png")
# Simultaneous hypothesis tests H0: Cμ = 0
tests = anova1_test_linear_combs(groups, alpha=0.05, C=C,
d=np.zeros(3), method=CorrectionMethod.TUKEY)
tests.summary()
Significance Testing
from statscore import z_test_mean, t_test_two_sample, AlternativeHypothesis
import numpy as np
x1 = np.array([10.2, 9.8, 10.1, 10.3, 9.9, 10.0, 10.4, 9.7])
x2 = np.array([10.8, 11.2, 10.9, 11.1, 10.7])
# Z-test (σ known)
z_test_mean(x1, mu0=10.0, sigma=0.3, alpha=0.05,
alternative=AlternativeHypothesis.TWO_SIDED).summary()
# Two-sample Welch's t-test (unequal variances)
result = t_test_two_sample(x1, x2, alpha=0.05, equal_var=False,
alternative=AlternativeHypothesis.TWO_SIDED)
result.summary()
result.plot().savefig("t_test.png")
Multiple Linear Regression
import numpy as np
from statscore import (
mult_lr_least_squares, mult_lr_partition_tss, regression_summary,
mult_norm_lr_simul_ci, mult_norm_lr_test_general, mult_norm_lr_pred_ci,
PredictionMethod,
)
attend = np.array([1, 0.5, 0.2, 0.4, 0.5, 0.7, 0.8, 0.9, 0.6, 0.1, 0, 0, 0.7, 0.8, 1])
homework = np.array([0.25, 1, 0.5, 1, 1, 0.75, 1, 0.25, 0, 0, 1, 0.5, 0.25, 0.75, 1])
y = np.array([60, 65, 40, 70, 65, 70, 85, 70, 44, 20, 40, 30, 50, 77, 90], dtype=float)
X = np.column_stack([np.ones(15), attend, homework])
# OLS estimates
ols = mult_lr_least_squares(X, y)
print(f"β̂ = {ols.beta_hat}") # [14.37, 46.20, 30.45]
print(f"Sₑ² = {ols.sigma2_unbiased:.4f}") # 19.8400
# R² and adjusted R²
tss = mult_lr_partition_tss(X, y)
print(f"R²={tss.R_squared:.4f} adj R²={tss.adj_R_squared:.4f}")
# R²=0.9588 adj R²=0.9520
# Full summary table (like R's summary(lm(...)))
regression_summary(X, y, alpha=0.05).summary(
feature_names=["(Intercept)", "attendance", "homework"])
# Simultaneous CIs for all β_i
mult_norm_lr_simul_ci(X, y, alpha=0.05).summary()
# General hypothesis test: H0: β_attend = β_homework
C = np.array([[0, 1, -1]]); c0 = np.array([0.0])
mult_norm_lr_test_general(X, y, C, c0, alpha=0.05).summary()
# F = 11.4796, p = 0.0054 → Reject H0
# Simultaneous prediction intervals for new observations
D = np.array([[1, 0.5, 1.0], [1, 1.0, 0.0]])
mult_norm_lr_pred_ci(X, y, D, alpha=0.05, method=PredictionMethod.BEST).summary()
Bayesian Conjugate Inference
import numpy as np
from statscore import (
bayes_normal_mean_known_var, bayes_normal_mean_unknown_var,
bayes_beta_binomial, bayes_gamma_poisson,
)
x = np.array([9.8, 10.2, 10.1, 9.9, 10.3, 9.7, 10.0, 10.4])
# Normal-Normal (variance known)
r = bayes_normal_mean_known_var(x, sigma_sq=0.04, mu0=10.0, kappa0=2.0)
r.summary() # 95% CI: (9.916, 10.164)
r.plot().savefig("posterior_normal.png")
# Normal-Gamma (variance unknown)
bayes_normal_mean_unknown_var(x, mu0=10.0, kappa0=1.0,
alpha0=2.0, beta0=0.1).summary()
# Beta-Binomial (success probability from 14/20 successes)
bayes_beta_binomial(n_trials=20, n_successes=14,
alpha0=1.0, beta0=1.0).summary()
# Posterior: Beta(15, 7) mean=0.6818 95% CI=(0.461, 0.858)
# Gamma-Poisson (Poisson rate from count data)
counts = np.array([3, 5, 2, 4, 6, 3, 5, 4])
bayes_gamma_poisson(counts, alpha0=1.0, beta0=1.0).summary()
# Posterior: Gamma(33, 9) mean=3.667
Bayesian MCMC
import numpy as np
from statscore import mcmc_normal_mean_unknown_var, mcmc_linear_regression
x = np.array([9.8, 10.2, 10.1, 9.9, 10.3, 9.7, 10.0, 10.4])
# MCMC for Normal data: joint posterior of (μ, σ)
result = mcmc_normal_mean_unknown_var(
x,
mu_prior_mean=0.0, mu_prior_std=10.0,
sigma_prior_alpha=2.0, sigma_prior_beta=1.0,
n_iter=12000, n_burnin=2000, alpha=0.05, seed=42,
)
result.summary()
# Param Post. Mean Post. Std 2.5% 97.5%
# mu 10.0476 0.0694 9.9116 10.1836
# sigma 0.2315 0.0536 0.1534 0.3590
result.plot().savefig("mcmc_trace.png") # trace + KDE panels
# MCMC for linear regression
X = np.column_stack([np.ones(15), attend, homework])
mcmc_linear_regression(X, y, beta_prior_std=10.0,
sigma_prior_alpha=2.0, sigma_prior_beta=1.0,
n_iter=15000, n_burnin=3000, seed=42).summary()
Diagnostics
from statscore import (
shapiro_wilk_test, levene_test,
regression_diagnostics, mean_confidence_interval,
)
# Normality check before t-test / ANOVA
shapiro_wilk_test(x, alpha=0.05).summary()
# W = 0.9502, p = 0.7121 → Fail to reject H0 (consistent with normality)
# Variance homogeneity check before ANOVA / pooled t-test
levene_test(groups, alpha=0.05).summary()
# Regression diagnostics: influence analysis
diag = regression_diagnostics(X, y)
diag.summary() # flags high-leverage and influential points
diag.plot().savefig("diagnostics.png") # 4-panel: leverage, std resid, Cook's D
# Mean confidence interval
mean_confidence_interval(x, alpha=0.05).summary()
# 95% t-interval for μ: (9.845, 10.255)
Data I/O
from statscore import load_data
result = load_data("experiment.csv")
print(result.format) # "csv"
print(result.n_rows) # 120
print(result.column_names) # ["subject", "group", "score"]
df = result.df # pandas DataFrame
# Extract groups for ANOVA
groups = [df.loc[df["group"] == g, "score"].to_numpy(float)
for g in df["group"].unique()]
Visualization
All plot functions return matplotlib.figure.Figure. Use .savefig() for files or .show() in interactive sessions. Call matplotlib.use("Agg") before importing statscore in headless environments.
import matplotlib; matplotlib.use("Agg")
from statscore import (
plot_regression, plot_residuals, plot_qq, plot_anova_groups,
plot_t_test, plot_f_test, plot_simultaneous_ci, plot_posterior_normal,
)
Shared utilities for building custom figures. Every result dataclass also exposes .plot() which draws a context-appropriate chart automatically.
Package Structure
statscore/
├── __init__.py # Public API — re-exports ~59 symbols; __version__
├── __main__.py # python -m statscore entry point
├── app/
│ ├── __init__.py # Streamlit browser UI — 6 pages
│ └── _launcher.py # statscore-ui console script entry point (subprocess wrapper)
├── plots/
│ └── __init__.py # Shared plot utilities — 8 functions
├── io/
│ └── __init__.py # load_data → LoadedData
├── cli/
│ ├── __init__.py # main(), _MENU_HANDLERS, _print_menu() — 21-item menu
│ ├── _anova.py # _run_one_way_anova, _run_two_way_anova, _run_anova_multiple_comparisons
│ ├── _testing.py # _run_z_test … _run_mean_ci (9 handlers)
│ ├── _regression.py # _run_simple_regression … _run_mcmc_regression (9 handlers)
│ └── _io.py # _parse_data_input, _parse_matrix_input, _parse_raw_string, _parse_groups_input
├── methods/
│ ├── anova/
│ │ ├── _results.py # ANOVA1PartitionResult, ANOVA1TestResult, ANOVA2*, SimultaneousCIResult, SimultaneousTestResult
│ │ ├── one_way.py # anova1_partition_tss, anova1_test_equality
│ │ ├── two_way.py # anova2_partition_tss, anova2_mle, anova2_test_equality
│ │ └── multiple_tests.py # anova1_is_contrast/orthogonal, bonferroni/sidak_correction, anova1_ci/test_linear_combs
│ ├── bayes/
│ │ ├── _results.py # NormalMeanKnownVarResult, NormalMeanUnknownVarResult
│ │ ├── _mcmc_results.py # MCMCResult, ConjugateModelResult
│ │ ├── conjugate.py # bayes_normal_mean_known_var, bayes_normal_mean_unknown_var
│ │ └── mcmc.py # run_mcmc, mcmc_normal_mean_unknown_var, mcmc_linear_regression,
│ │ # bayes_beta_binomial, bayes_gamma_poisson
│ ├── diagnostics/
│ │ ├── _results.py # ShapiroWilkResult, LeveneResult, RegressionDiagnosticsResult, MeanConfidenceIntervalResult
│ │ └── __init__.py # shapiro_wilk_test, levene_test, regression_diagnostics, mean_confidence_interval
│ ├── regression/
│ │ ├── _results.py # OLSResult, PartitionTSSResult, SimultaneousCIBetaResult,
│ │ │ # ConfidenceRegionResult, HypothesisTestResult, PredictionCIResult, RegressionSummaryResult
│ │ ├── least_squares.py # mult_lr_least_squares, mult_lr_partition_tss
│ │ ├── inference.py # mult_norm_lr_simul_ci, mult_norm_lr_cr, mult_norm_lr_is_in_cr,
│ │ │ # mult_norm_lr_test_general, mult_norm_lr_test_comp, mult_norm_lr_test_linear_reg
│ │ ├── prediction.py # mult_norm_lr_pred_ci
│ │ └── summary.py # regression_summary
│ └── testing/
│ ├── _results.py # ZTestResult, TTestOneSampleResult, TTestTwoSampleResult,
│ │ # TTestPairedResult, Chi2VarianceTestResult, FTestVariancesResult
│ ├── one_sample.py # z_test_mean, t_test_mean, chi2_test_variance
│ └── two_sample.py # t_test_two_sample, t_test_paired, f_test_variances
└── utils/
├── enums.py # AlternativeHypothesis, CorrectionMethod, PredictionMethod, TwoWayTestFactor
├── distributions.py # f_critical, t_ppf, chi2_ppf, norm_ppf, q_ppf, p-value helpers
└── validation.py # validate_positive, validate_1d_sample, validate_alternative, …
API Reference
Enums
| Enum | Values | Used by |
|---|---|---|
AlternativeHypothesis |
TWO_SIDED, LESS, GREATER |
All 6 significance tests |
CorrectionMethod |
SCHEFFE, TUKEY, BONFERRONI, SIDAK, BEST |
ANOVA multiple comparisons |
PredictionMethod |
SCHEFFE, BONFERRONI, BEST |
Regression prediction CIs |
TwoWayTestFactor |
A, B, AB |
Two-way ANOVA |
ANOVA
| Function | Returns | Description |
|---|---|---|
anova1_partition_tss(data) |
ANOVA1PartitionResult |
SS_between, SS_within, SS_total |
anova1_test_equality(data, alpha) |
ANOVA1TestResult |
F-test, df, MS, F-critical, p-value |
anova1_is_contrast(c) |
bool |
Checks Σcᵢ = 0 |
anova1_is_orthogonal(n, c1, c2) |
bool |
Checks Σnᵢc₁ᵢc₂ᵢ = 0 |
bonferroni_correction(alpha, m) |
float |
Per-comparison α = α/m |
sidak_correction(alpha, m) |
float |
Per-comparison α = 1−(1−α)^{1/m} |
anova1_ci_linear_combs(data, alpha, C, method) |
SimultaneousCIResult |
Simultaneous CIs for Cμ |
anova1_test_linear_combs(data, alpha, C, d, method) |
SimultaneousTestResult |
Simultaneous tests H₀: Cμ = d |
anova2_partition_tss(data) |
ANOVA2PartitionResult |
SS_A, SS_B, SS_AB, SS_E, SS_T |
anova2_mle(data) |
ANOVA2MLEResult |
μ̂, α̂ᵢ, β̂ⱼ, δ̂ᵢⱼ MLE estimates |
anova2_test_equality(data, alpha, test) |
ANOVA2TestResult |
F-test for A, B, or AB |
Significance Testing
| Function | Returns | Description |
|---|---|---|
z_test_mean(x, mu0, sigma, alpha, alternative) |
ZTestResult |
Z-test (σ known) |
t_test_mean(x, mu0, alpha, alternative) |
TTestOneSampleResult |
One-sample t-test |
chi2_test_variance(x, sigma0_sq, alpha, alternative) |
Chi2VarianceTestResult |
Chi-squared variance test |
t_test_two_sample(x1, x2, alpha, alternative, equal_var) |
TTestTwoSampleResult |
Pooled or Welch t-test |
t_test_paired(x1, x2, alpha, alternative) |
TTestPairedResult |
Paired t-test |
f_test_variances(x1, x2, alpha, alternative) |
FTestVariancesResult |
F-test for σ₁² = σ₂² |
Regression
| Function | Returns | Description |
|---|---|---|
mult_lr_least_squares(X, y) |
OLSResult |
β̂, σ²_MLE, σ²_unbiased, fitted values, residuals |
mult_lr_partition_tss(X, y) |
PartitionTSSResult |
RegSS, RSS, TSS, R², adj R² |
regression_summary(X, y, alpha, feature_names) |
RegressionSummaryResult |
Full OLS table with SE, t, p, CIs, F-test |
mult_norm_lr_simul_ci(X, y, alpha) |
SimultaneousCIBetaResult |
Scheffé simultaneous CIs for all β_i |
mult_norm_lr_cr(X, y, C, alpha) |
ConfidenceRegionResult |
Ellipsoidal CR for Cβ |
mult_norm_lr_is_in_cr(X, y, C, c0, alpha) |
bool |
Is c₀ inside the CR? |
mult_norm_lr_test_general(X, y, C, c0, alpha) |
HypothesisTestResult |
F-test for H₀: Cβ = c₀ |
mult_norm_lr_test_comp(X, y, alpha, components) |
HypothesisTestResult |
F-test for H₀: β_j = 0 (subset) |
mult_norm_lr_test_linear_reg(X, y, alpha) |
HypothesisTestResult |
Overall F-test for regression significance |
mult_norm_lr_pred_ci(X, y, D, alpha, method) |
PredictionCIResult |
Simultaneous prediction CIs for D |
Bayesian Inference
| Function | Returns | Description |
|---|---|---|
bayes_normal_mean_known_var(x, sigma_sq, mu0, kappa0, alpha) |
NormalMeanKnownVarResult |
Normal-Normal conjugate; posterior + predictive |
bayes_normal_mean_unknown_var(x, mu0, kappa0, alpha0, beta0, alpha) |
NormalMeanUnknownVarResult |
Normal-Gamma conjugate; marginal CIs for μ, σ² |
bayes_beta_binomial(n_trials, n_successes, alpha0, beta0, alpha) |
ConjugateModelResult |
Beta posterior for success probability |
bayes_gamma_poisson(x, alpha0, beta0, alpha) |
ConjugateModelResult |
Gamma posterior for Poisson rate |
run_mcmc(log_posterior, init, param_names, n_iter, n_burnin, proposal_std, alpha, model_name, seed) |
MCMCResult |
General Metropolis-Hastings sampler |
mcmc_normal_mean_unknown_var(x, mu_prior_mean, mu_prior_std, sigma_prior_alpha, sigma_prior_beta, n_iter, n_burnin, alpha, seed) |
MCMCResult |
MCMC for Normal data |
mcmc_linear_regression(X, y, beta_prior_mean, beta_prior_std, sigma_prior_alpha, sigma_prior_beta, n_iter, n_burnin, alpha, seed) |
MCMCResult |
MCMC for linear regression |
Diagnostics
| Function | Returns | Description |
|---|---|---|
shapiro_wilk_test(x, alpha) |
ShapiroWilkResult |
Shapiro-Wilk W-statistic; Q-Q plot |
levene_test(data, alpha) |
LeveneResult |
Centre-of-residuals variance homogeneity test |
regression_diagnostics(X, y) |
RegressionDiagnosticsResult |
Leverage h_{ii}, standardized residuals, Cook's D; influence flags |
mean_confidence_interval(x, alpha, sigma) |
MeanConfidenceIntervalResult |
z-interval (σ known) or t-interval |
Visualization
Shared utilities (statscore.plots)
| Function | Description |
|---|---|
plot_regression(x, y, beta_hat, ...) |
Scatter with fitted regression line |
plot_residuals(fitted, residuals, ...) |
Residuals vs fitted values |
plot_qq(x, ...) |
Normal Q-Q plot |
plot_anova_groups(data, group_labels, ...) |
Box plots with jittered data points |
plot_t_test(t_stat, t_crit, df, alternative, ...) |
t-distribution with rejection region |
plot_f_test(f_stat, f_crit_low, f_crit_up, ...) |
F-distribution with rejection region |
plot_simultaneous_ci(point_estimates, intervals, ...) |
CI forest plot |
plot_posterior_normal(result, title) |
Prior vs posterior density (Normal-Normal) |
Result-level .plot() methods
| Result class | Plot output |
|---|---|
ZTestResult |
Standard normal with rejection region |
TTestOneSampleResult |
t-distribution with rejection region |
TTestTwoSampleResult |
t-distribution with rejection region |
TTestPairedResult |
t-distribution with rejection region |
Chi2VarianceTestResult |
χ²-distribution with rejection region |
FTestVariancesResult |
F-distribution with rejection region |
ANOVA1TestResult |
SS bar chart + F-distribution |
ANOVA2TestResult |
SS bar chart + F-distribution |
SimultaneousCIResult |
CI forest plot |
SimultaneousTestResult |
Horizontal bar chart of test statistics |
RegressionSummaryResult |
Coefficient forest plot with CIs |
RegressionDiagnosticsResult |
4-panel: leverage, std residuals, Cook's D, residuals vs leverage |
MeanConfidenceIntervalResult |
Single CI interval plot |
NormalMeanKnownVarResult |
Prior/posterior density with credible interval |
NormalMeanUnknownVarResult |
Marginal posterior (t-distribution) with credible interval |
ShapiroWilkResult |
Normal Q-Q plot |
MCMCResult |
Trace plots + KDE posterior density panels per parameter |
ConjugateModelResult |
Prior vs posterior density (Beta or Gamma) |
Data I/O
| Function | Returns | Description |
|---|---|---|
load_data(path, **kwargs) |
LoadedData |
Loads .csv, .tsv, .xlsx, .xls, .json; kwargs forwarded to pandas |
LoadedData fields: .df (DataFrame), .path, .format, .n_rows, .n_cols, .column_names.
Mathematical Background
One-Way ANOVA
Model: X_{ij} = μ + α_i + ε_{ij}, with Σᵢ nᵢαᵢ = 0 and ε_{ij} ~ N(0,σ²).
| Source | Sum of Squares | df | Mean Square | F |
|---|---|---|---|---|
| Between | SS_B = Σᵢ nᵢ(X̄ᵢ − X̄)² | I−1 | MS_B = SS_B/(I−1) | MS_B/MS_W |
| Within | SS_W = Σᵢ Σⱼ (Xᵢⱼ − X̄ᵢ)² | n−I | MS_W = SS_W/(n−I) | |
| Total | SS_T = SS_B + SS_W | n−1 |
Under H₀, F ~ F(I−1, n−I). Scheffé simultaneous CI half-width for contrast c: √(r · F_{r,n−I,α} · MS_W · c^T(Gram)^{−1}c).
Two-Way ANOVA
Model: X_{ijk} = μ + αᵢ + βⱼ + δᵢⱼ + εᵢⱼₖ, K ≥ 2.
Decomposition: SS_T = SS_A + SS_B + SS_AB + SS_E
Each source tested by its own F-ratio against MS_E = SS_E/(IJ(K−1)).
Normal Distribution Tests
| Test | H₀ | Statistic | Null distribution |
|---|---|---|---|
| Z-test | μ = μ₀ | (x̄ − μ₀)/(σ/√n) | N(0,1) |
| One-sample t | μ = μ₀ | (x̄ − μ₀)/(s/√n) | t(n−1) |
| Chi-squared σ² | σ² = σ₀² | (n−1)s²/σ₀² | χ²(n−1) |
| Two-sample t (pooled) | μ₁ = μ₂ | (x̄₁−x̄₂)/(sₚ√(1/n₁+1/n₂)) | t(n₁+n₂−2) |
| Welch's t | μ₁ = μ₂ | (x̄₁−x̄₂)/√(s₁²/n₁+s₂²/n₂) | t(ν), ν Welch–Satterthwaite |
| Paired t | μ_d = 0 | d̄/(s_d/√n) | t(n−1) |
| F variance | σ₁² = σ₂² | s₁²/s₂² | F(n₁−1, n₂−1) |
Multiple Linear Regression
Model: Y = Xβ + ε, ε ~ N(0, σ²I), X is n×p with intercept column.
Estimators:
- β̂ = (X^TX)^{−1}X^Ty (OLS)
- σ̂² = (y − Xβ̂)^T(y − Xβ̂)/(n−p) (unbiased)
TSS partition: SS_T = SS_Reg + SS_Res, R² = SS_Reg/SS_T, adj R² = 1 − (1−R²)(n−1)/(n−p)
General test H₀: Cβ = c₀ (rank r):
F = (Cβ̂−c₀)^T [C(X^TX)^{−1}C^T]^{−1} (Cβ̂−c₀) / (r·σ̂²) ~ F(r, n−p)
Scheffé simultaneous CI for β_i: β̂ᵢ ± √(p · F_{p,n−p,α} · σ̂² · [(X^TX)^{−1}]ᵢᵢ)
Bayesian Conjugate Models
Normal-Normal (σ² known):
- Prior: μ ~ N(μ₀, σ²/κ₀)
- Posterior: μ|x ~ N(μₙ, σ²/κₙ), κₙ = κ₀ + n, μₙ = (κ₀μ₀ + nx̄)/κₙ
- Predictive: x_new|x ~ N(μₙ, σ²(1 + 1/κₙ))
Normal-Gamma (σ² unknown):
- Prior: (μ,τ) ~ NG(μ₀, κ₀, α₀, β₀)
- Updates: κₙ = κ₀+n, μₙ = (κ₀μ₀+nx̄)/κₙ, αₙ = α₀+n/2, βₙ = β₀+½Σ(xᵢ−x̄)²+κ₀n(x̄−μ₀)²/(2κₙ)
- Marginals: μ|x ~ t(2αₙ, μₙ, √(βₙ/(αₙκₙ))), σ²|x ~ InvGamma(αₙ, βₙ)
Beta-Binomial: p|k ~ Beta(α₀+k, β₀+n−k)
Gamma-Poisson: λ|x ~ Gamma(α₀+Σxᵢ, β₀+n)
Metropolis-Hastings MCMC
Algorithm (random-walk MH):
- Propose θ* = θᵗ + ε, ε ~ N(0, σ²_proposal · I)
- Compute log acceptance ratio: log r = log π(θ*) − log π(θᵗ)
- Set θᵗ⁺¹ = θ* with probability min(1, eˡᵒᵍ ʳ), else θᵗ⁺¹ = θᵗ
Positivity constraints: Parameters in (0,∞) are sampled in log-space. The chain stores log σ; the log-posterior includes the Jacobian log|∂σ/∂(log σ)| = log σ. This keeps proposals Gaussian and avoids boundary issues.
Initialisation: Sample statistics (x̄, log s) for the Normal model; OLS solution for the regression model. Both strategies centre the chain near the posterior mode, reducing required burn-in.
Diagnostics: Acceptance rate (target 0.15–0.50), trace plots (check for mixing and stationarity), KDE posterior density (check for unimodality).
Development
pip install -e ".[dev,ui]"
pytest tests/ -v # 205 tests across 12 test files
ruff check . # linting
mypy statscore/ # static type checking
python examples/demo.py # end-to-end function demos
statscore # interactive CLI
statscore-ui # launch browser UI at http://localhost:8501
Test organisation
| Test file | Coverage |
|---|---|
test_anova_one_way.py |
anova1_* functions, contrast utilities |
test_anova_two_way.py |
anova2_* functions, MLE estimates |
test_bayes_conjugate.py |
All 4 conjugate models |
test_cli.py |
CLI menu, handler imports, data parsing |
test_diagnostics.py |
shapiro_wilk_test, levene_test, regression_diagnostics, mean_ci |
test_io.py + test_io_fixtures.py |
load_data for all 5 formats |
test_plots.py |
All shared plot utilities |
test_regression.py |
OLS, TSS partition, inference, prediction |
test_regression_summary.py |
regression_summary table |
test_testing_one_sample.py |
z_test_mean, t_test_mean, chi2_test_variance |
test_testing_two_sample.py |
t_test_two_sample, t_test_paired, f_test_variances |
License
MIT
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file statscore-0.0.3.tar.gz.
File metadata
- Download URL: statscore-0.0.3.tar.gz
- Upload date:
- Size: 107.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a855d82c07d7d60d6b2b3500c8804d7ba7b96407d73b123f7e8a21df9bbd0080
|
|
| MD5 |
352957a66674ceecedd7f5d349e282af
|
|
| BLAKE2b-256 |
863b8ffbafdd490a00172256dbdafe3ec4a134a2284416c8ac4becd2cbb82d76
|
Provenance
The following attestation bundles were made for statscore-0.0.3.tar.gz:
Publisher:
publish.yml on furkankyildirim/statscore
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
statscore-0.0.3.tar.gz -
Subject digest:
a855d82c07d7d60d6b2b3500c8804d7ba7b96407d73b123f7e8a21df9bbd0080 - Sigstore transparency entry: 1758021103
- Sigstore integration time:
-
Permalink:
furkankyildirim/statscore@c454890433d56ff439b38b0ada5eebd3a0fe5200 -
Branch / Tag:
refs/tags/v0.0.3 - Owner: https://github.com/furkankyildirim
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@c454890433d56ff439b38b0ada5eebd3a0fe5200 -
Trigger Event:
push
-
Statement type:
File details
Details for the file statscore-0.0.3-py3-none-any.whl.
File metadata
- Download URL: statscore-0.0.3-py3-none-any.whl
- Upload date:
- Size: 86.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
fd8dd3e0f3ecd5a7199895a32e795c7fa2713160417726dfd6dac7054d70efd5
|
|
| MD5 |
836fae089bec531868c9d1bcf3c97d80
|
|
| BLAKE2b-256 |
9dfe380ac84693fcb28d024e5641b194d8f519ac1c23bf3bfbebd98195be1c9c
|
Provenance
The following attestation bundles were made for statscore-0.0.3-py3-none-any.whl:
Publisher:
publish.yml on furkankyildirim/statscore
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
statscore-0.0.3-py3-none-any.whl -
Subject digest:
fd8dd3e0f3ecd5a7199895a32e795c7fa2713160417726dfd6dac7054d70efd5 - Sigstore transparency entry: 1758021178
- Sigstore integration time:
-
Permalink:
furkankyildirim/statscore@c454890433d56ff439b38b0ada5eebd3a0fe5200 -
Branch / Tag:
refs/tags/v0.0.3 - Owner: https://github.com/furkankyildirim
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@c454890433d56ff439b38b0ada5eebd3a0fe5200 -
Trigger Event:
push
-
Statement type: