drift-detection / src /sample_data.py
Yogesh18018's picture
Upload folder using huggingface_hub
3a77c6f verified
Raw History Blame Contribute Delete
4.15 kB
"""
Sample Data Generator
=====================
Produces synthetic reference and drifted datasets for demonstration.
Features
--------
- age : Customer age
- income : Annual income ($)
- score : Internal credit / risk score
- balance : Account balance ($)
- transactions : Monthly transaction count
"""
import numpy as np
import pandas as pd
# Drift shift configuration
_DRIFT_SHIFTS: dict[str, dict] = {
"low": {
"age": {"mean_shift": 2, "std_scale": 1.05},
"income": {"mean_shift": 3000, "std_scale": 1.05},
"score": {"mean_shift": 5, "std_scale": 1.08},
"balance": {"mean_shift": 500, "std_scale": 1.05},
"transactions": {"mean_shift": 2, "std_scale": 1.05},
},
"medium": {
"age": {"mean_shift": 8, "std_scale": 1.20},
"income": {"mean_shift": 12000, "std_scale": 1.25},
"score": {"mean_shift": 20, "std_scale": 1.30},
"balance": {"mean_shift": 3000, "std_scale": 1.25},
"transactions": {"mean_shift": 8, "std_scale": 1.20},
},
"high": {
"age": {"mean_shift": 18, "std_scale": 1.50},
"income": {"mean_shift": 30000, "std_scale": 1.60},
"score": {"mean_shift": 45, "std_scale": 1.55},
"balance": {"mean_shift": 8000, "std_scale": 1.60},
"transactions": {"mean_shift": 18, "std_scale": 1.50},
},
}
def generate_reference_data(n: int = 2000, seed: int = 42) -> pd.DataFrame:
"""
Generate a clean baseline (reference) dataset.
Parameters
----------
n : Number of rows.
seed : Random seed for reproducibility.
Returns
-------
pd.DataFrame with columns [age, income, score, balance, transactions].
"""
rng = np.random.default_rng(seed)
return pd.DataFrame({
"age": rng.normal(loc=35, scale=10, size=n).clip(18, 80).round(0),
"income": rng.normal(loc=55000, scale=15000, size=n).clip(15000).round(2),
"score": rng.normal(loc=650, scale=80, size=n).clip(300, 850).round(0),
"balance": rng.normal(loc=12000, scale=5000, size=n).clip(0).round(2),
"transactions": rng.poisson(lam=20, size=n).clip(0),
})
def generate_drifted_data(
n: int = 2000,
drift_level: str = "medium",
seed: int = 123,
) -> pd.DataFrame:
"""
Generate a dataset whose distributions have shifted from the reference.
Parameters
----------
n : Number of rows.
drift_level : One of ``"low"``, ``"medium"``, ``"high"``.
seed : Random seed.
Returns
-------
pd.DataFrame with the same columns as reference, but shifted.
"""
if drift_level not in _DRIFT_SHIFTS:
raise ValueError(f"drift_level must be one of {list(_DRIFT_SHIFTS)}")
shifts = _DRIFT_SHIFTS[drift_level]
rng = np.random.default_rng(seed)
age_shift = shifts["age"]
income_shift = shifts["income"]
score_shift = shifts["score"]
balance_shift = shifts["balance"]
txn_shift = shifts["transactions"]
return pd.DataFrame({
"age": rng.normal(
loc=35 + age_shift["mean_shift"],
scale=10 * age_shift["std_scale"],
size=n,
).clip(18, 80).round(0),
"income": rng.normal(
loc=55000 + income_shift["mean_shift"],
scale=15000 * income_shift["std_scale"],
size=n,
).clip(15000).round(2),
"score": rng.normal(
loc=650 + score_shift["mean_shift"],
scale=80 * score_shift["std_scale"],
size=n,
).clip(300, 850).round(0),
"balance": rng.normal(
loc=12000 + balance_shift["mean_shift"],
scale=5000 * balance_shift["std_scale"],
size=n,
).clip(0).round(2),
"transactions": rng.poisson(
lam=20 + txn_shift["mean_shift"],
size=n,
).clip(0),
})