SPB Git

spb/wp38_uqo

Public
3.6 KB · 64 lines python
1"""Phase 4 features — region × category count matrices under the three weighting schemes and the sample variants.23Outputs data/processed/rc_counts.parquet (long format): sample ∈ {S_R, S_R0, S_A}, scheme ∈ {L, M, T}, region, category, n4plus store-level table data/processed/store_panel.parquet used by every model (one row per store in S_A with region, weights, size).5"""6from __future__ import annotations7import json8import numpy as np, pandas as pd9from src.common import ROOT, P, REGIONS, get_logger, ledger, register_output, write_json, PROC_DIR, EXP_DIR, LABEL, BASE_PROC, BASE_EXP1011log = get_logger("features.rc")12PROC = PROC_DIR131415def store_category_table():16    li = pd.read_parquet(P["interim"] / "listings_clean.parquet")17    sm = pd.read_parquet(P["interim"] / "stores_master.parquet")18    a = li[li.f_analysis_assort]19    if LABEL == "model":20        cm = pd.read_parquet(BASE_PROC / "category_model.parquet").set_index("uid").category_model21        a = a.assign(category=a.uid.map(cm).fillna(a.category))22    sc = a.groupby(["store_id", "category"]).size().rename("n").reset_index()23    sc = sc.merge(sm[["id", "region_final", "region_source", "n_listings", "platform", "store_kind", "certified", "first_source", "origin_class"]], left_on="store_id", right_on="id").drop(columns="id")24    sc = sc.merge(sm[["id", "region_dbfirst", "region_db"]], left_on="store_id", right_on="id").drop(columns="id")25    return sc, sm262728def build(sc: pd.DataFrame) -> pd.DataFrame:29    rows = []30    sizes = sc.groupby("store_id").n.sum()31    cut = sizes.quantile(0.99)32    for sample, mask in (("S_R", sc.region_final != "Inconnue"), ("S_R0", sc.region_db.notna()), ("S_A", pd.Series(True, index=sc.index))):33        d = sc[mask].copy()34        if sample == "S_R0": d["region_final"] = d.region_dbfirst35        d["w_L"] = d.n.astype(float)36        d["w_M"] = d.n / d.store_id.map(sizes)37        d["w_T"] = np.where(d.store_id.map(sizes) > cut, 0.0, d.n.astype(float))38        for scheme in ("L", "M", "T"):39            g = d.groupby(["region_final", "category"])[f"w_{scheme}"].sum().reset_index()40            g.columns = ["region", "category", "n"]; g["sample"] = sample; g["scheme"] = scheme41            rows.append(g)42    out = pd.concat(rows, ignore_index=True)43    return out444546def main():47    sc, sm = store_category_table()48    rc = build(sc)49    rc.to_parquet(PROC / "rc_counts.parquet", index=False); register_output(PROC / "rc_counts.parquet", "features.rc")50    sc.to_parquet(PROC / "store_category.parquet", index=False); register_output(PROC / "store_category.parquet", "features.rc")51    sp = sm[["id", "region_final", "region_source", "region_conflict", "n_listings", "n_categories", "platform", "store_kind", "certified", "cert_adq", "cert_lpq",52             "first_source", "origin_class", "median_price", "main_category", "lat", "lng"]].copy()53    sp = sp[sp.n_listings > 0]54    sp.to_parquet(PROC / "store_panel.parquet", index=False); register_output(PROC / "store_panel.parquet", "features.rc")55    summ = {"stores_S_A": int(sp.shape[0]), "stores_S_R": int((sp.region_final != "Inconnue").sum()), "stores_S_R0": int(sm.region_db.notna().sum()),56            "listings_S_R": int(rc.query("sample=='S_R' and scheme=='L'").n.sum()), "listings_S_A": int(rc.query("sample=='S_A' and scheme=='L'").n.sum()),57            "top1pct_cut": float(sc.groupby('store_id').n.sum().quantile(0.99)),58            "stores_by_region_S_R": sp[sp.region_final != "Inconnue"].region_final.value_counts().to_dict()}59    write_json(summ, EXP_DIR / "features_rc.json", "features.rc"); ledger("features.region_category", **summ); log.info(json.dumps(summ, ensure_ascii=False))606162if __name__ == "__main__":63    main()64
Files · 868e380d70bce866dfb2e5b5ff56d54a8909d47d
Menu

Theme