Python 数据分析案例
下面用一个完整的 Python 案例,对比两支队(以 A队 vs B队 为例),看谁更擅长"逆风球"。

问题定义
"逆风球"通常指先丢球(落后)的比赛,评价一支队是否擅长逆风球,关键看:
| 指标 | 含义 |
|---|---|
| 落后场次 | 先丢球的比赛数量 |
| 逆转率 | 落后后最终取胜的比例 |
| 扳平率 | 落后后至少拿到 1 分的比例 |
| 落后时场均拿分 | 落后局面下的抢分效率 |
| 逆风净胜球 | 落后后净胜球变化 |
构造数据(模拟)
import pandas as pd
import numpy as np
np.random.seed(42)
# 模拟每场比赛:球队、是否先丢球、最终结果
def make_matches(team, n, comeback_rate, draw_rate):
"""生成某队 n 场比赛数据"""
records = []
for i in range(n):
conceded_first = np.random.rand() < 0.45 # 45% 的比赛先丢球
if conceded_first:
r = np.random.rand()
if r < comeback_rate: # 逆转胜
result = "胜"
elif r < comeback_rate + draw_rate: # 扳平
result = "平"
else:
result = "负"
else:
result = np.random.choice(["胜", "平", "负"], p=[0.6, 0.25, 0.15])
records.append({"team": team, "match_id": i,
"conceded_first": conceded_first, "result": result})
return records
data = make_matches("A队", 38, comeback_rate=0.30, draw_rate=0.25) + \
make_matches("B队", 38, comeback_rate=0.18, draw_rate=0.30)
df = pd.DataFrame(data)
print(df.head())
核心指标计算
# 结果转积分
points_map = {"胜": 3, "平": 1, "负": 0}
df["points"] = df["result"].map(points_map)
# 只看"逆风球"(先丢球)
trailing = df[df["conceded_first"]].copy()
summary = trailing.groupby("team").agg(
落后场次=("match_id", "count"),
逆转胜=("result", lambda s: (s == "胜").sum()),
扳平=("result", lambda s: (s == "平").sum()),
落后场均分=("points", "mean"),
落后总积分=("points", "sum"),
).reset_index()
summary["逆转率"] = summary["逆转胜"] / summary["落后场次"]
summary["扳平率"] = (summary["逆转胜"] + summary["扳平"]) / summary["落后场次"]
print(summary.round(3))
输出示例:
team 落后场次 逆转胜 扳平 落后场均分 落后总积分 逆转率 扳平率
0 A队 17 5 4 1.176 20 0.294 0.529
1 B队 16 3 5 0.875 14 0.188 0.500
可视化对比
import matplotlib.pyplot as plt
fig, axes = plt.subplots(1, 3, figsize=(14, 4))
# 1. 落后场均拿分
axes[0].bar(summary["team"], summary["落后场均分"], color=["#d62728", "#1f77b4"])
axes[0].set_title("落后时场均拿分")
axes[0].set_ylim(0, 2)
# 2. 逆转率
axes[1].bar(summary["team"], summary["逆转率"], color=["#d62728", "#1f77b4"])
axes[1].set_title("逆转率(落后→取胜)")
# 3. 扳平率
axes[2].bar(summary["team"], summary["扳平率"], color=["#d62728", "#1f77b4"])
axes[2].set_title("扳平率(落后→至少1分)")
plt.tight_layout()
plt.show()
进阶:逆风球"质量"评分
单看比例不够,可以做一个加权综合评分:
from sklearn.preprocessing import MinMaxScaler
score_df = summary[["team", "逆转率", "扳平率", "落后场均分"]].copy()
scaler = MinMaxScaler()
score_df[["逆转率", "扳平率", "落后场均分"]] = scaler.fit_transform(
score_df[["逆转率", "扳平率", "落后场均分"]])
# 权重:逆转 50%,扳平 30%,场均分 20%
score_df["逆风指数"] = (score_df["逆转率"] * 0.5 +
score_df["扳平率"] * 0.3 +
score_df["落后场均分"] * 0.2)
print(score_df.sort_values("逆风指数", ascending=False).round(3))
输出示例:
team 逆转率 扳平率 落后场均分 逆风指数
0 A队 1.000 1.000 1.000 1.000
1 B队 0.000 0.000 0.000 0.000
综合以上指标:
| 维度 | A队 | B队 | 优势方 |
|---|---|---|---|
| 逆转率 | ~29% | ~19% | A队 |
| 扳平率 | ~53% | ~50% | A队 |
| 落后场均分 | 18 | 88 | A队 |
| 逆风指数 | 高 | 低 | A队 |
A队更擅长逆风球。 它在先丢球后不仅取胜比例更高,抢分效率也明显优于 B队,说明其落后时的调整能力和心理韧性更强。
真实数据建议
若要用于真实赛事,建议:
- 数据源:用
football-data.orgAPI 或soccerdata库抓取历史比赛; - 细化指标:加入"落后时间长度""落后几球""主客场""对手强度"做分层分析;
- 显著性检验:用
scipy.stats.chi2_contingency检验两队逆转率差异是否显著,避免小样本偶然性。
from scipy.stats import chi2_contingency
# 列联表:[[A逆转, A未逆转], [B逆转, B未逆转]]
table = [[5, 12], [3, 13]]
chi2, p, dof, _ = chi2_contingency(table)
print(f"p = {p:.3f}") # p 较大时差异不显著
这个案例框架可直接替换成两队真实数据即可得出结论,需要我把它改成抓取真实联赛数据的版本吗?