Warrior_EA/research/wyckoff_judge_eval.py

18 lines
1.6 KiB
Python

import os, numpy as np, pandas as pd
d = os.path.join(os.path.dirname(__file__), "wyckoff_gold", "judge")
K = pd.read_csv(os.path.join(d, "_key.csv"), dtype={"id": str}); C = pd.read_csv(os.path.join(d, "calls.csv"), dtype={"id": str})
A = K.merge(C, on="id"); assert len(A) == 180
A["r"] = np.where(A.call == "L", A.rL, np.where(A.call == "S", A.rS, np.nan))
t = lambda x: x.mean() / (x.std(ddof=1) / np.sqrt(len(x))) if len(x) > 2 else float("nan")
print("calls", A.call.value_counts().to_dict(), "| by kind", A.groupby("kind").call.value_counts().unstack().fillna(0).astype(int).to_dict("index"))
for name, m in [("ALL called", A.call != "N"), ("L", A.call == "L"), ("S", A.call == "S"), ("conf2", A.conf == 2),
("called on trig", (A.call != "N") & (A.kind == "trig")), ("called on ctl", (A.call != "N") & (A.kind == "ctl"))]:
x = A.r[m].dropna(); print(f"{name:16s} n={len(x):3d} meanR={x.mean():+.3f} t={t(x):+.2f} win%={(x>0).mean()*100:.0f}")
print("pool same-direction mean (all 180): L", round(A.rL.mean(), 3), " S", round(A.rS.mean(), 3))
# matched: same direction on the NOT-called charts
for s, col in (("L", "rL"), ("S", "rS")):
a = A[A.call == s][col]; b = A[A.call != s][col]
print(f"{s}: called {a.mean():+.3f} (n={len(a)}) vs rest {b.mean():+.3f} (n={len(b)}) diff {a.mean()-b.mean():+.3f}")
# rule trigger direction on same sample for comparison
A["rule"] = np.where((A.kind == "trig") & ((A.spring == 1) | (A.sos == 1)), "L", np.where((A.kind == "trig") & ((A.utad == 1) | (A.sow == 1)), "S", "N"))
print("agree with rule:", pd.crosstab(A.call, A.rule).to_dict())