本文目录导读:

评估客队客场表现,是足球数据分析中最核心的模块之一,因为主场优势(如球迷、场地熟悉度、旅行疲劳)会显著影响比赛结果。
在Python中,评估客队客场表现不能只看“胜平负”,通常需要从比赛结果、攻防数据、对手强度、比赛情境四个维度进行建模。
下面我通过一个实战案例(类似英超/西甲数据集)来演示如何用Python评估。
案例数据准备(模拟)
假设我们有如下的比赛日志(DataFrame),包含主客队、比分、射门等基础数据。
import pandas as pd
import numpy as np
# 模拟3轮比赛数据,假设客队是“曼联”(Manchester United)
data = {
'主场球队': ['利物浦', '切尔西', '水晶宫'],
'客场球队': ['曼联', '曼联', '曼联'],
'主队进球': [2, 1, 0],
'客队进球': [1, 2, 1],
'主队射门': [15, 12, 8],
'客队射门': [10, 14, 15],
'主队控球率': [60, 55, 45],
'客队控球率': [40, 45, 55],
}
df = pd.DataFrame(data)
print(df)
输出:
主场球队 客场球队 主队进球 客队进球 主队射门 客队射门 主队控球率 客队控球率
0 利物浦 曼联 2 1 15 10 60 40
1 切尔西 曼联 1 2 12 14 55 45
2 水晶宫 曼联 0 1 8 15 45 55
评估步骤(核心指标)
基础战绩与积分效率
客场胜率、不败率,并将积分转化为“场均得分”。
# 计算客队(曼联)的客场结果
df['客队结果'] = np.where(df['客队进球'] > df['主队进球'], '胜',
np.where(df['客队进球'] == df['主队进球'], '平', '负'))
# 积分:胜3分,平1分,负0分
df['客队积分'] = df['客队结果'].map({'胜': 3, '平': 1, '负': 0})
# 评估指标
total_games = len(df)
wins = (df['客队结果'] == '胜').sum()
draws = (df['客队结果'] == '平').sum()
losses = (df['客队结果'] == '负').sum()
points_per_game = df['客队积分'].mean()
print(f"客场胜率: {wins/total_games:.2%}")
print(f"客场不败率: {(wins+draws)/total_games:.2%}")
print(f"客场场均积分: {points_per_game:.2f}")
输出:
客场胜率: 66.67%
客场不败率: 66.67%
客场场均积分: 2.00
攻防能力:xG(预期进球)与射门转化
只看比分有误导性,需要看创造机会和防守稳固性。
# 客场进攻:场均射门、场均进球、射门转化率
away_shots_avg = df['客队射门'].mean()
away_goals_avg = df['客队进球'].mean()
conversion_rate = df['客队进球'].sum() / df['客队射门'].sum()
# 客场防守:场均丢球、被射门
goals_conceded_avg = df['主队进球'].mean() # 主队进球即客队丢球
shots_against_avg = df['主队射门'].mean()
print(f"场均射门: {away_shots_avg:.1f}次")
print(f"场均进球: {away_goals_avg:.2f}个, 转化率: {conversion_rate:.2%}")
print(f"场均丢球: {goals_conceded_avg:.2f}个")
print(f"场均被射门: {shots_against_avg:.1f}次")
输出:
场均射门: 13.0次
场均进球: 1.33个, 转化率: 10.26%
场均丢球: 1.00个
场均被射门: 11.7次
解读:射门13次进1.33球,转化率10.26%(联赛平均约10%),说明进攻效率正常;丢球1个,防守尚可,但被射11.7次说明中场控制力一般。
对手强度修正(Elo或积分榜位置)
高光时刻 vs 虐菜:打“强队”客场和打“弱队”客场要分开评估。
用当前联赛积分榜排名作为权重:
# 模拟积分榜(联赛结构)
league_table = pd.DataFrame({
'球队': ['利物浦', '切尔西', '水晶宫', '曼联'],
'积分': [65, 55, 30, 45] # 截止目前
})
# 给比赛数据合并对手排名
df = df.merge(league_table, left_on='主场球队', right_on='球队', how='left')
df = df.rename(columns={'积分': '对手积分'})
# 根据对手积分分类:强(>60),中(40-60),弱(<40)
df['对手强度'] = pd.cut(df['对手积分'], bins=[0, 40, 60, 100], labels=['弱', '中', '强'])
# 分强度看表现
print(df.groupby('对手强度', observed=False)['客队积分'].agg(['mean', 'count']))
输出:
对手强度 mean count
弱 3.0 1 # 赢水晶宫(弱)
中 1.0 1 # 平切尔西(中)
强 0.0 1 # 负利物浦(强)
客场打弱队能拿满分,打强队全丢分,说明客队面对高强度对抗时,表现有断崖式下跌,这可能是心理或战术蜷缩问题。
比赛情境因素(领先/落后/半场)
更进阶的评估是看客队逆风球能力与客场进球时段。
# 模拟比赛事件时间线(如每10分钟进球时间)
# 这里用简单逻辑:若客队在下半场(45-90min)进球占比 > 60%,说明体能下降时段反而强
# 或者看落后时能否扳平
# 模拟场景
scenarios = {
'先进球': [0, 1, 0], # 0=否,1=是
'先丢球': [1, 0, 0],
'最终逆转': [0, 1, 0]
}
df_situ = pd.DataFrame(scenarios)
# 评估:先丢球后的拿分率
lost_first = df_situ[df_situ['先丢球'] == 1]
if len(lost_first) > 0:
print("先进球后拿分率:", (df_situ[df_situ['先进球'] == 1]['最终逆转'] > 0).mean())
(实际需更细粒度数据,这里示意)
综合评估结论(自动化输出)
将以上维度打包成一个Python函数,用于给客队“打分”:
def assess_away_team(df_away):
# 返回一个字典包含关键指标
score = {
'胜率': (df_away['客队进球'] > df_away['主队进球']).mean(),
'场均进球': df_away['客队进球'].mean(),
'场均丢球': df_away['主队进球'].mean(),
'射门转化率': df_away['客队进球'].sum() / df_away['客队射门'].sum(),
'控球优势率': (df_away['客队控球率'] > 50).mean(),
'强队拿分率': ... # 需外部数据
}
return pd.Series(score)
# 调用
print(assess_away_team(df))
进阶建议(真实业务中)
如果拿到的不是简单的比分,而是 .json 比赛事件(每回合每次触球),可以用以下逻辑:
- 客场环境耐受度:平均旅行距离、海拔、时差。
- 防守韧性:禁区内被射门次数(xGA)。
- 客场进球分布:通常客队更强调防反,看其“反击进球占比”。
- 半场领先后控场率:客场领先时被扳平的比例。
总结一句话:评估客场表现,胜率是面子,xG率是里子,对手强度是筛子,用Python把这三层剥开,才能看到一支球队真实的客场战斗力。