Python案例:统计单刀球成功率
下面我用一个完整的Python案例来演示如何统计足球比赛中单刀球(1v1面对门将)的成功率。

需求分析
单刀球成功率 = 单刀球进球数 / 单刀球总次数 × 100%
需要的数据字段:
- 球员姓名
- 单刀球总次数
- 单刀球进球数
基础版:字典统计
# 球员单刀球数据:{球员: [单刀总数, 进球数]}
single_knife_data = {
"梅西": [12, 8],
"姆巴佩": [15, 9],
"哈兰德": [10, 7],
"C罗": [14, 6],
"萨拉赫": [11, 7],
"维尼修斯":[13, 5],
}
# 计算每位球员的单刀球成功率
print(f"{'球员':<8}{'单刀次数':<10}{'进球数':<8}{'成功率':<8}")
print("-" * 40)
results = []
for player, (total, goals) in single_knife_data.items():
rate = goals / total * 100
results.append((player, total, goals, rate))
print(f"{player:<8}{total:<10}{goals:<8}{rate:.2f}%")
# 排序:按成功率从高到低
print("\n=== 单刀成功率排行榜 ===")
results.sort(key=lambda x: x[3], reverse=True)
for i, (player, total, goals, rate) in enumerate(results, 1):
print(f"第{i}名: {player} 成功率 {rate:.2f}% ({goals}/{total})")
输出示例:
球员 单刀次数 进球数 成功率
----------------------------------------
梅西 12 8 66.67%
姆巴佩 15 9 60.00%
哈兰德 10 7 70.00%
C罗 14 6 42.86%
萨拉赫 11 7 63.64%
维尼修斯 13 5 38.46%
=== 单刀成功率排行榜 ===
第1名: 哈兰德 成功率 70.00% (7/10)
第2名: 梅西 成功率 66.67% (8/12)
第3名: 萨拉赫 成功率 63.64% (7/11)
第4名: 姆巴佩 成功率 60.00% (9/15)
第5名: C罗 成功率 42.86% (6/14)
第6名: 维尼修斯 成功率 38.46% (5/13)
进阶版:使用 Pandas + 可视化
import pandas as pd
import matplotlib.pyplot as plt
# 解决中文显示问题
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False
# 构造数据
data = {
"球员": ["梅西", "姆巴佩", "哈兰德", "C罗", "萨拉赫", "维尼修斯"],
"单刀次数": [12, 15, 10, 14, 11, 13],
"进球数": [8, 9, 7, 6, 7, 5]
}
df = pd.DataFrame(data)
# 计算成功率
df["成功率"] = (df["进球数"] / df["单刀次数"] * 100).round(2)
# 按成功率排序
df = df.sort_values("成功率", ascending=False).reset_index(drop=True)
# 打印表格
print(df.to_string(index=False))
# 联赛整体单刀成功率
total_knife = df["单刀次数"].sum()
total_goal = df["进球数"].sum()
league_rate = total_goal / total_knife * 100
print(f"\n整体单刀成功率: {league_rate:.2f}% ({total_goal}/{total_knife})")
# 可视化
fig, ax = plt.subplots(figsize=(8, 5))
bars = ax.bar(df["球员"], df["成功率"], color="steelblue")
# 在柱子上显示数值
for bar, rate in zip(bars, df["成功率"]):
ax.text(bar.get_x() + bar.get_width()/2, bar.get_height() + 1,
f"{rate}%", ha="center", fontsize=10)
# 平均线
ax.axhline(league_rate, color="red", linestyle="--", label=f"平均 {league_rate:.1f}%")
ax.set_ylabel("单刀成功率 (%)")
ax.set_title("球员单刀球成功率对比")
ax.set_ylim(0, 100)
ax.legend()
plt.tight_layout()
plt.show()
输出效果:
球员 单刀次数 进球数 成功率
哈兰德 10 7 70.00
梅西 12 8 66.67
萨拉赫 11 7 63.64
姆巴佩 15 9 60.00
C罗 14 6 42.86
维尼修斯 13 5 38.46
整体单刀成功率: 56.00% (42/75)
同时会生成一张柱状图,直观展示每位球员的成功率对比。
扩展:处理真实比赛事件数据
如果你有逐场比赛的事件数据(例如从 StatsBomb、Opta 或爬虫获取),可以这样处理:
import pandas as pd
# 假设 events.csv 字段: match_id, player, event_type, result
# event_type 为 "1v1" 或 "big_chance",result 为 "goal" / "miss" / "saved"
df = pd.read_csv("events.csv")
# 筛选单刀球事件
knife = df[df["event_type"] == "1v1"]
# 按球员分组统计
summary = knife.groupby("player").agg(
单刀次数=("result", "count"),
进球数=("result", lambda x: (x == "goal").sum())
).reset_index()
summary["成功率"] = (summary["进球数"] / summary["单刀次数"] * 100).round(2)
summary = summary.sort_values("成功率", ascending=False)
print(summary)
关键点总结
| 要点 | 说明 |
|---|---|
| 公式 | 成功率 = 进球数 ÷ 单刀次数 × 100% |
| 注意分母 | 分母必须是"单刀球机会"而非"射门次数" |
| 数据来源 | 通常来自比赛的 shot-level 或 event-level 数据 |
| 可视化 | 用柱状图 + 平均线更直观 |
| 进阶统计 | 可按联赛、赛季、位置分组,或做显著性检验 |
需要我针对具体数据源(如 StatsBomb 开放数据、中超数据、FIFA 游戏数据)写一个更贴近实战的案例吗?