Note
Go to the end to download the full example code.
Pass plot using lines
This example shows how to plot all passes from a team in a match as lines.
import matplotlib.pyplot as plt
from matplotlib import rcParams
from mplsoccer import Pitch, VerticalPitch, FontManager, Sbopen
rcParams['text.color'] = '#c7d5cc' # set the default text color
# get event dataframe for game 7478
parser = Sbopen()
df, related, freeze, tactics = parser.event(7478)
Boolean mask for filtering the dataset by team
team1, team2 = df.team_name.unique()
mask_team1 = (df.type_name == 'Pass') & (df.team_name == team1)
Filter dataset to only include one teams passes and get boolean mask for the completed passes
df_pass = df.loc[mask_team1, ['x', 'y', 'end_x', 'end_y', 'outcome_name']]
mask_complete = df_pass.outcome_name.isnull()
View the pass dataframe.
df_pass.head()
Plotting
# Setup the pitch
pitch = Pitch(pitch_type='statsbomb', pitch_color='#22312b', line_color='#c7d5cc')
fig, ax = pitch.draw(figsize=(16, 11), constrained_layout=False, tight_layout=True)
fig.set_facecolor('#22312b')
# Plot the completed passes
lc1 = pitch.lines(df_pass[mask_complete].x, df_pass[mask_complete].y,
df_pass[mask_complete].end_x, df_pass[mask_complete].end_y,
lw=5, transparent=True, comet=True, label='completed passes',
color='#ad993c', ax=ax)
# Plot the other passes
lc2 = pitch.lines(df_pass[~mask_complete].x, df_pass[~mask_complete].y,
df_pass[~mask_complete].end_x, df_pass[~mask_complete].end_y,
lw=5, transparent=True, comet=True, label='other passes',
color='#ba4f45', ax=ax)
# Plot the legend
ax.legend(facecolor='#22312b', edgecolor='None', fontsize=20, loc='upper left', handlelength=4)
# Set the title
ax_title = ax.set_title(f'{team1} passes vs {team2}', fontsize=30)
Plotting with grid. We will use mplsoccer’s grid function to plot a pitch with a title and endnote axes.
fig, axs = pitch.grid(endnote_height=0.03, endnote_space=0, figheight=12,
title_height=0.06, title_space=0,
# Turn off the endnote/title axis. I usually do this after
# I am happy with the chart layout and text placement
axis=False,
grid_height=0.86)
fig.set_facecolor('#22312b')
# Plot the completed passes
lc1 = pitch.lines(df_pass[mask_complete].x, df_pass[mask_complete].y,
df_pass[mask_complete].end_x, df_pass[mask_complete].end_y,
lw=5, transparent=True, comet=True, label='completed passes',
color='#ad993c', ax=axs['pitch'])
# Plot the other passes
lc2 = pitch.lines(df_pass[~mask_complete].x, df_pass[~mask_complete].y,
df_pass[~mask_complete].end_x, df_pass[~mask_complete].end_y,
lw=5, transparent=True, comet=True, label='other passes',
color='#ba4f45', ax=axs['pitch'])
# fontmanager for google font (robotto)
robotto_regular = FontManager()
# setup the legend
legend = axs['pitch'].legend(facecolor='#22312b', handlelength=5, edgecolor='None',
prop=robotto_regular.prop, loc='upper left')
for text in legend.get_texts():
text.set_fontsize(25)
# endnote and title
axs['endnote'].text(1, 0.5, '@your_twitter_handle', va='center', ha='right', fontsize=20,
fontproperties=robotto_regular.prop, color='#dee6ea')
ax_title = axs['title'].text(0.5, 0.5, f'{team1} passes vs {team2}', color='#dee6ea',
va='center', ha='center',
fontproperties=robotto_regular.prop, fontsize=25)
Filter datasets to only include passes leading to shots, and goals
TEAM1 = 'OL Reign'
TEAM2 = 'Houston Dash'
df_pass = df.loc[(df.pass_assisted_shot_id.notnull()) & (df.team_name == TEAM1),
['x', 'y', 'end_x', 'end_y', 'pass_assisted_shot_id']]
df_shot = (df.loc[(df.type_name == 'Shot') & (df.team_name == TEAM1),
['id', 'outcome_name', 'shot_statsbomb_xg']]
.rename({'id': 'pass_assisted_shot_id'}, axis=1))
df_pass = df_pass.merge(df_shot, how='left').drop('pass_assisted_shot_id', axis=1)
mask_goal = df_pass.outcome_name == 'Goal'
This example shows how to plot all passes leading to shots from a team using a colormap (cmap).
# Setup the pitch
pitch = VerticalPitch(pitch_type='statsbomb', pitch_color='#22312b', line_color='#c7d5cc',
half=True, pad_top=2)
fig, axs = pitch.grid(endnote_height=0.03, endnote_space=0, figheight=12,
title_height=0.08, title_space=0, axis=False,
grid_height=0.82)
fig.set_facecolor('#22312b')
# Plot the completed passes
pitch.lines(df_pass.x, df_pass.y, df_pass.end_x, df_pass.end_y,
lw=10, transparent=True, comet=True, cmap='jet',
label='pass leading to shot', ax=axs['pitch'])
# Plot the goals
pitch.scatter(df_pass[mask_goal].end_x, df_pass[mask_goal].end_y, s=700,
marker='football', edgecolors='black', c='white', zorder=2,
label='goal', ax=axs['pitch'])
pitch.scatter(df_pass[~mask_goal].end_x, df_pass[~mask_goal].end_y,
edgecolors='white', c='#22312b', s=700, zorder=2,
label='shot', ax=axs['pitch'])
# endnote and title
axs['endnote'].text(1, 0.5, '@your_twitter_handle', va='center', ha='right', fontsize=25,
fontproperties=robotto_regular.prop, color='#dee6ea')
axs['title'].text(0.5, 0.5, f'{TEAM1} passes leading to shots \n vs {TEAM2}', color='#dee6ea',
va='center', ha='center',
fontproperties=robotto_regular.prop, fontsize=25)
# set legend
legend = axs['pitch'].legend(facecolor='#22312b', edgecolor='None',
loc='lower center', handlelength=4)
for text in legend.get_texts():
text.set_fontproperties(robotto_regular.prop)
text.set_fontsize(25)
plt.show() # If you are using a Jupyter notebook you do not need this line
Total running time of the script: (0 minutes 2.332 seconds)