Skip to main content

pycatdap

PyPI version Python versions CI Docs License: MIT

AIC-based EDA and ML error analysis library for categorical data.

pycatdap is a Python implementation of CATDAP (CATegorical Data Analysis Program), developed by Sakamoto & Katsura (1980) at the Institute of Statistical Mathematics. It extends the classic CATDAP toolkit with modern exploratory data analysis (EDA) and machine learning error analysis workflows.

📖 Documentation: https://nbx-liz.github.io/pycatdap/

Why pycatdap?

Unlike general profilers (ydata-profiling, Skrub) or slice discovery tools (DivExplorer, pysubgroup), pycatdap uses AIC as its core relevance measure. This gives it four unique advantages:

Feature Most tools pycatdap
Variable relevance Cramér's V, mutual info AIC — explicit info-vs-complexity trade-off
Continuous binning Equal-width or quantile AIC-optimal binning
Subset discovery Feature importance ranking CATDAP-02 combinatorial search
Model coupling Tied to specific frameworks Model-agnostic (works with y_true, y_pred from anywhere)

Installation

# Core
pip install pycatdap

# With visualization (matplotlib)
pip install "pycatdap[plot]"

# With interactive Plotly figures + HTML reports
pip install "pycatdap[plotly]"

Supported: Python 3.10 / 3.11 / 3.12 / 3.13

Quickstart

Classic CATDAP

import pycatdap

df = pycatdap.datasets.load_heart_disease()

# CATDAP-01: pairwise AIC on the coded-categorical columns
cat = df[["target", "sex", "cp", "exang", "thal"]]
result = pycatdap.catdap1(cat, response_names=["target"])
print(result.aic_order["target"])  # variables ranked by ΔAIC

# CATDAP-02: best explanatory subset (continuous columns auto-pooled)
result2 = pycatdap.catdap2(
    df,
    #     age sex cp trestbps chol fbs restecg thalach exang oldpeak slope ca thal target
    pool=[1, 2, 2, 1, 1, 2, 2, 1, 2, 1, 2, 2, 2, 2],
    response_name="target",
    nvar=6,
)
for s in result2.subsets[:3]:
    print(f"AIC={s.aic:.2f}, vars={s.variables}")

One-call EDA report (v0.5+)

report = pycatdap.profile(df, response="target")
report.show()                       # Jupyter inline
report.to_html("report.html")       # self-contained HTML, inline Plotly
report.to_dict()                    # JSON-friendly
report.to_plotly_json()             # react-plotly.js / LizyStudio

ProfileResult exposes overview, variables (one VariableCard per column, including ΔAIC vs the response), association (m × m ΔAIC matrix), top_subsets (CATDAP-02 result when response is given), and quality_warnings (high_cardinality / constant / id_candidate / high_missing with overridable thresholds). See docs/tutorials/08-profile-titanic.ipynb for an end-to-end walkthrough.

Target analysis and CI-integrable suite (v0.6+)

# Target-driven: rank every column by ΔAIC vs `response`, keep top-K cross-tabs
ta = pycatdap.target_analysis(df, response="symptoms", top_k=5)
ta.ranking                         # variable / delta_aic / kind / n_obs
ta.top_summaries["cholesterol"]    # full TargetSummary for drill-down

# Quality scan only (fast — no catdap2 / association_matrix)
qr = pycatdap.quality_report(df)
assert qr.passed, qr.show()

# CI gate: one-line data contract
suite = pycatdap.suite.AICIndependenceSuite(df, response="symptoms")
result = suite.run()
assert result.passed, result.summary()

# Non-AIC association measures (pure-numpy, no scipy)
m = pycatdap.association_matrix(df, measure="cramers_v")
pycatdap.measures.register("my_measure", my_fn)  # pluggable per pysubgroup convention

See docs/tutorials/09-target-analysis-and-quality-suite.ipynb.

ML error labelling (v0.7.0)

from pycatdap.datasets import load_german_credit

df = load_german_credit()
y_true = df["class"]
y_pred = my_model.predict(df.drop(columns=["class"]))

# Label every prediction "correct" / "incorrect"
labels = pycatdap.error.error_label(y_true, y_pred)

# Or get fine-grained TP / FP / FN / TN (binary classification only)
conf = pycatdap.error.confusion_label(y_true, y_pred, positive="bad")

# Feed the error label back into target_analysis to discover which columns
# explain the errors — foundation for v0.8.0 `error_analysis()`
ta = pycatdap.target_analysis(df.assign(was_correct=labels), response="was_correct")

See docs/tutorials/10-ml-error-labeling.ipynb.

One-call ML error analysis (v0.8.0)

# task auto-detected from y_true / y_pred dtypes
result = pycatdap.error_analysis(
    df=test_df,
    y_true=y_test,                                  # str column name or array
    y_pred=model.predict(X_test),                   # str column name or array
    top_k=5,
)
result.show()                                       # Jupyter / stdout summary
result.to_html("errors.html")                       # self-contained Plotly report
result.feature_ranking                              # ΔAIC ranking of explanatories
result.top_slices                                   # single-variable cohort slices
result.confusion                                    # canonical TP/FP/FN/TN (binary)
result.to_divexplorer_format()                      # DivExplorer-compatible DataFrame

# Larger fairness-relevant benchmarks (needs `pip install 'pycatdap[data]'`)
df = pycatdap.datasets.fetch_california_housing()   # regression
df = pycatdap.datasets.fetch_adult_income()         # fairness demo
df = pycatdap.datasets.fetch_compas()               # fairness demo

See docs/tutorials/11-ml-error-analysis-one-call.ipynb.

ML error visualisation (v0.9.0)

r = pycatdap.error_analysis(df, y_true, y_pred)

# Result delegation — visualise straight off the result
r.plot_confusion()                                  # binary OR multi-class
r.plot_confusion(backend="plotly", normalize="true")
r.residual_plot()                                   # regression

# Or call the standalone functions
pycatdap.error.plot_confusion(y_true, y_pred, labels=[0, 1], normalize="true")
pycatdap.error.plot_confusion_by_slice(df, y_true, y_pred, var="age_group")
pycatdap.error.confusion_aic(y_true, y_pred)        # ΔAIC, negative = informative

pycatdap.error.residual_plot(y_true, y_pred, kind="histogram")
pycatdap.error.residual_by_category(df, y_true, y_pred, "feature")
pycatdap.error.residual_pool_plot(y_true, y_pred, n_bins=4)

See docs/tutorials/12-ml-error-visualization.ipynb.

ML calibration (v0.10.0)

r = pycatdap.error_analysis(df, y_true, y_pred, y_proba=proba)  # binary classification
r.calibration_curve(strategy="aic")                 # reliability diagram (AIC-binned)

# Or call the standalone functions
pycatdap.error.calibration_curve(y_true, proba, strategy="aic", backend="plotly")
pycatdap.error.brier_score(y_true, proba)
pycatdap.error.expected_calibration_error(y_true, proba)   # ECE
pycatdap.error.maximum_calibration_error(y_true, proba)    # MCE

strategy="aic" bins the probability axis where the observed positive-rate shifts — sharper than equal-width / quantile bins on skewed predictions. See docs/tutorials/13-ml-calibration.ipynb.

ML slice discovery, cohort comparison & drift (v0.11.0)

# Auto-discover the multivariable cohorts where the model fails most
result = pycatdap.error.discover_error_slices(
    df, y_true, y_pred, max_vars=3, measure="aic", top_k=10, min_support=30
)
for s in result.slices:
    print(s.error_metric, s.description)   # e.g. "age ∈ [60, 78] × plan = basic"
result.to_divexplorer_format()             # DivExplorer-compatible flat table

# Compare two cohorts (distribution + ΔAIC), Sweetviz-style HTML report
pycatdap.error.compare_cohorts(df_a, df_b).to_html("comparison.html")

# Detect train→prod drift, ranked by ΔAIC magnitude
pycatdap.error.detect_drift(df_train, df_prod, y_true=y, y_pred=yhat)

# Calibration beyond binary classification
pycatdap.error.regression_calibration_table(y_true, y_pred)          # regression
pycatdap.error.multiclass_calibration_table(y_true, y_proba)         # one-vs-rest

Slice discovery prunes the search space on support (Apriori, anti-monotone) rather than ΔAIC — sound, and >50% reduction on wide datasets. The interestingness measure is pluggable ("aic", "cramers_v", "mutual_info", or any registered callable). See docs/tutorials/14-ml-slice-discovery-and-drift.ipynb.

Status & Roadmap

Version Theme
v0.2.0 ✅ Core CATDAP-01/02 (released)
v0.3.0 — v0.6.0 ✅ EDA workflow (Plotly backend, profile, target analysis)
v0.7.0 ✅ error labelling building blocks
v0.8.0 ✅ one-call error_analysis() + benchmark datasets
v0.9.0 ✅ error visualisation (confusion + residual)
v0.10.0 ✅ calibration (AIC-binned reliability diagram + Brier/ECE/MCE)
v0.11.0 ✅ slice discovery + cohort comparison + drift + regression/multi-class calibration
v0.12.0 LizyStudio integration
v1.0.0 API stabilization

Full roadmap: PLAN.md · Meta Issue #11

Development

git clone https://github.com/nbx-liz/pycatdap.git
cd pycatdap
uv sync --all-groups
uv run pytest                                  # tests (excluding slow R cross-validation)
uv run pytest -m slow                          # slow tests (requires R + catdap package)
uv run python -m mkdocs serve                  # local docs preview
make ci                                        # ruff + mypy + pytest + build

Contributing guidelines: CONTRIBUTING.md

Project structure

Document Purpose
BLUEPRINT.md Canonical specification (Japanese)
HISTORY.md Proposal-to-decision log (Japanese)
PLAN.md Development roadmap (Japanese)
CHANGELOG.md Release history
docs/ Published documentation site

Citation

If you use pycatdap in research, please cite the original CATDAP work:

@article{sakamoto1980categorical,
  title={Categorical Data Analysis by AIC},
  author={Sakamoto, Yosiyuki and Katsura, Koichi},
  journal={Mathematical Sciences},
  year={1980}
}

License

MIT

Metadata

Release files for pycatdap 0.14.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for pycatdap 0.14.0
File Size Uploaded
pycatdap-0.14.0.tar.gz 684.1 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for pycatdap 0.14.0
File Interpreter ABI Platform
pycatdap-0.14.0-py3-none-any.whl Python 3 none any Details

Total release size: 875.1 kB

Release files / pycatdap-0.14.0.tar.gz

Download URL pycatdap-0.14.0.tar.gz
Size 684.1 kB
Tags Source
SHA-256 checksum
How to use checksums
2b04739c7ec6060c9ead20244ec0e420ffafa8e77590c7426ba95b803729f8ca
BLAKE2b-256 checksum
How to use checksums
4f9660f245f8a4082ad487db8691fcc8e56b031a40c2291a28529116dec8d46f
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jun 7, 2026.

Transparency log

Release files / pycatdap-0.14.0-py3-none-any.whl

Download URL pycatdap-0.14.0-py3-none-any.whl
Size 190.9 kB
Tags Python 3
SHA-256 checksum
How to use checksums
3707785257d5ac83855ca50c25483401630b49bed1b04517d52ffac261d70cf8
BLAKE2b-256 checksum
How to use checksums
0e5175019ff2d1a163fadf73bc5d94f79e65528583513062681ab014e5469d3b
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jun 7, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.14.0 This release

2 release files

0.12.1

2 release files

0.12.0

2 release files

0.11.0

2 release files

0.10.0

2 release files

0.9.0

2 release files

0.8.0

2 release files

0.7.0

2 release files

0.6.1

2 release files

0.6.0

2 release files

0.5.0

2 release files

0.4.0

2 release files

0.3.0

2 release files

0.2.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page