本文目录导读:

- 统计口径定义
- 方案1:Python + Pandas(本地CSV/Excel数据)
- 方案2:调用 API(FBref / API-Football / Sofascore)
- 方案3:SQL 版(数据库内统计)
- 方案4:Excel 公式(无代码)
- 实用增强点
- 数据源建议
统计头球争顶成功率需要明确数据来源和统计口径,以下是几种实用脚本方案,覆盖不同场景:
统计口径定义
头球争顶成功率 = 争顶成功次数 / 争顶总次数 × 100%
关键字段通常包括:
- 球员ID/姓名
- 争顶总数(Aerial Duels)
- 争顶成功数(Aerial Duels Won)
- 比赛/赛季标识
- 位置、出场时间(用于过滤)
方案1:Python + Pandas(本地CSV/Excel数据)
import pandas as pd
def aerial_duel_success_rate(df, player_col='player',
total_col='aerial_total',
won_col='aerial_won',
min_duels=10):
"""
统计头球争顶成功率
min_duels: 最少争顶次数阈值,避免小样本偏差
"""
df = df.copy()
# 过滤小样本
df = df[df[total_col] >= min_duels]
# 计算成功率
df['success_rate'] = (df[won_col] / df[total_col] * 100).round(2)
# 按球员聚合(多场比赛汇总)
result = df.groupby(player_col).agg(
total_duels=(total_col, 'sum'),
won_duels=(won_col, 'sum'),
matches=(total_col, 'count')
).reset_index()
result['success_rate'] = (result['won_duels'] / result['total_duels'] * 100).round(2)
result = result.sort_values('success_rate', ascending=False)
return result
# 使用示例
df = pd.read_csv('aerial_stats.csv')
rank = aerial_duel_success_rate(df)
print(rank.head(20))
rank.to_csv('aerial_success_ranking.csv', index=False)
方案2:调用 API(FBref / API-Football / Sofascore)
FBref(免费,需爬取)
import pandas as pd
import requests
def get_fbref_aerial(url):
"""url FBref 球员/球队 standard 页面"""
tables = pd.read_html(url)
# 找到含 'Aerial' 的表,具体索引需按页面调整
df = tables[0]
return df
# 示例:某球员赛季数据
# df = get_fbref_aerial('https://fbref.com/en/players/xxx/')
API-Football(付费,结构化好)
import requests
API_KEY = "your_key"
HEADERS = {"x-apisports-key": API_KEY}
def get_player_aerial(player_id, season=2023, league=39):
url = "https://v3.football.api-sports.io/players"
params = {"id": player_id, "season": season, "league": league}
r = requests.get(url, headers=HEADERS, params=params).json()
stats = r['response'][0]['statistics'][0]['duels']
total = stats['total']
won = stats['won']
rate = won / total * 100 if total else 0
return {"total": total, "won": won, "rate": round(rate, 2)}
方案3:SQL 版(数据库内统计)
SELECT
player_name,
SUM(aerial_total) AS total_duels,
SUM(aerial_won) AS won_duels,
ROUND(SUM(aerial_won) * 100.0 / NULLIF(SUM(aerial_total), 0), 2) AS success_rate
FROM match_player_stats
WHERE season = '2024-25'
AND aerial_total >= 10 -- 小样本过滤
GROUP BY player_name
HAVING SUM(aerial_total) >= 30 -- 赛季总样本阈值
ORDER BY success_rate DESC;
方案4:Excel 公式(无代码)
若数据在 Excel:
=IFERROR(D2/C2, 0) // 单场成功率 =SUMIF(A:A, "球员名", D:D)/SUMIF(A:A, "球员名", C:C) // 汇总
或用数据透视表:行=球员,值=争顶成功/争顶总数,再添加计算字段。
实用增强点
- 位置分组:中后卫/前锋争顶基线不同,建议分位置对比
result = df.groupby(['position', player_col])...
- 加权平均 vs 简单平均:多场汇总要用「总成功/总次数」,不能对每场成功率取平均
- 对手强度修正:可按对手联赛/球队强度分层
- 可视化:
import matplotlib.pyplot as plt top10 = rank.head(10) plt.barh(top10['player'], top10['success_rate']) plt.xlabel('头球争顶成功率 (%)') plt.gca().invert_yaxis() plt.show()
数据源建议
| 数据源 | 费用 | 字段完整度 | 适合场景 |
|---|---|---|---|
| FBref | 免费 | 高(含争顶) | 个人/研究 |
| Sofascore API | 免费/受限 | 高 | 快速查询 |
| API-Football | 付费 | 中高 | 产品集成 |
| Opta/StatsBomb | 付费 | 最高(含坐标) | 专业分析 |
需要我针对某个具体数据源(FBref 爬虫、某 API 的响应解析)写出完整可运行脚本吗?告诉我你的数据格式或来源即可。