ai-market-mechanism/plots/generate_plots.py
agent-runner ef901e2eb9 v4.0: 地市间对比分析 + 实施路线图 + 风险缓解矩阵
- 新增 3.7 地市间对比分析(表 6,8 地市分三梯队,含梯度分析与跨地市验证)
- 新增 5.4 实施路线图与风险缓解(表 7 三阶段路线图 + 表 8 六类风险矩阵)
- 更新 notebooks/pilot_analysis.md(新增第 9-10 节)
- 新增 plots/city_comparison.png + city_comparison.csv + roadmap_data.csv
- 更新 processing/validate_data.py(校验扩展至 46 项,全部通过)
2026-08-21 10:47:22 +00:00

122 lines
4.2 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env python3
"""生成试点数据分析图表。
输出:
plots/pilot_run_data.png — 各地市预警数据柱状图
plots/vendor_effort.png — 供应商人天投入饼图
plots/access_cost.png — 接入链路耗时对比图
"""
import csv
import os
import sys
import matplotlib
matplotlib.use("Agg")
import matplotlib.pyplot as plt
PLOT_DIR = os.path.dirname(os.path.abspath(__file__))
def load_csv(name):
path = os.path.join(PLOT_DIR, name)
with open(path, encoding="utf-8") as f:
return list(csv.DictReader(f))
def plot_run_data():
rows = load_csv("pilot_run_data.csv")
cities = [r["city"] for r in rows]
alerts = [int(r["alert_count"]) if r["alert_count"] else 0 for r in rows]
colors = ["#2196F3" if a > 0 else "#BDBDBD" for a in alerts]
fig, ax = plt.subplots(figsize=(10, 5))
bars = ax.bar(cities, alerts, color=colors)
ax.set_ylabel("累计预警数据(条)")
ax.set_title("各地市电量突增能力应用预警数据(截至 2026-06-25")
for bar, val in zip(bars, alerts):
if val > 0:
ax.text(bar.get_x() + bar.get_width() / 2, val + 200,
f"{val:,}", ha="center", fontsize=9)
plt.xticks(rotation=30, ha="right")
plt.tight_layout()
plt.savefig(os.path.join(PLOT_DIR, "pilot_run_data.png"), dpi=150)
plt.close()
def plot_vendor_effort():
rows = load_csv("vendor_effort.csv")
labels = [r["category"] for r in rows]
sizes = [int(r["person_days"]) for r in rows]
fig, ax = plt.subplots(figsize=(8, 6))
wedges, texts, autotexts = ax.pie(
sizes, labels=labels, autopct="%1.0f%%", startangle=140,
textprops={"fontsize": 9},
)
ax.set_title("供应商人天投入结构(合计 100 人天)")
plt.tight_layout()
plt.savefig(os.path.join(PLOT_DIR, "vendor_effort.png"), dpi=150)
plt.close()
def plot_access_cost():
rows = load_csv("access_cost.csv")
steps = [r["step"] for r in rows if r["step"] != "端到端合计"]
ideal = [int(r["ideal_days"]) for r in rows if r["step"] != "端到端合计"]
actual = [int(r["actual_days"]) for r in rows if r["step"] != "端到端合计"]
x = range(len(steps))
width = 0.35
fig, ax = plt.subplots(figsize=(10, 5))
ax.bar([i - width / 2 for i in x], ideal, width, label="理想耗时", color="#4CAF50")
ax.bar([i + width / 2 for i in x], actual, width, label="实际耗时", color="#FF5722")
ax.set_ylabel("耗时(工作日)")
ax.set_title("单地市接入链路耗时:理想 vs 实际")
ax.set_xticks(x)
ax.set_xticklabels(steps, rotation=20, ha="right")
ax.legend()
plt.tight_layout()
plt.savefig(os.path.join(PLOT_DIR, "access_cost.png"), dpi=150)
plt.close()
def plot_city_comparison():
rows = load_csv("city_comparison.csv")
cities = [r["city"] for r in rows]
alerts = [int(r["alert_count"]) for r in rows]
teams = [r["team"] for r in rows]
colors = {"第一梯队": "#4CAF50", "第二梯队": "#2196F3", "第三梯队": "#BDBDBD"}
bar_colors = [colors.get(t, "#999") for t in teams]
fig, ax = plt.subplots(figsize=(10, 5))
bars = ax.bar(cities, alerts, color=bar_colors)
ax.set_ylabel("累计预警数据(条)")
ax.set_title("各地市接入阶段与产出对比(截至 2026-06-25")
for bar, val, team in zip(bars, alerts, teams):
if val > 0:
ax.text(bar.get_x() + bar.get_width() / 2, val + 200,
f"{val:,}", ha="center", fontsize=9)
else:
ax.text(bar.get_x() + bar.get_width() / 2, 200,
team, ha="center", fontsize=8, color="#666")
from matplotlib.patches import Patch
legend = [Patch(facecolor=colors[t], label=t) for t in ["第一梯队", "第二梯队", "第三梯队"]]
ax.legend(handles=legend, loc="upper right")
plt.xticks(rotation=30, ha="right")
plt.tight_layout()
plt.savefig(os.path.join(PLOT_DIR, "city_comparison.png"), dpi=150)
plt.close()
def main():
plot_run_data()
plot_vendor_effort()
plot_access_cost()
plot_city_comparison()
print("图表已生成pilot_run_data.png, vendor_effort.png, access_cost.png, city_comparison.png")
if __name__ == "__main__":
main()