Spaces:
Runtime error
Runtime error
Download src/ccdp/identification/reference_table.py from theDocWho/car-crash-fix-amount-predictor: direct link, hf CLI and curl.
- Browser
- Download file 6.66 kB
-
https://huggingface.co/spaces/theDocWho/car-crash-fix-amount-predictor/resolve/main/src/ccdp/identification/reference_table.py
- Command line
-
hf download hf://spaces/theDocWho/car-crash-fix-amount-predictor/src/ccdp/identification/reference_table.py
-
curl -L -o reference_table.py https://huggingface.co/spaces/theDocWho/car-crash-fix-amount-predictor/resolve/main/src/ccdp/identification/reference_table.py
6.66 kB
| """Canonical reference table: (make, model, year) -> body_type, segment, avg cost. | |
| Built from the cost-bearing datasets (iaai + ganeshsura) during Phase 1 EDA. | |
| Persisted as Parquet (with CSV mirror for inspection) at: | |
| data/processed/reference_table.parquet | |
| data/processed/reference_table.csv | |
| The table supports a graceful-degradation `nearest()` lookup used by the | |
| fallback estimator and the Tier-2 cost path. | |
| """ | |
| from __future__ import annotations | |
| import json | |
| from dataclasses import dataclass | |
| from pathlib import Path | |
| from typing import Iterable, Optional | |
| DEFAULT_PATH = Path("data/processed/reference_table.parquet") | |
| class ReferenceRow: | |
| make: Optional[str] | |
| model: Optional[str] | |
| year: Optional[int] | |
| body_type: str | |
| segment: str | |
| avg_cost_usd: float | |
| n_samples: int | |
| datasets: str # comma-joined list of source dataset names | |
| def to_dict(self) -> dict: | |
| return self.__dict__.copy() | |
| # --- build -------------------------------------------------------------- | |
| def build( | |
| rows: Iterable[dict], | |
| out_path: Path = DEFAULT_PATH, | |
| ) -> Path: | |
| """Build reference table from per-record dicts. | |
| `rows` must contain (at minimum) `make`, `model`, `year`, `body_type`, | |
| `segment`, `cost_usd`, `dataset`. Missing fields are normalized to None. | |
| """ | |
| import pandas as pd # local import — pandas is in [ml] extras | |
| df = pd.DataFrame(list(rows)) | |
| if df.empty: | |
| out_path.parent.mkdir(parents=True, exist_ok=True) | |
| empty = pd.DataFrame( | |
| columns=["make", "model", "year", "body_type", "segment", | |
| "avg_cost_usd", "n_samples", "datasets"] | |
| ) | |
| empty.to_parquet(out_path, index=False) | |
| empty.to_csv(out_path.with_suffix(".csv"), index=False) | |
| return out_path | |
| for col in ("make", "model", "body_type", "segment"): | |
| if col in df: | |
| df[col] = df[col].fillna("unknown").astype(str).str.lower() | |
| else: | |
| df[col] = "unknown" | |
| if "year" not in df: | |
| df["year"] = None | |
| grouped = ( | |
| df.groupby(["make", "model", "year", "body_type", "segment"], dropna=False) | |
| .agg( | |
| avg_cost_usd=("cost_usd", "mean"), | |
| n_samples=("cost_usd", "size"), | |
| datasets=("dataset", lambda s: ",".join(sorted(set(map(str, s))))), | |
| ) | |
| .reset_index() | |
| ) | |
| grouped = grouped.sort_values(["make", "model", "year"]).reset_index(drop=True) | |
| out_path.parent.mkdir(parents=True, exist_ok=True) | |
| grouped.to_parquet(out_path, index=False) | |
| grouped.to_csv(out_path.with_suffix(".csv"), index=False) | |
| return out_path | |
| def load(path: Path | None = None): | |
| import pandas as pd | |
| if path is None: | |
| path = DEFAULT_PATH | |
| if not path.exists(): | |
| raise FileNotFoundError( | |
| f"Reference table not built yet at {path}. Run Phase 1 EDA notebook " | |
| f"or `ccdp data build-reference-table`." | |
| ) | |
| return pd.read_parquet(path) | |
| # --- lookup ------------------------------------------------------------- | |
| def nearest( | |
| make: Optional[str] = None, | |
| model: Optional[str] = None, | |
| year: Optional[int] = None, | |
| body_type: Optional[str] = None, | |
| segment: Optional[str] = None, | |
| path: Path | None = None, | |
| ) -> Optional[dict]: | |
| """Graceful-degradation lookup. Returns the matched aggregate row + 'how'. | |
| Chain: | |
| 1. exact (make, model, year) | |
| 2. (make, model) any year — most recent first | |
| 3. (segment, body_type) | |
| 4. (body_type,) only | |
| 5. (segment,) only | |
| """ | |
| df = load(path) | |
| if df.empty: | |
| return None | |
| def _result(sub, how: str) -> Optional[dict]: | |
| if sub.empty: | |
| return None | |
| # weighted average by sample count | |
| if "n_samples" in sub and sub["n_samples"].sum() > 0: | |
| cost = (sub["avg_cost_usd"] * sub["n_samples"]).sum() / sub["n_samples"].sum() | |
| else: | |
| cost = sub["avg_cost_usd"].mean() | |
| return { | |
| "match_how": how, | |
| "n_samples": int(sub["n_samples"].sum()) if "n_samples" in sub else len(sub), | |
| "avg_cost_usd": float(cost), | |
| "body_type": _mode(sub.get("body_type")), | |
| "segment": _mode(sub.get("segment")), | |
| "example_model": _example_model(sub), | |
| } | |
| if make and model and year is not None: | |
| sub = df[(df["make"] == make.lower()) & (df["model"].astype(str).str.startswith(model.lower())) & (df["year"] == year)] | |
| r = _result(sub, "exact") | |
| if r: | |
| return r | |
| if make and model: | |
| sub = df[(df["make"] == make.lower()) & (df["model"].astype(str).str.startswith(model.lower()))] | |
| r = _result(sub, "make_model_any_year") | |
| if r: | |
| return r | |
| if segment and body_type: | |
| sub = df[(df["segment"] == segment.lower()) & (df["body_type"] == body_type.lower())] | |
| r = _result(sub, "segment_body_type") | |
| if r: | |
| return r | |
| if body_type: | |
| sub = df[df["body_type"] == body_type.lower()] | |
| r = _result(sub, "body_type") | |
| if r: | |
| return r | |
| if segment: | |
| sub = df[df["segment"] == segment.lower()] | |
| r = _result(sub, "segment") | |
| if r: | |
| return r | |
| return None | |
| def _mode(series) -> str: | |
| if series is None or len(series) == 0: | |
| return "unknown" | |
| m = series.mode() | |
| return str(m.iloc[0]) if not m.empty else "unknown" | |
| def _example_model(sub) -> str: | |
| if sub.empty: | |
| return "unknown" | |
| top = sub.sort_values("n_samples", ascending=False).iloc[0] | |
| parts = [str(top.get("make", "")), str(top.get("model", ""))] | |
| return " ".join(p for p in parts if p and p != "unknown").strip() or "unknown" | |
| # --- coverage report ---------------------------------------------------- | |
| def coverage_report(path: Path | None = None) -> dict: | |
| """Quick health summary for the report generator.""" | |
| df = load(path) | |
| if df.empty: | |
| return {"rows": 0} | |
| return { | |
| "rows": len(df), | |
| "unique_makes": int(df["make"].nunique()), | |
| "unique_models": int(df["model"].nunique()), | |
| "year_range": [int(df["year"].dropna().min()) if df["year"].notna().any() else None, | |
| int(df["year"].dropna().max()) if df["year"].notna().any() else None], | |
| "body_type_counts": json.loads(df["body_type"].value_counts().to_json()), | |
| "segment_counts": json.loads(df["segment"].value_counts().to_json()), | |
| "total_samples": int(df["n_samples"].sum()), | |
| "median_avg_cost_usd": float(df["avg_cost_usd"].median()), | |
| } | |