Spaces:
Running
Running
File size: 4,145 Bytes
57b5041 3a77c6f 57b5041 606cfa3 57b5041 3a77c6f 57b5041 3a77c6f 57b5041 3a77c6f 57b5041 3a77c6f 57b5041 3a77c6f 57b5041 3a77c6f 57b5041 3a77c6f | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 | """
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),
})
|