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

数据准备
import pandas as pd
import matplotlib.pyplot as plt
# 模拟单刀球数据(每行代表一次单刀球机会)
data = {
'球员': [
'武磊', '武磊', '武磊', '武磊', '武磊',
'姆巴佩', '姆巴佩', '姆巴佩', '姆巴佩', '姆巴佩', '姆巴佩',
'哈兰德', '哈兰德', '哈兰德', '哈兰德', '哈兰德', '哈兰德', '哈兰德',
'梅西', '梅西', '梅西', '梅西', '梅西', '梅西',
'孙兴慜', '孙兴慜', '孙兴慜', '孙兴慜', '孙兴慜'
],
'结果': [
'进球', '进球', '未进', '进球', '未进',
'进球', '进球', '进球', '未进', '进球', '进球',
'进球', '进球', '未进', '进球', '进球', '未进', '进球',
'进球', '未进', '进球', '进球', '未进', '进球',
'进球', '进球', '未进', '进球', '未进'
]
}
df = pd.DataFrame(data)
print(df.head())
统计每个球员的单刀成功率
# 方法1:使用groupby + apply
def calc_success_rate(group):
total = len(group)
scores = (group['结果'] == '进球').sum()
return scores / total if total > 0 else 0
success_rate = df.groupby('球员')['结果'].apply(
lambda x: (x == '进球').sum() / len(x)
).reset_index(name='单刀成功率')
# 计算次数
count_df = df.groupby('球员')['结果'].agg(
单刀次数='count',
进球数=lambda x: (x == '进球').sum()
).reset_index()
# 合并
result = pd.merge(count_df, success_rate, on='球员')
result['单刀成功率'] = result['单刀成功率'].round(3)
result = result.sort_values('单刀成功率', ascending=False)
print(result)
输出结果:
球员 单刀次数 进球数 单刀成功率
0 姆巴佩 6 5 0.833
1 哈兰德 7 5 0.714
2 梅西 6 4 0.667
3 孙兴慜 5 3 0.600
4 武磊 5 3 0.600
统计整体单刀成功率
# 全局成功率
total_shots = len(df)
total_goals = (df['结果'] == '进球').sum()
overall_rate = total_goals / total_shots
print(f"总单刀次数:{total_shots}")
print(f"总进球数:{total_goals}")
print(f"整体单刀成功率:{overall_rate:.2%}")
输出:
总单刀次数:29
总进球数:20
整体单刀成功率:68.97%
可视化(柱状图)
# 设置中文
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False
fig, ax = plt.subplots(figsize=(8, 5))
bars = ax.bar(result['球员'], result['单刀成功率'], color='#1f77b4')
# 在柱子上显示数值
for bar, rate in zip(bars, result['单刀成功率']):
ax.text(bar.get_x() + bar.get_width()/2, bar.get_height() + 0.02,
f'{rate:.1%}', ha='center', fontsize=10)
ax.set_ylabel('单刀成功率')
ax.set_title('球员单刀球成功率对比')
ax.set_ylim(0, 1)
plt.tight_layout()
plt.show()
扩展:按结果分析
# 统计结果分布
result_dist = df['结果'].value_counts()
print(result_dist)
# 用饼图展示
result_dist.plot.pie(autopct='%1.1f%%', figsize=(5,5),
title='单刀球结果分布')
plt.ylabel('')
plt.show()
关键公式总结
| 指标 | 公式 |
|---|---|
| 单刀成功率 | 进球数 ÷ 单刀总次数 |
| 球员效率 | groupby('球员') 后 apply |
| 全局成功率 | df整体计算 |
真实数据扩展建议
若要用真实足球数据,可以:
- 爬取数据:使用
requests+BeautifulSoup从懂球帝、Whoscored、FBref 等网站抓取 - 使用API:StatsBomb、Opta 等提供结构化事件数据(event data)
- 关键字段:球员、射门位置、是否1对1、是否进球、比赛时间
# 真实数据示例结构 # df 应包含: 球员, 位置(x,y), 对手人数, 结果, 比赛ID # 筛选单刀球条件:射门位置在禁区内 且 只有门将防守 single_knife = df[(df['位置_x'] > 80) & (df['防守人数'] == 1)]
需要我针对特定联赛/球员的真实数据做统计,或者用爬虫抓取真实数据,可以再告诉我!