Spaces:
Sleeping
Sleeping
| from __future__ import annotations | |
| import argparse | |
| from pathlib import Path | |
| import sys | |
| import numpy as np | |
| import pandas as pd | |
| ROOT_DIR = Path(__file__).resolve().parents[1] | |
| if str(ROOT_DIR) not in sys.path: | |
| sys.path.insert(0, str(ROOT_DIR)) | |
| from app.config import get_settings | |
| def generate_dataset(rows: int, seed: int = 42) -> pd.DataFrame: | |
| rng = np.random.default_rng(seed) | |
| categories = np.array(["electronics", "fashion", "home", "beauty", "grocery"]) | |
| brands = np.array(["brand_a", "brand_b", "brand_c", "brand_d"]) | |
| segments = np.array(["budget", "standard", "premium", "loyal"]) | |
| category = rng.choice(categories, size=rows, p=[0.24, 0.22, 0.18, 0.16, 0.20]) | |
| brand = rng.choice(brands, size=rows) | |
| customer_segment = rng.choice(segments, size=rows, p=[0.25, 0.40, 0.20, 0.15]) | |
| hour_of_day = rng.integers(0, 24, size=rows) | |
| day_of_week = rng.integers(0, 7, size=rows) | |
| is_weekend = (day_of_week >= 5).astype(int) | |
| is_festival = rng.binomial(1, 0.12, size=rows) | |
| inventory_level = rng.integers(5, 180, size=rows) | |
| inventory_days_cover = np.round(rng.uniform(1.0, 28.0, size=rows), 2) | |
| base_cost = np.round(rng.uniform(150.0, 2200.0, size=rows), 2) | |
| category_factor = { | |
| "electronics": 1.55, | |
| "fashion": 1.35, | |
| "home": 1.25, | |
| "beauty": 1.48, | |
| "grocery": 1.18, | |
| } | |
| segment_factor = { | |
| "budget": 0.95, | |
| "standard": 1.0, | |
| "premium": 1.16, | |
| "loyal": 1.08, | |
| } | |
| base_markup = np.array([category_factor[item] for item in category]) * np.array( | |
| [segment_factor[item] for item in customer_segment] | |
| ) | |
| competitor_price = np.round(base_cost * base_markup * rng.uniform(0.92, 1.08, size=rows), 2) | |
| current_price = np.round(competitor_price * rng.uniform(0.96, 1.08, size=rows), 2) | |
| click_through_rate = np.round(rng.uniform(0.01, 0.15, size=rows), 4) | |
| conversion_rate = np.round(rng.uniform(0.008, 0.08, size=rows), 4) | |
| units_sold_last_5m = rng.poisson(4 + is_festival * 2 + is_weekend, size=rows) | |
| units_sold_last_1h = rng.poisson(18 + is_festival * 10 + is_weekend * 4, size=rows) | |
| demand_multiplier = ( | |
| 1 | |
| + is_festival * 0.10 | |
| + is_weekend * 0.04 | |
| + (hour_of_day >= 18).astype(int) * 0.05 | |
| + (conversion_rate * 2.5) | |
| + (units_sold_last_1h / 300) | |
| ) | |
| inventory_multiplier = np.where( | |
| inventory_level < 20, | |
| 1.11, | |
| np.where(inventory_level > 120, 0.93, 1.0), | |
| ) | |
| optimal_price = ( | |
| base_cost | |
| * base_markup | |
| * demand_multiplier | |
| * inventory_multiplier | |
| * rng.uniform(0.97, 1.03, size=rows) | |
| ) | |
| optimal_price = np.minimum(optimal_price, current_price * 1.30) | |
| optimal_price = np.maximum(optimal_price, base_cost * 1.08) | |
| frame = pd.DataFrame( | |
| { | |
| "sku_id": [f"SKU-{1000 + idx}" for idx in range(rows)], | |
| "category": category, | |
| "brand": brand, | |
| "customer_segment": customer_segment, | |
| "hour_of_day": hour_of_day, | |
| "day_of_week": day_of_week, | |
| "is_weekend": is_weekend, | |
| "is_festival": is_festival, | |
| "inventory_level": inventory_level, | |
| "inventory_days_cover": inventory_days_cover, | |
| "competitor_price": competitor_price, | |
| "click_through_rate": click_through_rate, | |
| "conversion_rate": conversion_rate, | |
| "units_sold_last_5m": units_sold_last_5m, | |
| "units_sold_last_1h": units_sold_last_1h, | |
| "base_cost": base_cost, | |
| "current_price": current_price, | |
| "optimal_price": np.round(optimal_price, 2), | |
| } | |
| ) | |
| return frame | |
| def main() -> None: | |
| parser = argparse.ArgumentParser(description="Generate synthetic pricing events data.") | |
| parser.add_argument("--rows", type=int, default=25000, help="Number of rows to generate") | |
| parser.add_argument("--seed", type=int, default=42, help="Random seed") | |
| args = parser.parse_args() | |
| settings = get_settings() | |
| frame = generate_dataset(rows=args.rows, seed=args.seed) | |
| settings.raw_data_path.parent.mkdir(parents=True, exist_ok=True) | |
| frame.to_csv(settings.raw_data_path, index=False) | |
| print(f"Saved {len(frame)} rows to {settings.raw_data_path}") | |
| if __name__ == "__main__": | |
| main() | |