| """Orchestrates synthetic data generation and persists CSVs to data/.""" |
|
|
| from src.config import DATA_DIR, END_DATE, N_CUSTOMERS, N_PRODUCTS, SEED, START_DATE |
| from src.data_generation.generate_customers import generate_customers |
| from src.data_generation.generate_orders import generate_orders |
| from src.data_generation.generate_products import generate_products |
| from src.utils.logger import get_logger |
|
|
| logger = get_logger(__name__) |
|
|
|
|
| def generate_all( |
| n_customers: int = N_CUSTOMERS, |
| n_products: int = N_PRODUCTS, |
| seed: int = SEED, |
| start_date: str = START_DATE, |
| end_date: str = END_DATE, |
| ) -> tuple: |
| """Run the full synthetic data generation pipeline. |
| |
| Returns: |
| Tuple of (customers, products, orders) DataFrames. |
| """ |
| DATA_DIR.mkdir(parents=True, exist_ok=True) |
|
|
| logger.info(f"Generating {n_customers:,} customers …") |
| customers = generate_customers( |
| n=n_customers, seed=seed, start_date=start_date, end_date=end_date |
| ) |
|
|
| logger.info(f"Generating {n_products:,} products …") |
| products = generate_products(n=n_products, seed=seed) |
|
|
| logger.info("Generating orders (this may take a moment) …") |
| orders = generate_orders( |
| customers=customers, |
| products=products, |
| seed=seed, |
| start_date=start_date, |
| end_date=end_date, |
| ) |
|
|
| |
| customers_out = customers.drop(columns=["lifecycle_type"]) |
|
|
| customers_out.to_csv(DATA_DIR / "customers.csv", index=False) |
| products.to_csv(DATA_DIR / "products.csv", index=False) |
| orders.to_csv(DATA_DIR / "orders.csv", index=False) |
|
|
| logger.info( |
| f"Data saved to {DATA_DIR}: " |
| f"{len(customers_out):,} customers, " |
| f"{len(products):,} products, " |
| f"{len(orders):,} orders" |
| ) |
|
|
| _log_summary(customers, orders) |
| return customers, products, orders |
|
|
|
|
| def _log_summary(customers: "pd.DataFrame", orders: "pd.DataFrame") -> None: |
| """Log descriptive statistics useful for churn-period calibration.""" |
| import numpy as np |
|
|
| hist = orders.sort_values(["customer_id", "order_date"]) |
| hist["prev"] = hist.groupby("customer_id")["order_date"].shift(1) |
| hist["inter_days"] = (hist["order_date"] - hist["prev"]).dt.days |
| inter = hist["inter_days"].dropna() |
|
|
| logger.info( |
| f"Inter-order time median={np.median(inter):.0f}d " |
| f"P75={np.percentile(inter, 75):.0f}d " |
| f"P80={np.percentile(inter, 80):.0f}d " |
| f"P90={np.percentile(inter, 90):.0f}d" |
| ) |
| lc = customers.groupby("lifecycle_type").size().to_dict() |
| logger.info(f"Lifecycle mix: {lc}") |
|
|
|
|
| if __name__ == "__main__": |
| generate_all() |
|
|