本文目录导读:

这是一个非常实用且足球数据爱好者会关心的脚本需求,背身拿球成功率(通常指接球后成功转身或成功回做球的成功率)在足球数据分析中通常涉及对抗成功与传球成功的组合。
由于不同的数据源(如StatsBomb、Opta)对“背身”的定义不同,我为你提供一个基于Python逻辑的可运行脚本,并提供一个网页版(HTML)的简易计算器,方便你快速使用。
Python 数据清洗与计算脚本(专业级)
这个脚本假设你有一份包含球员事件数据的CSV(逗号分隔值)文件,包含了接球位置、是否对抗、是否成功等信息,脚本会输出每个球员的背身拿球成功率。
import pandas as pd
import numpy as np
def calculate_back_to_goal_success_rate(df):
"""
计算背身拿球成功率。
逻辑:球员接球时如果身体朝向与进攻方向相反(或球门方向),且身位处于对方半场。
"""
# 假设数据拥有以下列 (请根据你的数据调整列名):
# 'player' : 球员名
# 'event' : 事件类型 (Receival / Pass / Duel)
# 'x' : 事件X坐标 (0-100)
# 'y' : 事件Y坐标 (0-100)
# 'body_angle': 身体角度 (度,0度=面向对方球门)
# 'outcome' : 结果 (Success / Fail)
# 1. 过滤出接球事件 (Receival)
receivals = df[df['event'] == 'Receival'].copy()
# 2. 定义“背身”条件:
# - 身体朝向与进攻方向相反 (角度 > 90度 或 面向本方球门)
# - 且位置在后场或中场(排除在禁区内抢点)
# - 假设你在对方半场接球,身体朝向本方半场,即为背身
# 这里简化为:如果身体角度 > 90 度,视为背身接球
receivals['is_back_to_goal'] = receivals['body_angle'] > 90
# 过滤掉非背身接球
back_receivals = receivals[receivals['is_back_to_goal']].copy()
# 3. 关联后续结果:
# - 成功(Success)定义:接球后顺利传球给队友(传球成功)或在对抗中没丢球权。
# 我们这里假设数据中有 'next_event_outcome' 列表示该次触球后的结果。
# 如果没有,我们可以通过合并下一次触球来计算。
# 简化处理:假设 outcome 列直接标记了这次拿球是否成功。
successes = back_receivals[back_receivals['outcome'] == 'Success']
# 4. 计算成功率
result = back_receivals.groupby('player').apply(
lambda x: pd.Series({
'背身拿球次数': len(x),
'背身拿球成功次数': len(x[x['outcome'] == 'Success']),
'成功率': (len(x[x['outcome'] == 'Success']) / len(x) * 100).round(2) if len(x) > 0 else 0
})
).reset_index()
# 5. 过滤掉样本太小的球员(例如少于10次)
result = result[result['背身拿球次数'] >= 10]
return result.sort_values('成功率', ascending=False)
# --- 示例用法 ---
if __name__ == "__main__":
# 生成模拟数据 (Test Data)
np.random.seed(42)
n_samples = 1000
players = ['Kane', 'Haaland', 'Benzema', 'Osimhen']
data = {
'player': np.random.choice(players, n_samples),
'event': np.random.choice(['Receival', 'Pass', 'Duel'], n_samples, p=[0.5, 0.3, 0.2]),
'x': np.random.uniform(30, 80, n_samples), # 偏向前场
'y': np.random.uniform(0, 100, n_samples),
'body_angle': np.random.uniform(0, 180, n_samples), # 0度=面对球门
'outcome': np.random.choice(['Success', 'Fail'], n_samples, p=[0.7, 0.3])
}
# 只保留面向本方球门的接球 (angle > 90)
df_test = pd.DataFrame(data)
# 计算
result_df = calculate_back_to_goal_success_rate(df_test)
print("🏆 背身拿球成功率排行榜 (Top 5):")
print(result_df.to_string(index=False))
HTML + JavaScript 可视化计算器(轻量级)
如果你没有编程环境,或者只是想快速计算某场比赛的几项数据,可以使用下面的网页工具,直接在浏览器中运行,输入总数和成功数即可。
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">⚽ 背身拿球成功率计算器</title>
<style>
body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
background: linear-gradient(135deg, #0f2027, #203a43, #2c5364);
color: #fff;
min-height: 100vh;
display: flex;
justify-content: center;
align-items: center;
margin: 0;
}
.container {
background: rgba(255, 255, 255, 0.1);
backdrop-filter: blur(10px);
padding: 40px;
border-radius: 20px;
box-shadow: 0 8px 32px 0 rgba(0, 0, 0, 0.5);
border: 1px solid rgba(255, 255, 255, 0.2);
width: 400px;
text-align: center;
}
h1 {
margin-bottom: 30px;
font-size: 24px;
border-bottom: 2px solid #4CAF50;
padding-bottom: 10px;
display: inline-block;
}
.input-group {
margin: 20px 0;
text-align: left;
}
label {
display: block;
margin-bottom: 8px;
font-weight: 600;
color: #e0e0e0;
}
input {
width: 95%;
padding: 12px;
border: none;
border-radius: 8px;
font-size: 16px;
background: rgba(255, 255, 255, 0.2);
color: #fff;
outline: none;
transition: 0.3s;
}
input:focus {
background: rgba(255, 255, 255, 0.3);
box-shadow: 0 0 0 2px #4CAF50;
}
input::placeholder {
color: #c0c0c0;
opacity: 0.7;
}
button {
width: 100%;
padding: 14px;
background: linear-gradient(90deg, #4CAF50, #45a049);
border: none;
border-radius: 12px;
color: white;
font-size: 18px;
font-weight: bold;
cursor: pointer;
margin-top: 10px;
transition: transform 0.2s;
}
button:hover {
transform: scale(1.02);
}
button:active {
transform: scale(0.98);
}
.result-box {
margin-top: 25px;
padding: 20px;
background: rgba(0, 0, 0, 0.4);
border-radius: 12px;
border-left: 5px solid #4CAF50;
opacity: 0;
transition: opacity 0.5s;
}
.result-box.show {
opacity: 1;
}
.percentage {
font-size: 42px;
font-weight: 900;
color: #ffd700;
}
.detail {
color: #bbb;
margin-top: 10px;
font-size: 14px;
}
.note {
margin-top: 20px;
font-size: 12px;
color: #aaa;
text-align: left;
line-height: 1.6;
border-top: 1px dashed #666;
padding-top: 10px;
}
</style>
</head>
<body>
<div class="container">
<h1>⚽ 背身拿球成功率</h1>
<form id="calcForm">
<div class="input-group">
<label for="attempts">⏱️ 背身拿球总次数</label>
<input type="number" id="attempts" name="attempts" min="0" placeholder="30" required>
</div>
<div class="input-group">
<label for="success">✅ 成功转身/回做球次数</label>
<input type="number" id="success" name="success" min="0" placeholder="22" required>
</div>
<div class="input-group">
<label for="context">🏷️ 场景描述(可选)</label>
<input type="text" id="context" placeholder="英超赛季 - 凯恩">
</div>
<button type="button" onclick="calculate()">📊 计算成功率</button>
</form>
<div class="result-box" id="resultBox">
<div class="percentage" id="percentage">--%</div>
<div class="detail" id="detail">等待计算...</div>
</div>
<div class="note">
<strong>📌 定义说明:</strong><br>
成功率 = (成功次数 ÷ 总尝试次数) × 100%<br>
<span style="color: #ffd700;">及格线:60%</span> | <span style="color: #4CAF50;">优秀线:70%</span> | <span style="color: #ff6347;">顶级:75%+</span>
</div>
</div>
<script>
function calculate() {
const attempts = parseFloat(document.getElementById('attempts').value);
const success = parseFloat(document.getElementById('success').value);
const context = document.getElementById('context').value || '球员数据';
// 输入验证
if (isNaN(attempts) || attempts <= 0) {
alert('请输入有效的背身拿球总次数!');
return;
}
if (isNaN(success) || success < 0 || success > attempts) {
alert('成功次数必须介于 0 和总次数之间!');
return;
}
const percentage = ((success / attempts) * 100).toFixed(1);
// 评级
let grade = '';
if (percentage >= 75) grade = '🌟 世界级水准';
else if (percentage >= 70) grade = '🏆 精英级别';
else if (percentage >= 60) grade = '✅ 合格水平';
else if (percentage >= 50) grade = '⚠️ 有待提升';
else grade = '❌ 需大量训练';
// 显示结果
const box = document.getElementById('resultBox');
document.getElementById('percentage').textContent = percentage + '%';
document.getElementById('detail').innerHTML =
`${context}:<strong>${success}/${attempts}</strong> 次成功<br>评级:${grade}`;
box.classList.add('show');
}
</script>
</body>
</html>
使用建议与说明
-
成功率”的定义:
- 在专业足球数据(如Wyscout)中,这个数据通常特指“Under Pressure”情况下的Forward Pass Success或Duel Success。
- 真正的背身拿球成功不仅指你没丢球,还指你传球给队友的准确率(尤其是向前传球),你可以调整Python脚本中的
outcome字段,将“成功”定义为“传球成功且方向向前”。
-
剔除干扰项:
- 补时阶段、垃圾时间的胜负已定比赛,球员的对抗强度会下降,这会影响数据公正性,建议在Python脚本中增加
minute列过滤(只统计1-80分钟的数据)。
- 补时阶段、垃圾时间的胜负已定比赛,球员的对抗强度会下降,这会影响数据公正性,建议在Python脚本中增加
-
对手强度修正:
- 顶级的背身中锋(如凯恩)面对高位逼抢时成功率会低于面对低位防守,如果你有对手的
pressure_level字段,可以进行加权计算。
- 顶级的背身中锋(如凯恩)面对高位逼抢时成功率会低于面对低位防守,如果你有对手的
-
可视化输出:
- 你可以在Python脚本中加上
matplotlib来绘制柱状图,比较不同球员之间的差距。
- 你可以在Python脚本中加上
你觉得这个脚本是否符合你的需求? 如果你有具体的数据文件(或数据格式),可以告诉我,我可以帮你调整成可以直接读取你数据的版本。