.. DO NOT EDIT. .. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. .. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: .. "gallery/lesson1/plot_PlottingShots.py" .. LINE NUMBERS ARE GIVEN BELOW. .. only:: html .. note:: :class: sphx-glr-download-link-note Click :ref:`here ` to download the full example code .. rst-class:: sphx-glr-example-title .. _sphx_glr_gallery_lesson1_plot_PlottingShots.py: Plotting shots ============== Start by watching the video below, then learn how to plot shot positions. .. youtube:: GWsK_KWKCas :width: 640 :height: 349 .. GENERATED FROM PYTHON SOURCE LINES 12-17 .. code-block:: default import matplotlib.pyplot as plt import numpy as np from mplsoccer import Pitch, Sbopen, VerticalPitch .. GENERATED FROM PYTHON SOURCE LINES 18-25 Opening the dataset ---------------------------- The first thing we have to do is open the data. We use a parser SBopen available in mplsoccer. Using method *event* and putting the id of the game as a parameter we load the data. The event data, which we will mostly focus on, is stored in a dataframe *df*. From this dataframe we take out the names of the two teams. Then, we filter the dataframe so that only shots are left. .. GENERATED FROM PYTHON SOURCE LINES 25-33 .. code-block:: default parser = Sbopen() df, related, freeze, tactics = parser.event(69301) #get team names team1, team2 = df.team_name.unique() #A dataframe of shots shots = df.loc[df['type_name'] == 'Shot'].set_index('id') .. GENERATED FROM PYTHON SOURCE LINES 34-48 Making the shot map using iterative solution ---------------------------- First let's draw the pitch using the `MPL Soccer class `_, In this example, we set variables for pitch length and width to the Statsbomb coordinate system (they use yards). You can read more about `different coordinate systems here `_ Now, we iterate through all the shots in the match. We take *x* and *y* coordinates, the team name and information if goal was scored. If It was scored, we plot a solid circle with a name of the player, if not, we plot a transculent circle (parameter alpha tunes the transcluency). To have England's shots on one half and Sweden shots on the other half, we subtract *x* and *y* from the pitch length and height. Football data tends to be attacking left to right, and we will use this as default in the course. .. GENERATED FROM PYTHON SOURCE LINES 48-85 .. code-block:: default pitch = Pitch(line_color = "black") fig, ax = pitch.draw(figsize=(10, 7)) #Size of the pitch in yards (!!!) pitchLengthX = 120 pitchWidthY = 80 #Plot the shots by looping through them. for i,shot in shots.iterrows(): #get the information x=shot['x'] y=shot['y'] goal=shot['outcome_name']=='Goal' team_name=shot['team_name'] #set circlesize circleSize=2 #plot England if (team_name==team1): if goal: shotCircle=plt.Circle((x,y),circleSize,color="red") plt.text(x+1,y-2,shot['player_name']) else: shotCircle=plt.Circle((x,y),circleSize,color="red") shotCircle.set_alpha(.2) #plot Sweden else: if goal: shotCircle=plt.Circle((pitchLengthX-x,pitchWidthY - y),circleSize,color="blue") plt.text(pitchLengthX-x+1,pitchWidthY - y - 2 ,shot['player_name']) else: shotCircle=plt.Circle((pitchLengthX-x,pitchWidthY - y),circleSize,color="blue") shotCircle.set_alpha(.2) ax.add_patch(shotCircle) #set title fig.suptitle("England (red) and Sweden (blue) shots", fontsize = 24) fig.set_size_inches(10, 7) plt.show() .. image-sg:: /gallery/lesson1/images/sphx_glr_plot_PlottingShots_001.png :alt: England (red) and Sweden (blue) shots :srcset: /gallery/lesson1/images/sphx_glr_plot_PlottingShots_001.png :class: sphx-glr-single-img .. GENERATED FROM PYTHON SOURCE LINES 86-97 Using mplsoccer's Pitch class ---------------------------- This time we make a direct query to return only shots by each team. We only need the columns with cooridnates, outcome (showing if goal was scored), and player name. If a goal was scored, we use scatter method to plot a circle and annotate method to mark scorer's name. If not, we use scatter method to draw a translucent circle. Note that, once again, to plot the shots on different halves we needed to reverse the coordinates for Sweden. Using pitch.scatter we could have plotted all shots using one line. However, since name of a player and alpha differs if goal was scored, it was more convenient to loop through smaller dataset. .. GENERATED FROM PYTHON SOURCE LINES 97-131 .. code-block:: default #create pitch pitch = Pitch(line_color='black') fig, ax = pitch.grid(grid_height=0.9, title_height=0.06, axis=False, endnote_height=0.04, title_space=0, endnote_space=0) #query mask_england = (df.type_name == 'Shot') & (df.team_name == team1) #finding rows in the df and keeping only necessary columns df_england = df.loc[mask_england, ['x', 'y', 'outcome_name', "player_name"]] #plot them - if shot ended with Goal - alpha 1 and add name #for England for i, row in df_england.iterrows(): if row["outcome_name"] == 'Goal': #make circle pitch.scatter(row.x, row.y, alpha = 1, s = 500, color = "red", ax=ax['pitch']) pitch.annotate(row["player_name"], (row.x + 1, row.y - 2), ax=ax['pitch'], fontsize = 12) else: pitch.scatter(row.x, row.y, alpha = 0.2, s = 500, color = "red", ax=ax['pitch']) mask_sweden = (df.type_name == 'Shot') & (df.team_name == team2) df_sweden = df.loc[mask_sweden, ['x', 'y', 'outcome_name', "player_name"]] #for Sweden we need to revert coordinates for i, row in df_sweden.iterrows(): if row["outcome_name"] == 'Goal': pitch.scatter(120 - row.x, 80 - row.y, alpha = 1, s = 500, color = "blue", ax=ax['pitch']) pitch.annotate(row["player_name"], (120 - row.x + 1, 80 - row.y - 2), ax=ax['pitch'], fontsize = 12) else: pitch.scatter(120 - row.x, 80 - row.y, alpha = 0.2, s = 500, color = "blue", ax=ax['pitch']) fig.suptitle("England (red) and Sweden (blue) shots", fontsize = 30) plt.show() .. image-sg:: /gallery/lesson1/images/sphx_glr_plot_PlottingShots_002.png :alt: England (red) and Sweden (blue) shots :srcset: /gallery/lesson1/images/sphx_glr_plot_PlottingShots_002.png :class: sphx-glr-single-img .. GENERATED FROM PYTHON SOURCE LINES 132-138 Plotting shots on one half ---------------------------- To plot shots of only one team on one half we use VerticalPitch() class If you set *half* to *True*, you will plot only one half of the pitch. It is a nice way of plotting shots since they rarely occur on the defensive half. We plot all the shots at once this time, without looping through the dataframe this time. .. GENERATED FROM PYTHON SOURCE LINES 138-147 .. code-block:: default pitch = VerticalPitch(line_color='black', half = True) fig, ax = pitch.grid(grid_height=0.9, title_height=0.06, axis=False, endnote_height=0.04, title_space=0, endnote_space=0) #plotting all shots pitch.scatter(df_england.x, df_england.y, alpha = 1, s = 500, color = "red", ax=ax['pitch'], edgecolors="black") fig.suptitle("England shots against Sweden", fontsize = 30) plt.show() .. image-sg:: /gallery/lesson1/images/sphx_glr_plot_PlottingShots_003.png :alt: England shots against Sweden :srcset: /gallery/lesson1/images/sphx_glr_plot_PlottingShots_003.png :class: sphx-glr-single-img .. GENERATED FROM PYTHON SOURCE LINES 148-154 Challenge - try it before looking at the next page ---------------------------- 1) Create a dataframe of passes which contains all the passes in the match 2) Plot the start point of every Sweden pass. Attacking left to right. 3) Plot only passes made by Caroline Seger (she is Sara Caroline Seger in the database) 4) Plot arrows to show where the passes went to. .. rst-class:: sphx-glr-timing **Total running time of the script:** ( 0 minutes 0.398 seconds) .. _sphx_glr_download_gallery_lesson1_plot_PlottingShots.py: .. only:: html .. container:: sphx-glr-footer sphx-glr-footer-example .. container:: sphx-glr-download sphx-glr-download-python :download:`Download Python source code: plot_PlottingShots.py ` .. container:: sphx-glr-download sphx-glr-download-jupyter :download:`Download Jupyter notebook: plot_PlottingShots.ipynb ` .. only:: html .. rst-class:: sphx-glr-signature `Gallery generated by Sphinx-Gallery `_