expresso_graph
This commit is contained in:
+44
-27
@@ -1,6 +1,7 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
import sys
|
import sys
|
||||||
import subprocess
|
import subprocess
|
||||||
|
import os
|
||||||
|
|
||||||
# === AUTO INSTALL ===
|
# === AUTO INSTALL ===
|
||||||
def ensure(pkg):
|
def ensure(pkg):
|
||||||
@@ -17,29 +18,32 @@ import matplotlib.pyplot as plt
|
|||||||
|
|
||||||
# === ARGS ===
|
# === ARGS ===
|
||||||
if len(sys.argv) < 2:
|
if len(sys.argv) < 2:
|
||||||
print("Usage: python graph.py data.csv")
|
print("Usage: python graph.py data.csv [output_dir]")
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
FILE = sys.argv[1]
|
FILE = sys.argv[1]
|
||||||
|
OUTDIR = sys.argv[2] if len(sys.argv) > 2 else "graphs"
|
||||||
|
|
||||||
|
os.makedirs(OUTDIR, exist_ok=True)
|
||||||
|
|
||||||
# === LOAD ===
|
# === LOAD ===
|
||||||
df = pd.read_csv(FILE)
|
df = pd.read_csv(FILE)
|
||||||
|
|
||||||
if "datetime" not in df.columns:
|
required_cols = ["datetime", "profit", "buy_in"]
|
||||||
print("Missing datetime column")
|
for col in required_cols:
|
||||||
sys.exit(1)
|
|
||||||
|
|
||||||
df["datetime"] = pd.to_datetime(df["datetime"])
|
|
||||||
df = df.sort_values("datetime")
|
|
||||||
|
|
||||||
# === CHECK REQUIRED COLS ===
|
|
||||||
required = ["profit", "buy_in", "category"]
|
|
||||||
for col in required:
|
|
||||||
if col not in df.columns:
|
if col not in df.columns:
|
||||||
print(f"Missing column: {col}")
|
print(f"Missing column: {col}")
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
# === 1. CUMULATIVE PROFIT ===
|
df["datetime"] = pd.to_datetime(df["datetime"], errors="coerce")
|
||||||
|
df = df.dropna(subset=["datetime"])
|
||||||
|
df = df.sort_values("datetime")
|
||||||
|
|
||||||
|
# === CLEAN NUMERIC ===
|
||||||
|
df["profit"] = pd.to_numeric(df["profit"], errors="coerce").fillna(0)
|
||||||
|
df["buy_in"] = pd.to_numeric(df["buy_in"], errors="coerce").fillna(0)
|
||||||
|
|
||||||
|
# === CUMULATIVE PROFIT ===
|
||||||
df["cum_profit"] = df["profit"].cumsum()
|
df["cum_profit"] = df["profit"].cumsum()
|
||||||
|
|
||||||
plt.figure()
|
plt.figure()
|
||||||
@@ -49,28 +53,38 @@ plt.xlabel("Time")
|
|||||||
plt.ylabel("€")
|
plt.ylabel("€")
|
||||||
plt.xticks(rotation=45)
|
plt.xticks(rotation=45)
|
||||||
plt.tight_layout()
|
plt.tight_layout()
|
||||||
|
plt.savefig(f"{OUTDIR}/cum_profit.png")
|
||||||
|
plt.close()
|
||||||
|
|
||||||
# === 2. PROFIT PER GAME (SCATTER) ===
|
# === PROFIT PER GAME ===
|
||||||
plt.figure()
|
plt.figure()
|
||||||
plt.scatter(range(len(df)), df["profit"])
|
plt.scatter(range(len(df)), df["profit"])
|
||||||
plt.title("Profit per Game")
|
plt.title("Profit per Game")
|
||||||
plt.xlabel("Game #")
|
plt.xlabel("Game #")
|
||||||
plt.ylabel("€")
|
plt.ylabel("€")
|
||||||
plt.tight_layout()
|
plt.tight_layout()
|
||||||
|
plt.savefig(f"{OUTDIR}/profit_scatter.png")
|
||||||
|
plt.close()
|
||||||
|
|
||||||
# === 3. ROI BY CATEGORY ===
|
# === ROI BY CATEGORY (SAFE) ===
|
||||||
roi = df.groupby("category").apply(
|
if "category" in df.columns:
|
||||||
lambda x: x["profit"].sum() / x["buy_in"].sum()
|
df_valid = df[df["buy_in"] > 0]
|
||||||
)
|
|
||||||
|
|
||||||
plt.figure()
|
if not df_valid.empty:
|
||||||
roi.plot(kind="bar")
|
roi = df_valid.groupby("category").apply(
|
||||||
plt.title("ROI by Game Type")
|
lambda x: x["profit"].sum() / x["buy_in"].sum()
|
||||||
plt.xlabel("Category")
|
)
|
||||||
plt.ylabel("ROI")
|
|
||||||
plt.tight_layout()
|
|
||||||
|
|
||||||
# === 4. SESSION PERFORMANCE ===
|
plt.figure()
|
||||||
|
roi.plot(kind="bar")
|
||||||
|
plt.title("ROI by Category")
|
||||||
|
plt.xlabel("Category")
|
||||||
|
plt.ylabel("ROI")
|
||||||
|
plt.tight_layout()
|
||||||
|
plt.savefig(f"{OUTDIR}/roi_category.png")
|
||||||
|
plt.close()
|
||||||
|
|
||||||
|
# === SESSION PERFORMANCE ===
|
||||||
if "session" in df.columns:
|
if "session" in df.columns:
|
||||||
session_profit = df.groupby("session")["profit"].sum()
|
session_profit = df.groupby("session")["profit"].sum()
|
||||||
|
|
||||||
@@ -80,8 +94,10 @@ if "session" in df.columns:
|
|||||||
plt.xlabel("Session")
|
plt.xlabel("Session")
|
||||||
plt.ylabel("€")
|
plt.ylabel("€")
|
||||||
plt.tight_layout()
|
plt.tight_layout()
|
||||||
|
plt.savefig(f"{OUTDIR}/session_profit.png")
|
||||||
|
plt.close()
|
||||||
|
|
||||||
# === 5. WIN DISTRIBUTION ===
|
# === POSITION DISTRIBUTION ===
|
||||||
if "position" in df.columns:
|
if "position" in df.columns:
|
||||||
pos_counts = df["position"].value_counts()
|
pos_counts = df["position"].value_counts()
|
||||||
|
|
||||||
@@ -91,6 +107,7 @@ if "position" in df.columns:
|
|||||||
plt.xlabel("Position")
|
plt.xlabel("Position")
|
||||||
plt.ylabel("Count")
|
plt.ylabel("Count")
|
||||||
plt.tight_layout()
|
plt.tight_layout()
|
||||||
|
plt.savefig(f"{OUTDIR}/positions.png")
|
||||||
|
plt.close()
|
||||||
|
|
||||||
# === SHOW ALL ===
|
print(f"✅ Graphs saved in: {OUTDIR}")
|
||||||
plt.show()
|
|
||||||
|
|||||||
Reference in New Issue
Block a user