EDA & leakage¶
parleml_mli.eda is a data-level exploratory analysis package: correlations,
distributions, missingness, outliers, duplicates, consolidated alerts, and a
leakage scanner. It works on any frame — no model required. The canonical
entry point is compute_eda.
In short
compute_eda(X, y=y)works on any frame; no model needed.- It profiles a 20,000-row sample by default. Duplicates, rarity and unlabelled-row checks read the full frame.
- The leakage scan flags six kinds of suspicious feature, such as near-perfect target separation, ID-like columns and dates recorded after the outcome.
- Associations share one bias-corrected
|r|scale: Pearson, Cramér's V and η. - Leakage findings feed the trust summary's leakage tile.
Agent access
The EDA artifact is exposed to AI agents as the MCP tool get_eda
(sections + per-column drill) plus the eda.* chart family — see the
ParleML MCP docs site (parleml_mcp/docs/).
Two ways in¶
As part of profiling — set ProfilingConfig(eda=EDAConfig(...)) and read
result.eda_:
from parleml_mli import ProfilingConfig, EDAConfig, fit_profiler
config = ProfilingConfig(eda=EDAConfig())
result = fit_profiler(
model=clf, X=X_train, y=y_train,
target_mask=(y_train == 1), config=config,
)
eda = result.eda_
Standalone — call compute_eda on any frame:
from parleml_mli import compute_eda
eda = compute_eda(X_train, y=y_train)
eda.table # TableStats: rows, columns, missing %, duplicates
eda.variables # per-column VariableStats
eda.correlation_matrix # numeric + categorical correlation matrix
eda.alerts # consolidated data-quality alerts
eda.leakage_report # suspicious-feature findings (see below)
What runs on the sample, and what on the full frame¶
compute_eda profiles a working sample (sample_size, default 20,000 rows)
with fg-data-profiling
(import data_profiling) and mli's own kernels. The profiler runs with its
usage telemetry switched off (YDATA_PROFILING_NO_ANALYTICS), so profiling a
dataset never sends anything over the network. A few checks need every row
and read the full frame instead:
- Duplicate rows — one pass finds them:
table.n_duplicate_rowscounts the rows that repeat an earlier row (1,000 identical rows count 999), theDUPLICATESalert reports that count, andduplicates_dflists the largest groups.duplicates_kwargs={"subset": [...]}defines a duplicate by those columns for all three. - Rarity — a
CONSTANTalert from the sample is dropped when the column varies in the full frame, and anID_LIKENESSfinding confirms its cardinality there. - Unlabelled rows — a row without a target value is not an extra target
class. Target correlations, the target tie-break between over-correlated
features and the leakage scan's target checks read the labelled rows only
(and are skipped when no row is labelled); one
MISSINGalert on the target counts the unlabelled rows of the full frame.
Target and matrix associations share one |r| scale: Pearson for
numeric pairs, Cramér's V for categorical pairs and the correlation ratio η for
mixed pairs. Both categorical measures are bias-corrected — Cramér's V by
Bergsma–Wicher, η as the square root of Kelley's ε² (the adjusted η²) — so a
high-cardinality categorical does not read as associated with pure noise; a
categorical with more levels than half the rows gets no η (NaN).
Configuration¶
compute_eda takes either a prebuilt EDAConfig
or field overrides as **kwargs:
from parleml_mli.eda import EDAConfig
cfg = EDAConfig(sample_size=50_000, correlations_enabled=True, leakage_enabled=True)
eda = compute_eda(X_train, y=y_train, config=cfg)
# …or override individual fields inline:
eda = compute_eda(X_train, y=y_train, sample_size=50_000, outliers_enabled=False)
Runtime depends on row count, column types, cardinality and enabled checks. Every
artifact has an on/off toggle (univariate_enabled, missingness_enabled,
outliers_enabled, …) and a *_kwargs sub-config. See the full table on the
Configuration parameters
page.
Leakage scanning¶
When leakage_enabled=True (the default), compute_eda runs
detect_suspicious_features as its final step and attaches the result to
eda.leakage_report. It flags six finding kinds:
| Finding | Trigger |
|---|---|
SINGLE_VALUE |
Fewer than two distinct values — a constant column. |
HIGH_CARDINALITY |
A categorical / text column whose distinct values come close to the row count (never a number, boolean or timestamp). |
ID_LIKENESS |
Near-unique cardinality (leakage_id_cardinality_threshold) plus an ID-shaped value or name — looks like a row id, not a feature. |
TARGET_CORRELATION_EXTREME |
|correlation| with the target ≥ leakage_target_correlation_threshold (default 0.99), or, for a binary target, a numeric feature that alone separates the classes with ROC AUC ≥ leakage_binary_auc_threshold (default 0.98, either direction; scored when each class has at least 30 labelled rows). |
NEAR_DUPLICATE_PROXY |
A feature is a near-perfect proxy for the target (leakage_near_duplicate_threshold). |
POST_OUTCOME_DATE |
A datetime feature is later than time_column on a high share of rows — recorded after the outcome. |
The target checks read the labelled rows only; the other detectors read every row.
eda = compute_eda(X_train, y=y_train, time_column="event_ts")
for finding in eda.leakage_report.findings:
print(finding.kind, finding.columns, finding.suggested_action, finding.description)
You can also run the scanner directly without a full EDA pass — on a frame that carries the target column:
from parleml_mli.eda import detect_suspicious_features
report = detect_suspicious_features(train_df, target="is_fraud")
Plots¶
EDAResult carries plot helpers that return plotly figures on demand:
The row-level AutoViz figures — correlated pairs, category boxplots, the PCA
biplot and parallel coordinates — draw sampled rows of the dataset, so the
result stores none of their data: build them from the frame the EDA ran on with
parleml_mli.eda.render_autoviz_figure(kind, df, result=eda) (seeded from
eda.config, so a figure is identical across calls). The shape radar is drawn
from the result itself (eda.plot_shape_radar()).
Persisted results¶
An EDAResult carries schema_version (parleml_mli.eda.EDA_SCHEMA_VERSION). One
written under another schema is refused on load — unpickling it (e.g. inside a
saved profile) and EDAResult.from_dict both raise
parleml_mli.StaleArtifactError: re-run compute_eda on the dataset. The
platform treats such a cached EDA as absent and recomputes it on the next
Run EDA.
In the platform¶
The product's Dataset EDA / Leakage panels are powered by compute_eda +
detect_suspicious_features, and the leakage findings feed the
Trust Summary leakage tile.
Next¶
- Evaluation, trust & model cards: where the leakage findings are graded.
- Interactive visualizations: every EDA chart.