from __future__ import annotations import math from pathlib import Path import pandas as pd ROOT = Path(__file__).resolve().parent OUT_DIR = ROOT / "paper_tables" def _to_int_series(s: pd.Series) -> pd.Series: return s.map(lambda x: int(round(float(x))) if pd.notna(x) else x) def _to_float_series(s: pd.Series, ndigits: int) -> pd.Series: return s.map(lambda x: round(float(x), ndigits) if pd.notna(x) else x) def _format_table1_metrics_summary(df: pd.DataFrame) -> pd.DataFrame: out = df.copy() out["E1_total_service"] = _to_int_series(out["E1_total_service"]) out["E2_quality_weighted"] = _to_int_series(out["E2_quality_weighted"]) out["F1_gini"] = _to_float_series(out["F1_gini"], 4) out["F2_min_satisfaction"] = _to_float_series(out["F2_min_satisfaction"], 2) out["F3_cv_satisfaction"] = _to_float_series(out["F3_cv_satisfaction"], 4) out["E1_total_service_pct"] = _to_float_series(out["E1_total_service_pct"], 2) out["E2_quality_weighted_pct"] = _to_float_series(out["E2_quality_weighted_pct"], 2) return out def _format_table2_corrected_sites(df: pd.DataFrame) -> pd.DataFrame: out = df.copy() out["site_id"] = _to_int_series(out["site_id"]) out["mu"] = _to_float_series(out["mu"], 1) out["sigma"] = _to_float_series(out["sigma"], 1) out["p_trunc"] = _to_float_series(out["p_trunc"], 3) out["mu_tilde"] = _to_float_series(out["mu_tilde"], 1) out["mu_delta"] = _to_float_series(out["mu_delta"], 1) out["mu_delta_pct"] = _to_float_series(out["mu_delta_pct"], 1) return out def _format_table3_backtest_summary(df: pd.DataFrame) -> pd.DataFrame: out = df.copy() out["value"] = out["value"].map(lambda x: round(float(x), 6) if pd.notna(x) else x) out["p_value"] = out["p_value"].map(lambda x: round(float(x), 6) if pd.notna(x) else x) return out def _format_appendix_site_details(df: pd.DataFrame) -> pd.DataFrame: out = df.copy() out["site_id"] = _to_int_series(out["site_id"]) out["mu"] = _to_float_series(out["mu"], 1) out["mu_tilde"] = _to_float_series(out["mu_tilde"], 1) out["k"] = _to_int_series(out["k"]) out["annual_service"] = _to_int_series(out["annual_service"]) out["r"] = _to_float_series(out["r"], 4) out["quality_factor"] = _to_float_series(out["quality_factor"], 4) out["service_quality_weighted"] = _to_int_series(out["service_quality_weighted"]) return out def export_tables() -> list[Path]: OUT_DIR.mkdir(parents=True, exist_ok=True) written: list[Path] = [] # Table 1: overall performance comparison metrics_xlsx = ROOT / "04_metrics.xlsx" metrics = pd.read_excel(metrics_xlsx, sheet_name="metrics_summary") metrics_paper = _format_table1_metrics_summary(metrics) p1 = OUT_DIR / "table1_metrics_summary.csv" metrics_paper.to_csv(p1, index=False, encoding="utf-8-sig") written.append(p1) # Table 2: truncation correction (corrected sites) backtest_xlsx = ROOT / "07_backtest.xlsx" corrected = pd.read_excel(backtest_xlsx, sheet_name="corrected_sites") corrected = corrected.copy() corrected["mu_delta"] = corrected["mu_tilde"] - corrected["mu"] corrected["mu_delta_pct"] = corrected["mu_delta"] / corrected["mu"] * 100 corrected_paper = _format_table2_corrected_sites(corrected) p2 = OUT_DIR / "table2_corrected_sites.csv" corrected_paper.to_csv(p2, index=False, encoding="utf-8-sig") written.append(p2) # Table 3: backtest & fit statistics summary = pd.read_excel(backtest_xlsx, sheet_name="summary_metrics") summary_paper = _format_table3_backtest_summary(summary) p3 = OUT_DIR / "table3_backtest_summary.csv" summary_paper.to_csv(p3, index=False, encoding="utf-8-sig") written.append(p3) # Table 4: constraint validation results validate_xlsx = ROOT / "06_validate.xlsx" validation = pd.read_excel(validate_xlsx, sheet_name="validation_results") p4 = OUT_DIR / "table4_validation_results.csv" validation.to_csv(p4, index=False, encoding="utf-8-sig") written.append(p4) # Appendix: per-site allocation details (optional for paper appendix) site_details = pd.read_excel(metrics_xlsx, sheet_name="site_details") site_details_paper = _format_appendix_site_details(site_details) p5 = OUT_DIR / "appendix_site_details.csv" site_details_paper.to_csv(p5, index=False, encoding="utf-8-sig") written.append(p5) return written def main() -> None: written = export_tables() rel = [p.relative_to(ROOT) for p in written] print("Wrote:") for p in rel: print(f" - {p}") if __name__ == "__main__": main()