Skip to content

Examples

Cross-validation benchmark

A full 5-fold stratified cross-validation loop that injects 30% MAR missing values and evaluates imputation quality via MAE.

import pandas as pd
from sklearn.model_selection import StratifiedKFold
from sklearn.preprocessing import MinMaxScaler
from tabrag_xai_imputer import RAGImputer
from mdatagen.multivariate.mMAR import mMAR

df = pd.read_csv("data/pima-indians-diabetes/pima_diabetes.csv")
X = df.drop(columns="target")
y = df["target"].values

cv = StratifiedKFold(n_splits=5, shuffle=True, random_state=42)

for fold, (train_idx, test_idx) in enumerate(cv.split(X.values, y), start=1):
    X_train = pd.DataFrame(X.values[train_idx], columns=X.columns)
    X_test  = pd.DataFrame(X.values[test_idx],  columns=X.columns)

    # Normalise — fit on train only to prevent data leakage
    scaler = MinMaxScaler().fit(X_train)
    X_train_norm = pd.DataFrame(scaler.transform(X_train), columns=X.columns)
    X_test_norm  = pd.DataFrame(scaler.transform(X_test),  columns=X.columns)

    # Inject 30% MAR missing values
    X_test_missing = (
        mMAR(X=X_test_norm, y=y[test_idx], n_xmiss=X_test_norm.shape[1])
        .random(missing_rate=30)
        .drop(columns="target")
    )

    # Fit and impute
    imputer = RAGImputer(
        n_neighbors=10,
        llm_api="gemini",
        llm_model_name="gemini-2.0-flash",
        dataset_name="Pima Indians Diabetes",
    )
    imputer.fit(X_train_norm)
    X_imputed = imputer.transform(X_test_missing)

    # MAE on imputed positions only
    mae = np.abs(X_imputed[mask] - X_test_norm.values[mask]).mean()
    print(f"Fold {fold} — MAE: {mae:.4f}")

Explainability walkthrough

Demonstrate .explain() on a held-out test set with artificially injected MCAR missing values.

import numpy as np
import pandas as pd
from sklearn.model_selection import train_test_split
from tabrag_xai_imputer import RAGImputer
from mdatagen.multivariate.mMCAR import mMCAR

DATASET_NAME = "Pima Indians Diabetes"
MISSING_RATE = 0.15
RANDOM_STATE = 42

df = pd.read_csv("data/pima-indians-diabetes/pima_diabetes.csv")
X = df.select_dtypes(include="number").drop(
    columns=["Outcome"], errors="ignore"
).astype(float)

X_train, X_test = train_test_split(X, test_size=0.1, random_state=RANDOM_STATE)

# Inject MCAR missing values
generator = mMCAR(
    X=X_test,
    y=y_test,
    missing_rate=int(MISSING_RATE * 100),
    seed=RANDOM_STATE,
)

X_test_missing = generator.random()

# Fit → impute → explain
imputer = RAGImputer(
    n_neighbors=5,
    feature_weighting="correlation",
    llm_model_name="gemini-2.0-flash",
    llm_api="gemini",
    dataset_name=DATASET_NAME,
    llm_batch_size=1,
)
imputer.fit(X_train)
X_imputed = imputer.transform(X_test_missing)
X_imputed_df = pd.DataFrame(X_imputed, columns=X_test.columns, index=X_test.index)

explanations = imputer.explain(X_test_missing, X_imputed_df)

# Pretty-print results
for idx, explanation in zip(
    X_test_missing.index[X_test_missing.isna().any(axis=1)],
    explanations,
):
    missing_cols = X_test_missing.columns[X_test_missing.loc[idx].isna()].tolist()
    imputed_vals = {col: round(X_imputed_df.loc[idx, col], 4) for col in missing_cols}
    print(f"\n[Row {idx}]")
    print(f"  Missing  : {missing_cols}")
    print(f"  Imputed  : {imputed_vals}")
    print(f"  Reasoning: {explanation.strip()}")
    print("-" * 70)

Sample output

[Row 42]
  Missing  : ['Glucose', 'BMI']
  Imputed  : {'Glucose': 0.5312, 'BMI': 0.4827}
  Reasoning: The retrieved neighbors show a consistent pattern of moderate
  glucose levels (0.45–0.60) for patients in this age and blood-pressure
  range. The imputed Glucose value of 0.53 reflects the central tendency
  of the three closest neighbors, all of whom share similar Insulin and
  SkinThickness profiles. For BMI, the retrieved records cluster tightly
  around 0.47–0.52, and the absence of extreme Insulin values further
  supports a near-average BMI estimate of 0.48.
------------------------------------------------------------------------