Metadata-Version: 2.4
Name: multvar
Version: 0.1.0
Summary: Classical multivariate analysis, ANOVA, and MANOVA for Python
Author: Ricardo Antunes
Maintainer: Ricardo Antunes
License-Expression: MIT
Project-URL: Homepage, https://github.com/Rictunes/Multvar
Project-URL: Documentation, https://github.com/Rictunes/Multvar#readme
Project-URL: Repository, https://github.com/Rictunes/Multvar.git
Project-URL: Issues, https://github.com/Rictunes/Multvar/issues
Project-URL: Changelog, https://github.com/Rictunes/Multvar/blob/main/CHANGELOG.md
Project-URL: Technical reference, https://doi.org/10.1002/9781118391686
Keywords: multivariate analysis,ANOVA,MANOVA,Hotelling T2,PCA,statistics
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Education
Classifier: Intended Audience :: Science/Research
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Classifier: Topic :: Scientific/Engineering :: Mathematics
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
License-File: CREDITS.md
Requires-Dist: numpy>=1.23
Requires-Dist: pandas>=1.5
Requires-Dist: scipy>=1.9
Requires-Dist: statsmodels>=0.14
Requires-Dist: scikit-learn>=1.2
Provides-Extra: plot
Requires-Dist: matplotlib>=3.7; extra == "plot"
Provides-Extra: dev
Requires-Dist: build>=1.2; extra == "dev"
Requires-Dist: pytest>=8; extra == "dev"
Requires-Dist: pytest-cov>=5; extra == "dev"
Requires-Dist: twine>=6; extra == "dev"
Dynamic: license-file

# MultVar

[![CI](https://github.com/Rictunes/Multvar/actions/workflows/ci.yml/badge.svg)](https://github.com/Rictunes/Multvar/actions/workflows/ci.yml)
[![PyPI](https://img.shields.io/pypi/v/multvar.svg)](https://pypi.org/project/multvar/)
[![Python](https://img.shields.io/pypi/pyversions/multvar.svg)](https://pypi.org/project/multvar/)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)

`multvar` is an open-source Python package for classical multivariate analysis,
with a particularly direct API for ANOVA and MANOVA. It combines transparent
statistical result objects with NumPy, pandas, SciPy, statsmodels and
scikit-learn.

The package is an independent implementation. The book *Methods of Multivariate
Analysis*, Third Edition, by Alvin C. Rencher and William F. Christensen was
used as a technical reference. The project is not affiliated with or endorsed
by the authors or publisher, and no book text or companion data are distributed.

## Installation

```bash
python -m pip install multvar
```

For plots used in your own notebooks:

```bash
python -m pip install "multvar[plot]"
```

## Quick start: MANOVA with `iris`

```python
import multvar as mv

iris = mv.load_dataset("iris")
responses = ["Sepal.Length", "Sepal.Width", "Petal.Length", "Petal.Width"]

result = mv.one_way_manova(iris, responses, "Species")
print(result.summary_frame())

# Response-wise ANOVAs with Holm multiplicity correction
print(mv.manova_followup(iris, responses, "Species"))
```

The MANOVA output includes all four classical criteria:

- Wilks' lambda
- Pillai's trace
- Hotelling-Lawley trace
- Roy's greatest root

## Quick start: ANOVA

```python
import pandas as pd
import multvar as mv

data = pd.DataFrame({
    "score": [5, 6, 7, 8, 9, 10, 12, 13, 14],
    "treatment": ["A"] * 3 + ["B"] * 3 + ["C"] * 3,
})

classical = mv.one_way_anova(data, "score", "treatment")
robust = mv.welch_anova(data, "score", "treatment")
diagnostics = mv.anova_assumptions(data, "score", "treatment")

print(classical.estimates["table"])
print(robust)
print(diagnostics)
```

## Public function reference

All functions below are available directly from the `multvar` namespace, for
example `multvar.one_way_manova(...)`.

| Area | Function | Description |
|---|---|---|
| Datasets | `available_datasets()` | Lists the packaged datasets together with their descriptions and sources. |
| Datasets | `dataset_info(name)` | Returns provenance and metadata for one packaged dataset. |
| Datasets | `load_dataset(name)` | Loads `cars` or `iris` as a pandas DataFrame. |
| Descriptive analysis | `multivariate_summary(data)` | Calculates the mean vector, covariance and correlation matrices, generalized variance and total variance. |
| Descriptive analysis | `mahalanobis_distances(data)` | Calculates observation distances from the multivariate centroid using the sample covariance matrix. |
| Descriptive analysis | `pooled_covariance(data, variables, group)` | Calculates the within-group pooled covariance matrix. |
| Normality and outliers | `univariate_normality(data)` | Applies the Shapiro-Wilk normality test to every variable. |
| Normality and outliers | `mardia_test(data)` | Performs Mardia's multivariate skewness and kurtosis tests. |
| Normality and outliers | `multivariate_outliers(data)` | Detects observations using Mahalanobis distances and chi-square tail probabilities. |
| Mean vectors | `known_covariance_mean_test(data, mean, covariance)` | Tests a population mean vector when its covariance matrix is known. |
| Mean vectors | `one_sample_hotelling_t2(data, mean)` | Performs the one-sample Hotelling T² test. |
| Mean vectors | `two_sample_hotelling_t2(x, y)` | Compares two mean vectors using a pooled-covariance Hotelling T² test. |
| Mean vectors | `paired_hotelling_t2(before, after)` | Performs a paired multivariate test on within-pair differences. |
| Mean vectors | `profile_test(data)` | Tests flatness of a one-sample multivariate response profile. |
| Mean vectors | `two_sample_profile_test(x, y)` | Tests parallelism of two multivariate response profiles. |
| Mean vectors | `bonferroni_mean_intervals(data)` | Produces simultaneous Bonferroni confidence intervals for mean components. |
| ANOVA | `one_way_anova(data, response, group)` | Performs classical fixed-effects one-way ANOVA and returns a complete ANOVA table. |
| ANOVA | `welch_anova(data, response, group)` | Performs Welch's heteroscedastic one-way ANOVA. |
| ANOVA | `two_way_anova(data, response, factor_a, factor_b)` | Fits a two-factor ANOVA with optional interaction and Type II or III sums of squares. |
| ANOVA | `one_way_contrast(data, response, group, coefficients)` | Tests a planned contrast among one-way ANOVA group means. |
| ANOVA | `anova_assumptions(data, response, group)` | Runs Shapiro-Wilk, Levene and Bartlett diagnostics for a one-way ANOVA. |
| ANOVA | `tukey_hsd(data, response, group)` | Performs Tukey HSD pairwise comparisons. |
| ANOVA | `repeated_measures_anova(data, response, subject, within)` | Fits a within-subject repeated-measures ANOVA. |
| MANOVA | `manova(data, responses, formula_rhs)` | Fits a general formula-based MANOVA and reports Wilks, Pillai, Hotelling-Lawley and Roy statistics. |
| MANOVA | `one_way_manova(data, responses, group)` | Fits a balanced or unbalanced one-factor MANOVA. |
| MANOVA | `two_way_manova(data, responses, factor_a, factor_b)` | Fits a two-factor MANOVA with an optional interaction. |
| MANOVA | `manova_followup(data, responses, group)` | Runs response-wise ANOVAs with Holm multiplicity correction after an overall MANOVA. |
| MANOVA | `multivariate_contrast(fitted, name, contrast)` | Tests a custom coefficient contrast and optional response transformation in a fitted MANOVA. |
| Covariance tests | `covariance_matrix_test(data, covariance)` | Tests whether the population covariance equals a specified matrix. |
| Covariance tests | `box_m_test(data, variables, group)` | Applies Box's M test for equality of group covariance matrices. |
| Covariance tests | `bartlett_sphericity_test(data)` | Tests whether the population correlation matrix is the identity matrix. |
| Covariance tests | `covariance_sphericity_test(data)` | Tests the covariance structure Sigma = sigma² I. |
| Covariance tests | `mauchly_sphericity_test(data)` | Tests sphericity of wide-format repeated measurements. |
| Covariance tests | `compound_symmetry_test(data)` | Tests an equal-variance, common-covariance compound-symmetry structure. |
| Covariance tests | `block_independence_test(data, first, second)` | Tests independence between two variable subvectors. |
| Regression | `multivariate_regression(predictors, responses)` | Fits a multivariate multiple regression by least squares. |
| Regression | `multivariate_regression_test(data, responses, predictors)` | Produces overall and term-wise multivariate tests for a regression model. |
| Canonical correlation | `canonical_correlation(x, y)` | Computes canonical correlations, weights, scores and sequential Wilks tests. |
| Canonical correlation | `redundancy_indices(result, x, y)` | Calculates Stewart-Love variance-extraction and redundancy indices. |
| Dimension reduction | `principal_components(data)` | Performs covariance- or correlation-based principal component analysis. |
| Dimension reduction | `parallel_analysis(data)` | Performs Horn's simulated parallel analysis for component retention. |
| Dimension reduction | `kmo(data)` | Calculates overall and variable-wise Kaiser-Meyer-Olkin adequacy measures. |
| Factor analysis | `exploratory_factor_analysis(data, n_factors)` | Fits maximum-likelihood exploratory factor analysis with optional varimax rotation. |
| Factor analysis | `varimax(loadings)` | Applies an orthogonal varimax rotation to a loading matrix. |
| Factor analysis | `cfa_fit_indices(observed_covariance, implied_covariance, ...)` | Evaluates a fitted CFA covariance model with chi-square, CFI, TLI, RMSEA and SRMR. |
| Discrimination | `linear_discriminant_analysis(features, groups)` | Fits a linear discriminant classifier. |
| Discrimination | `quadratic_discriminant_analysis(features, groups)` | Fits a quadratic discriminant classifier. |
| Discrimination | `discriminant_significance(features, groups)` | Performs sequential Wilks-lambda tests for canonical discriminant roots. |
| Classification | `cross_validated_classification(estimator, features, groups)` | Calculates stratified cross-validated classification accuracy and predictions. |
| Cluster analysis | `distance_matrix(data)` | Calculates a pairwise observation-distance matrix. |
| Cluster analysis | `hierarchical_clustering(data)` | Builds an agglomerative hierarchy using SciPy linkage methods. |
| Cluster analysis | `kmeans_clustering(data, n_clusters)` | Fits a K-means partition with optional standardization. |
| Cluster analysis | `cluster_validity(data, labels)` | Calculates silhouette, Calinski-Harabasz and Davies-Bouldin indices. |
| Cluster analysis | `choose_cluster_count(data, candidates)` | Compares candidate K-means solutions using inertia and validity indices. |
| Ordination | `correspondence_analysis(table)` | Performs simple correspondence analysis and a Pearson independence test. |
| Ordination | `multidimensional_scaling(data)` | Performs metric or nonmetric multidimensional scaling. |

## Formula-based MANOVA

Use `manova` when you need covariates, nesting, transformations or another
statsmodels/Patsy formula:

```python
result = mv.manova(
    data=my_data,
    responses=["y1", "y2", "y3"],
    formula_rhs="C(treatment) * C(block) + age",
)
print(result.summary_frame("C(treatment)"))
```

For ordinary factor names, `one_way_manova` and `two_way_manova` automatically
quote unusual column names such as `Sepal.Length`.

## Datasets

Only datasets with clear, independent public provenance are packaged:

```python
mv.available_datasets()
cars = mv.load_dataset("cars")
iris = mv.load_dataset("iris")
```

`cars` and `iris` are the classic datasets distributed with R. Their source
pages are recorded by `dataset_info`. The companion datasets from the reference
book are intentionally not included because an explicit redistribution license
was not identified.

## Interpretation and numerical responsibility

Multivariate tests rely on assumptions such as independent observations,
appropriate design specification, sufficient sample size and nonsingular
covariance matrices. A small p-value is not an effect size and does not establish
practical importance. Inspect diagnostics, uncertainty and the study design.

Most likelihood-ratio, Mardia, covariance-structure, canonical-root and CFA
tests use asymptotic approximations. The method name and degrees of freedom are
included in each result so analyses can be audited.

## Development

```bash
git clone https://github.com/Rictunes/Multvar.git
cd MultVar
python -m venv .venv
python -m pip install -e ".[dev]"
python -m pytest
```

See [CONTRIBUTING.md](CONTRIBUTING.md) and [CREDITS.md](CREDITS.md).

## License

The software is released under the [MIT License](LICENSE). Dataset provenance
and reference credits are documented separately in [CREDITS.md](CREDITS.md).
