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
相关产品推荐
相关产品推荐

