SPB Git

spb/wp26_uqo

Public
2.5 KB · 58 lines python
1#!/usr/bin/env python32# Author: Simon-Pierre Boucher — simon-pierre.boucher@uqo.ca3"""Baseline feature matrix with as-of comparable summaries.45    python3 scripts/03_features.py [--synthetic] [--no-geo]6→ data/{processed|synthetic}/feature_matrix.parquet (+ results/data/feature_matrix_summary*.json).7Geo features are joined when data/<base>/geo_features.parquet exists (run scripts/04_geo.py first).8"""9from __future__ import annotations1011import argparse12import json13import time1415import polars as pl1617from agentic_valuation.config import PROCESSED, RESULTS, SYNTHETIC18from agentic_valuation.features.matrix import build_feature_matrix, feature_columns192021def main() -> None:22    ap = argparse.ArgumentParser(description=__doc__)23    ap.add_argument("--synthetic", action="store_true")24    ap.add_argument("--no-geo", action="store_true", help="ignore geo_features.parquet even if present")25    args = ap.parse_args()26    base = SYNTHETIC if args.synthetic else PROCESSED27    t0 = time.perf_counter()28    analytic = pl.read_parquet(base / "analytic.parquet")29    splits = pl.read_parquet(base / "splits.parquet")30    geo = None31    geo_path = base / "geo_features.parquet"32    if geo_path.exists() and not args.no_geo:33        geo = pl.read_parquet(geo_path)34    fm = build_feature_matrix(analytic, splits, geo=geo, comps_summary=True)35    fm.write_parquet(base / "feature_matrix.parquet", compression="zstd")36    num, cat = feature_columns(fm)37    summary = {38        "synthetic": args.synthetic,39        "rows": fm.height,40        "by_split": {k: int(v) for k, v in fm.group_by("split").len().iter_rows()},41        "numeric_features": num,42        "categorical_features": cat,43        "geo_joined": geo is not None,44        "geo_rows": None if geo is None else geo.height,45        "missingness_pct": {c: round(100.0 * fm[c].null_count() / fm.height, 3) for c in num + cat},46        "nb_n_12m_quantiles": {q: float(fm["nb_n_12m"].quantile(q)) for q in (0.05, 0.25, 0.5, 0.75, 0.95)},47        "nb_mean_dist_km_median": float(fm["nb_mean_dist_km"].median()),48        "seconds": round(time.perf_counter() - t0, 2),49    }50    out = RESULTS / "data" / ("feature_matrix_summary_synthetic.json" if args.synthetic else "feature_matrix_summary.json")51    out.parent.mkdir(parents=True, exist_ok=True)52    out.write_text(json.dumps(summary, indent=1, ensure_ascii=False))53    print(json.dumps({k: summary[k] for k in ("rows", "by_split", "geo_joined", "nb_n_12m_quantiles", "nb_mean_dist_km_median", "seconds")}, ensure_ascii=False, indent=1))545556if __name__ == "__main__":57    main()58
Files · main
Menu

Theme