本文目录导读:

在Python中量化射门转化率的高低,不能只看一个简单的除法(进球/射门),因为没有考虑射门的难度,真正的量化需要结合数据科学的方法。
这里我提供三个层级的量化方案,从基础统计到进阶模型,你可以根据数据条件选择。
基础修正版(适合仅有基础数据的球迷/分析师)
如果只有进球数(Goals)、射门数(Shots)和联赛平均数据,可以计算标准化转化率(z-score),即评估“比平均水平高出几个标准差”。
核心逻辑:只要射门数足够多,单纯的高转化率可能包含运气成分,引入“射门加权调整”(类似棒球中的wOBA),但用Python实现:
import numpy as np
import pandas as pd
# 模拟数据:不同球员
data = {
'player': ['A', 'B', 'C', 'D'],
'goals': [15, 10, 8, 5],
'shots': [50, 100, 30, 20],
'xG_per_shot': [0.11, 0.14, 0.09, 0.12] # 每次射门的期望进球(如果没xG,可用联赛平均替代)
}
df = pd.DataFrame(data)
# 基础转化率
df['basic_rate'] = df['goals'] / df['shots']
# ---- 核心量化指标:xG差值法(衡量“状态”或“实力”)----
# 总预期进球
df['total_xG'] = df['shots'] * df['xG_per_shot']
# 实际进球 - 预期进球
df['xG_diff'] = df['goals'] - df['total_xG']
# 转化率与预期的比值(>1 表示超常发挥)
df['expected_ratio'] = df['goals'] / df['total_xG']
# ---- 进阶:计算“射门转化效率等级”----
# 设定阈值(基于历史数据统计)
# xG_ratio > 1.15 且总射门 > 50,判定为“高效终结者”
df['level'] = np.where((df['expected_ratio'] > 1.15) & (df['shots'] > 30), '高',
np.where(df['expected_ratio'] < 0.85, '低', '正常'))
print(df[['player', 'basic_rate', 'expected_ratio', 'level']])
输出解释:
expected_ratio = 1.2意味着球员比预期进球多20%,这是“量化高低”的标准。- 重点:如果球员A只有50脚射门,打出15球(ratio=1.2),说明他把握机会能力极强;但如果球员B打出100脚射门进10球(ratio=0.71),则说明转化率低于预期,可能存在大量低质量射门。
科学量化版(适用于有逐球事件数据)
如果你有每脚射门的坐标(x,y),构建射门质量评分模型,这是量化转化率高低最科学的做法——射门转化率 = 预期进球率(xG)。
构建基础xG模型(Logistic回归)
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import train_test_split
# 假设你有历史数据:射门坐标距离、角度、是否进球
# 特征:distance(距球门距离),angle(角度),是点球(1/0),是头球(1/0)
X = np.array([[10, 30, 0, 0], # 近角、小角度
[20, 15, 0, 0], # 远射、正面
[5, 45, 1, 0]]) # 点球
y = np.array([0, 0, 1]) # 是否进球
# 实际应用中X会有几千行,这里仅示意
model = LogisticRegression()
model.fit(X, y)
# 利用模型计算每个球员的“预期转化率”
def calc_xG(shots_df):
features = shots_df[['distance', 'angle', 'penalty', 'header']].values
each_xg = model.predict_proba(features)[:, 1] # 每次射门进球概率
shots_df['xG'] = each_xg
player_xg = shots_df.groupby('player')['xG'].sum()
actual_goals = shots_df.groupby('player')['goal'].sum()
ratio = actual_goals / player_xg
return ratio
# 用法:ratio > 1 表示转化率高于预期,反之低于预期。
引入转化率置信区间(防止小样本误判)
使用二项分布检验,区分“真实的强”和“运气好”。
from scipy.stats import binomtest
def conversion_assessment(goals, shots, xG_rate):
"""
goals: 实际进球数
shots: 总射门数
xG_rate: 该名球员的平均预期转化率(0.12)
"""
# 零假设:该球员的真实转化率就是xG_rate
p_value = binomtest(goals, shots, xG_rate, alternative='greater').pvalue
if p_value < 0.05:
return f"超过预期水平(p={p_value:.3f}),有统计显著性"
else:
return f"未超过预期水平(p={p_value:.3f}),可能属于正常波动"
print(conversion_assessment(goals=15, shots=50, xG_rate=0.11))
# 输出:超过预期水平(p=0.000...),有统计显著性
动态实时量化(模拟蒙特卡洛)
这是量化“射门转化率”背后得分效率波动的方法,通过模拟10000次该球员在同样射门质量下的进球数分布,看“当前进球数”处于分布的什么位置。
import matplotlib.pyplot as plt
import numpy as np
def simulate_scoring(shot_probs, actual_goals, n_sims=10000):
"""
shot_probs: 该球员每脚射门的xG概率列表
actual_goals: 该球员实际总进球数
"""
sim_goals = np.random.binomial(1, shot_probs, size=(n_sims, len(shot_probs))).sum(axis=1)
# 分位数
p90 = np.percentile(sim_goals, 90)
p10 = np.percentile(sim_goals, 10)
mean_goals = sim_goals.mean()
# 实际进球在模拟分布中的百分位
percentile_rank = (sim_goals < actual_goals).mean() * 100
print(f"预期平均进球: {mean_goals:.1f}")
print(f"90%情况进不超过: {p90:.0f}球")
print(f"实际进{actual_goals}球,超过模拟中的 {percentile_rank:.1f}% 情况")
# 可视化
plt.hist(sim_goals, bins=30, alpha=0.7)
plt.axvline(actual_goals, color='r', linestyle='--', label=f'实际进球={actual_goals}')
plt.legend()
plt.title('进球数模拟分布(射门质量已固定)')
plt.show()
# 用法示例:某球员有5次射门,xG分别为 [0.2, 0.1, 0.3, 0.05, 0.15],实际进1球
simulate_scoring([0.2, 0.1, 0.3, 0.05, 0.15], 1)
结果解读:如果实际进球数为1,在模拟的10000次中,有85%的情况下都进不了1球(即大部分时候只有0球),这说明该球员的转化率不仅高,而且在低射门数量下实现了超常输出,属于“极高”的量化结果。
量化射门转化率高低的“黄金法则”
| 指标 | 公式/方法 | 判定标准(高/低) |
|---|---|---|
| 基础转化率 | goals/shots |
联赛平均(如8%)为基准,高于10%为高 |
| xG差值法 | actual - xG_total |
高出预期进球数 ≥ 2球 → 高效 |
| 科学模型xG | actual / xG_total |
比值 > 1.2(且样本>20脚) → 极高 |
| 统计显著性 | P值(二项检验) | P < 0.05 才说明是“真水平” |
| 稳定性量化 | 模拟分位数 | 超越90%模拟情况 → 极高 |
最后建议:如果没有xG数据,用“基础转化率 + 联赛平均对比”即可,但一定要加上射门数过滤(如至少射门25次以上),否则进球效率(如2脚进1球)没有统计意义,会被误判为“极高”。