Commit 67c38fb5 authored by jerrrrry's avatar jerrrrry
Browse files

Replace plot.py

parent f30e0381
import argparse, pandas as pd, matplotlib #!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
需求:
1. 生成 1 张「跨-Sheet 5 指标汇总」柱状图(保留)
2. 额外生成 5 张「单指标跨-Sheet 对比柱状图」
3. 全部输出到指定文件夹
python six_plots.py your.xlsx -o output_folder
"""
import argparse, pandas as pd, matplotlib, os, re
matplotlib.use('Agg') matplotlib.use('Agg')
import matplotlib.pyplot as plt, re, os import matplotlib.pyplot as plt
# ---------- 工具 ----------
def find_avg_row(df): def find_avg_row(df):
for idx, row in df.iterrows(): for idx, row in df.iterrows():
if any(isinstance(cell, str) and re.search(r'平均值|Average', str(cell)) for cell in row): if any(isinstance(cell, str) and re.search(r'平均值|Average', str(cell)) for cell in row):
...@@ -10,90 +21,96 @@ def find_avg_row(df): ...@@ -10,90 +21,96 @@ def find_avg_row(df):
def extract_values(df): def extract_values(df):
idx = find_avg_row(df) idx = find_avg_row(df)
vals = [float(v) for v in df.iloc[idx].dropna().iloc[-4:] if str(v).replace('.', '').isdigit()] vals = [float(v) for v in df.iloc[idx].dropna().iloc[-5:] if str(v).replace('.', '').isdigit()]
if len(vals) != 4: if len(vals) != 5:
vals = [float(v) for v in df.iloc[-1].dropna().iloc[-4:] if str(v).replace('.', '').isdigit()] vals = [float(v) for v in df.iloc[-1].dropna().iloc[-5:] if str(v).replace('.', '').isdigit()]
if len(vals) != 4: return dict(zip(['total_throughput', 'generate_throughput', 'singel_road_generate_throughput', 'generate_throughput_without_ttft', 'ttft'], vals))
raise ValueError("无法提取4个百分比")
return { # ---------- 绘图 ----------
"Total_throughput": vals[3], def draw_bar(data, labels, colors, title, out_path, xlabels):
"generate_throughput": vals[2], fig, ax = plt.subplots(figsize=(max(len(xlabels) * 0.8, 12), 6))
"singel_road_generate_throughput": vals[1], fig.patch.set_facecolor('#ffffff')
"generate_throughput_without_ttft": vals[0] ax.set_facecolor('#ffffff')
} bars = ax.bar(xlabels, data, color=colors, width=0.6)
for bar, v in zip(bars, data):
height = bar.get_height()
ax.annotate(f"{v:.1f}%",
xy=(bar.get_x() + bar.get_width() / 2, height),
xytext=(0, 3), textcoords='offset points',
ha='center', va='bottom', fontsize=7, rotation=60,
bbox=dict(boxstyle="round,pad=0.15", facecolor='white', edgecolor='none'))
ax.set_ylabel("Percentage")
ax.set_title(title, fontsize=13, weight='bold')
ax.grid(axis='y', linestyle='-', linewidth=0.25, alpha=0.2)
ax.tick_params(axis='x', rotation=30)
plt.tight_layout()
for ext in ['png', 'pdf']:
plt.savefig(f"{out_path}.{ext}", dpi=300 if ext == 'png' else None, bbox_inches='tight')
plt.close()
def plot_summary(file_path, output_prefix): # ---------- 主流程 ----------
xls = pd.ExcelFile(file_path) def main():
summary = {} parser = argparse.ArgumentParser(description='生成 6 张柱状图:1 张汇总 + 5 张单指标')
for sheet in xls.sheet_names: parser.add_argument("xlsx_path", help="输入 Excel 文件")
try: parser.add_argument("-o", "--output", default="output", help="输出文件夹")
df = pd.read_excel(xls, sheet_name=sheet, header=None) args = parser.parse_args()
summary[sheet] = extract_values(df)
except Exception: xls = pd.ExcelFile(args.xlsx_path)
continue summary = {sheet: extract_values(pd.read_excel(xls, sheet_name=sheet, header=None))
if not summary: for sheet in xls.sheet_names}
print("❌ 无数据可绘图")
return
labels = [ labels = [
"Total_throughput", "total_throughput",
"generate_throughput", "generate_throughput",
"singel_road_generate_throughput", "singel_road_generate_throughput",
"generate_throughput_without_ttft" "generate_throughput_without_ttft",
"ttft"
] ]
# 大师级配色(Material 2024) colors = ['#005F73', '#0A9396', '#94D2BD', '#E9D8A6', '#d62728']
colors = ['#005F73', '#0A9396', '#94D2BD', '#E9D8A6'] os.makedirs(args.output, exist_ok=True)
# 1. 跨-Sheet 5 指标汇总(原图保持不变)
models = list(summary.keys()) models = list(summary.keys())
x = range(len(models)) x = range(len(models))
bar_width = 0.18 bar_width = 0.14
fig, ax = plt.subplots(figsize=(max(len(models) * 1.1, 14), 8)) fig, ax = plt.subplots(figsize=(max(len(models) * 1.1, 14), 8))
fig.patch.set_facecolor('#F8F9FA') fig.patch.set_facecolor('#F8F9FA')
ax.set_facecolor('#FFFFFF') ax.set_facecolor('#FFFFFF')
for i, lab in enumerate(labels): for i, lab in enumerate(labels):
vals = [summary[m][lab] for m in models] vals = [summary[m][lab] for m in models]
offset = (i - 1.5) * bar_width offset = (i - 1.5) * bar_width
bars = ax.bar([p + offset for p in x], vals, width=bar_width, bars = ax.bar([p + offset for p in x], vals, width=bar_width,
label=lab.replace('_', ' ').title(), color=colors[i]) label=lab.replace('_', ' ').title(), color=colors[i])
# 保持倾斜 60° + 虚线指引
for bar, v in zip(bars, vals): for bar, v in zip(bars, vals):
height = bar.get_height() height = bar.get_height()
# 虚线起点(柱顶中心)
line_start = (bar.get_x() + bar.get_width() / 2, height) line_start = (bar.get_x() + bar.get_width() / 2, height)
# 文本终点(再向上 5%)
text_pos = (line_start[0], height + max(vals) * 0.05) text_pos = (line_start[0], height + max(vals) * 0.05)
# 画虚线
ax.plot([line_start[0], text_pos[0]], [line_start[1], text_pos[1]], ax.plot([line_start[0], text_pos[0]], [line_start[1], text_pos[1]],
color='#555555', linestyle='--', linewidth=0.8, alpha=0.7) color='#555555', linestyle='--', linewidth=0.8, alpha=0.7)
# 倾斜 60° 文字
ax.text(text_pos[0], text_pos[1], f"{v:.1f}%", ax.text(text_pos[0], text_pos[1], f"{v:.1f}%",
ha='center', va='bottom', fontsize=7, ha='center', va='bottom', fontsize=7, rotation=60,
rotation=60, color='#000000', weight='bold') color='#000000', weight='bold')
# 轴 & 网格
ax.set_xticks(x) ax.set_xticks(x)
ax.set_xticklabels(models, rotation=25, ha='right', fontsize=10, weight='bold') ax.set_xticklabels(models, rotation=25, ha='right', fontsize=10, weight='bold')
ax.set_ylabel("Percentage", fontsize=12, weight='bold') ax.set_ylabel("Percentage", fontsize=12, weight='bold')
ax.set_title("Throughput Comparison", fontsize=16, weight='bold', pad=20) ax.set_title("Throughput Comparison", fontsize=16, weight='bold', pad=20)
ax.grid(axis='y', linestyle='-', linewidth=0.3, alpha=0.3, color='#DEE2E6') ax.grid(axis='y', linestyle='-', linewidth=0.3, alpha=0.3, color='#DEE2E6')
ax.legend(frameon=False, loc='upper left', bbox_to_anchor=(1.02, 1), fontsize=9) ax.legend(frameon=False, loc='upper left', bbox_to_anchor=(1.02, 1), fontsize=9)
plt.subplots_adjust(left=0.05, right=0.85, bottom=0.12, top=0.92) plt.tight_layout()
for ext in ['png', 'pdf']: for ext in ['png', 'pdf']:
plt.savefig(f"{output_prefix}.{ext}", dpi=300 if ext == 'png' else None, plt.savefig(os.path.join(args.output, f"summary.{ext}"), dpi=300 if ext == 'png' else None,
bbox_inches='tight') bbox_inches='tight')
print(f"✅ 已保存:{output_prefix}.png / .pdf") plt.close()
# 2-6. 5 张单指标跨-Sheet 对比图
for lab, color in zip(labels, colors):
vals = [summary[s][lab] for s in models]
draw_bar(vals, [lab], [color],
f"{lab.replace('_', ' ').title()} - All Sheets",
os.path.join(args.output, lab),
models)
if __name__ == "__main__": print(f"✅ 6 张图已生成:{args.output}")
parser = argparse.ArgumentParser()
parser.add_argument("xlsx_path") if __name__ == '__main__':
parser.add_argument("-o", "--output", default="summary_chart") main()
args = parser.parse_args()
plot_summary(args.xlsx_path, args.output)
\ No newline at end of file
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment