You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Statsbomb xG足球射门图射门点未按预期坐标位置绘制问题

问题根源

射门点全部聚集在角落是代码逻辑bug导致的:

  • 坐标值类型错误:用正则和split拆分location字段后,得到的横纵坐标都是字符串格式,没有转成浮点数。mplsoccer的散点接口接收到字符串输入时,不会按数值映射球场坐标,会把所有字符串值归类到坐标轴起始位置,最终所有点堆在角落。
  • 坐标解析逻辑有缺陷:原正则直接剔除所有非数字、小数点、空格的字符,一旦原始location字段里逗号前后的空格数量不一致,split后会生成空字符串元素,取到无效坐标值。
  • 额外逻辑遗漏:原代码只写了英格兰队的射门绘制分支,突尼斯队的所有射门都没有被画出来。
修复后代码

直接替换原有坐标解析和绘图部分即可,修复后坐标会正确映射到球场对应位置:

import pandas as pd
import matplotlib.pyplot as plt
from mplsoccer import Pitch

data = pd.read_csv('TN_EN_WC18.csv')

# 更稳妥的坐标解析逻辑,直接转成浮点型数值
data[['x', 'y']] = data['location'].str.strip('[]')\
                            .str.split(',', expand=True)\
                            .astype(float)

pitch = Pitch(pitch_type='statsbomb', pitch_color='#0f1029', line_color='White')
fig, axs = pitch.draw(figsize=(10, 8))

# 遍历绘制所有射门
for _, row in data.iterrows():
    point_size = row['shot_statsbomb_xg'] * 1000
    # 配色规则:进球用绿色,英格兰非进球用红色,突尼斯非进球用蓝色
    if row['shot_outcome'] == 'Goal':
        c = '#33ff69'
    elif row['team'] == 'England':
        c = '#ff4433'
    else:
        c = '#3399ff'
    pitch.scatter(row['x'], row['y'], s=point_size, c=c, ax=axs, 
                  alpha=0.8, edgecolor='white', zorder=3)

# 设置图表样式
fig.suptitle('2018世界杯小组赛 突尼斯vs英格兰 xG射门图', 
             fontsize=20, color="White", fontweight='bold', fontfamily="Monospace")
fig.set_size_inches(15, 7)
fig.set_facecolor("#0f1029")

plt.tight_layout()
plt.show()
可选优化项
  • 如果需要把两队射门都绘制在进攻方向的对方半场(即常规xG射门图的视角,两边进攻方向都朝向对方球门),可以对其中一队的坐标做翻转:突尼斯队的x坐标用120 - x、y坐标用80 - y即可适配StatsBomb的120*80坐标体系。
  • 散点添加edgecolor='white'和透明度参数后,重叠的射门点辨识度会明显提升。
  • 如果需要给进球点加特殊标记,可以在scatter里加marker='*'单独调整进球点的样式。

内容的提问来源于stack exchange,提问作者Anas Souabni

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.28 08:03:27