def keypasses(Df,hometeam,homeid,awayteam,awayid): df = Df.copy() pitch = Pitch(pitch_type='statsbomb', figsize=(10,5), line_zorder=2, layout=(1,2), line_color='k', orientation='horizontal',constrained_layout=True, tight_layout=False) fig, ax = pitch.draw() homedef = df.query("(teamId==@homeid)&(KP == 1)&(endX!=0)&(endY!=0)") awaydef = df.query("(teamId==@awayid)&(KP == 1)&(endX!=0)&(endY!=0)") # homemask = homedef.outcomeType_displayName == 'Successful' # awaymask = awaydef.outcomeType_displayName == 'Successful' pitch.arrows(homedef.x,80-homedef.y,homedef.endX,80-homedef.endY,headwidth=5, headlength=5, zorder=5,color='#fee090',width=1,ax=ax[0]) # pitch.lines(homedef[~homemask].x,80-homedef[~homemask].y,homedef[~homemask].endX,80-homedef[~homemask].endY, # zorder=5,color='tab:red',linewidth=2,comet=True,ax=ax[0]) pitch.arrows(awaydef.x,80-awaydef.y,awaydef.endX,80-awaydef.endY,headwidth=5, headlength=5, zorder=5,color='#fee090',width=1,ax=ax[1]) # pitch.lines(awaydef[~awaymask].x,80-awaydef[~awaymask].y,awaydef[~awaymask].endX,80-awaydef[~awaymask].endY, # zorder=5,color='tab:red',linewidth=2,comet=True,ax=ax[1]) ax[0].set_title(hometeam+'\n'+'Key Passes',fontsize=30) ax[1].set_title(awayteam+'\n'+'Key Passes',fontsize=30) fig.text(0.0, 0.0, "Created by Soumyajit Bose / @Soumyaj15209314",fontstyle="italic",fontsize=15,color='#edece9') # add_image(bu_alt, fig, left=0.9, bottom=0.01, width=0.07) return fig
def badpasses(Df,hometeam,homeid): df = Df.copy() pitch = Pitch(pitch_type='statsbomb', figsize=(10,4.5), line_zorder=2, layout=(1,2), line_color='k', orientation='horizontal',constrained_layout=True, tight_layout=False) fig, ax = pitch.draw() def3rd = df.query("(teamId==@homeid)&(type_displayName == 'Pass')&(x<40)") mid3rd = df.query("(teamId==@homeid)&(type_displayName == 'Pass')&(x>=40)&(x<80)") defmask = def3rd.outcomeType_displayName == 'Successful' midmask = mid3rd.outcomeType_displayName == 'Successful' # awaymask = awaydef.outcomeType_displayName == 'Successful' pitch.arrows(def3rd[~defmask].x,80-def3rd[~defmask].y,def3rd[~defmask].endX,80-def3rd[~defmask].endY, headwidth=5, headlength=5,zorder=5,color='tab:red',width=1,ax=ax[0]) # pitch.lines(homedef[~homemask].x,80-homedef[~homemask].y,homedef[~homemask].endX,80-homedef[~homemask].endY, # zorder=5,color='tab:red',linewidth=2,comet=True,ax=ax[0]) pitch.arrows(mid3rd[~midmask].x,80-mid3rd[~midmask].y,mid3rd[~midmask].endX,80-mid3rd[~midmask].endY, headwidth=5, headlength=5,zorder=5,color='tab:red',width=1,ax=ax[1]) # pitch.lines(awaydef[~awaymask].x,80-awaydef[~awaymask].y,awaydef[~awaymask].endX,80-awaydef[~awaymask].endY, # zorder=5,color='tab:red',linewidth=2,comet=True,ax=ax[1]) ax[0].set_title(hometeam+' Unsuccessful Passes'+'\n'+'from defensive 3rd',fontsize=20) ax[1].set_title(hometeam+' Unsuccessful Passes'+'\n'+'from middle 3rd',fontsize=20) # fig.text(0.0, 0.05, "All unsuccessful passes originating from defensive third of the pitch",fontstyle="italic",fontsize=15,color='#edece9') fig.text(0.0, 0.0, "Created by Soumyajit Bose / @Soumyaj15209314",fontstyle="italic",fontsize=15,color='#edece9') # add_image(bu_alt, fig, left=0.9, bottom=0.0, width=0.07) return fig
constrained_layout=True, tight_layout=False) fig, ax = pitch.draw() fig.set_facecolor('#22312b') for i, pas in Passes.iterrows(): x = pas['location'][0] y = pas['location'][1] endx = pas['pass_end_location'][0] endy = pas['pass_end_location'][1] name = pas['player_name'] == 'Virgil van Dijk' if name: pitch.scatter(x, y, ax=ax, s=100, edgecolor='black', facecolor='cornflowerblue') pitch.arrows(x, y, endx, endy, width=2, headwidth=10, headlength=10, color='#ad993c', ax=ax, label='completed passes') ax.set_title('VVD vs Spurs', color='#dee6ea', fontsize=25)
# Setup the pitch pitch = Pitch(pitch_type='statsbomb', orientation='horizontal', pitch_color='#22312b', line_color='#c7d5cc', figsize=(16, 11), constrained_layout=False, tight_layout=True) fig, ax = pitch.draw() # Plot the completed passes pitch.arrows(df_pass[mask_complete].x, df_pass[mask_complete].y, df_pass[mask_complete].pass_end_x, df_pass[mask_complete].pass_end_y, width=2, headwidth=10, headlength=10, color='#ad993c', ax=ax, label='completed passes') # Plot the other passes pitch.arrows(df_pass[~mask_complete].x, df_pass[~mask_complete].y, df_pass[~mask_complete].pass_end_x, df_pass[~mask_complete].pass_end_y, width=2, headwidth=6, headlength=5, headaxislength=12, color='#ba4f45',
def getTeamTotalPasses(events_df, teamId, team, opponent, pitch_color): """ Parameters ---------- events_df : DataFrame of all events. teamId : ID of the team, the passes of which are required. team : Name of the team, the passes of which are required. opponent : Name of opponent team. pitch_color : color of the pitch. Returns ------- Pitch Plot. """ # Get Total Passes passes_df = events_df.loc[events_df['type'] == 'Pass'].reset_index( drop=True) # Get Team Passes team_passes = passes_df.loc[passes_df['teamId'] == teamId] successful_passes = team_passes.loc[team_passes['outcomeType'] == 'Successful'].reset_index(drop=True) unsuccessful_passes = team_passes.loc[ team_passes['outcomeType'] == 'Unsuccessful'].reset_index(drop=True) # Setup the pitch pitch = Pitch(pitch_type='statsbomb', pitch_color=pitch_color, line_color='#c7d5cc', figsize=(16, 11)) fig, ax = pitch.draw(constrained_layout=True, tight_layout=False) # Plot the completed passes pitch.arrows(successful_passes.x / 100 * 120, 80 - successful_passes.y / 100 * 80, successful_passes.endX / 100 * 120, 80 - successful_passes.endY / 100 * 80, width=1, headwidth=10, headlength=10, color='#ad993c', ax=ax, label='Completed') # Plot the other passes pitch.arrows(unsuccessful_passes.x / 100 * 120, 80 - unsuccessful_passes.y / 100 * 80, unsuccessful_passes.endX / 100 * 120, 80 - unsuccessful_passes.endY / 100 * 80, width=1, headwidth=6, headlength=5, headaxislength=12, color='#ba4f45', ax=ax, label='Blocked') # setup the legend ax.legend(facecolor=pitch_color, handlelength=5, edgecolor='None', fontsize=8, loc='upper left', shadow=True) # Set the title fig.suptitle(f'{team} Passes vs {opponent}', y=1, fontsize=15) # Set the subtitle ax.set_title('Data : Whoscored/Opta', fontsize=8, loc='right', fontstyle='italic', fontweight='bold') # Set the figure facecolor fig.set_facecolor(pitch_color)
def passmap(Df, teamid, teamname, min1, max1): pitch = Pitch(pitch_type='statsbomb', orientation='vertical', pitch_color='#000000', line_color='#a9a9a9', constrained_layout=True, tight_layout=False, linewidth=0.5) fig, ax = pitch.draw() df = Df.copy() df = df[(df.expandedMinute >= min1) & (df.expandedMinute <= max1)] allplayers = df[(df.teamId == teamid) & (df.name.notna())].name.tolist() playersubbedoff = df[(df.type_displayName == 'SubstitutionOff') & (df.teamId == teamid)]['name'].tolist() timeoff = df[(df.type_displayName == 'SubstitutionOff') & (df.teamId == teamid)]['expandedMinute'].tolist() playersubbedon = df[(df.type_displayName == 'SubstitutionOn') & (df.teamId == teamid)]['name'].tolist() timeon = df[(df.type_displayName == 'SubstitutionOn') & (df.teamId == teamid)]['expandedMinute'].tolist() majoritylist = [] minoritylist = [] for i in range(len(timeon)): if ((timeon[i] >= min1) & (timeon[i] <= max1)): player1min = timeon[i] - min1 player2min = max1 - timeon[i] if (player1min >= player2min): majoritylist.append(playersubbedoff[i]) minoritylist.append(playersubbedon[i]) else: majoritylist.append(playersubbedon[i]) minoritylist.append(playersubbedoff[i]) players = list(set(allplayers) - set(minoritylist)) #return players shirtNo = [] for p in players: shirtNo.append(int(df[df.name == p]['shirtNo'].values[0])) passes_df = df.query( "(type_displayName=='Pass')&(name in @players)&(receiver in @players)&\ (outcomeType_displayName == 'Successful')&(teamId==@teamid)") #passes_df.insert(29, column='passRecipientName', value=passes_df['name'].shift(-1)) passes_df.dropna(subset=["receiver"], inplace=True) #passes_df['passer'] = passes_df['playerId'] #passes_df['recipient'] = passes_df['passer'].shift(-1) passes_df = passes_df[passes_df.columns[~passes_df.isnull().all()]] passes_df['playerKitNumber'] = passes_df['shirtNo'].fillna(0).astype( np.int) passes_df['playerKitNumberReceipt'] = passes_df['shirtNo'].shift( -1).fillna(0).astype(np.int) passer_avg = passes_df.groupby('playerKitNumber').agg({ 'x': ['median'], 'y': ['median', 'count'], 'epv_value': ['sum'] }) passer_avg.columns = ['x', 'y', 'count', 'epv'] passer_avg.index = passer_avg.index.astype(int) passes_formation = passes_df[[ 'id', 'playerKitNumber', 'playerKitNumberReceipt' ]].copy() passes_formation['kitNo_max'] = passes_formation[[ 'playerKitNumber', 'playerKitNumberReceipt' ]].max(axis='columns') passes_formation['kitNo_min'] = passes_formation[[ 'playerKitNumber', 'playerKitNumberReceipt' ]].min(axis='columns') passes_between = passes_formation.groupby(['kitNo_max', 'kitNo_min' ]).id.count().reset_index() passes_between.rename({'id': 'pass_count'}, axis='columns', inplace=True) # add on the location of each player so we have the start and end positions of the lines passes_between = passes_between.merge(passer_avg, left_on='kitNo_min', right_index=True) passes_between = passes_between.merge(passer_avg, left_on='kitNo_max', right_index=True, suffixes=['', '_end']) ''' #Between Passer and Recipient passes_between = passes_df.groupby(['passer', 'recipient']).id.count().reset_index() passes_between.rename({'id': 'pass_count'}, axis='columns', inplace=True) passes_between = passes_between.merge(passer_avg, left_on='passer', right_index=True) passes_between = passes_between.merge(passer_avg, left_on='recipient', right_index=True, suffixes=['', '_end']) ''' #Minimum No. of Passes passes_between = passes_between.loc[(passes_between['pass_count'] >= 3)] #Scaling for StatsBomb passes_between['x'] = passes_between['x'] * 1.2 passes_between['y'] = passes_between['y'] * 0.8 passer_avg['x'] = passer_avg['x'] * 1.2 passer_avg['y'] = passer_avg['y'] * 0.8 passes_between['x_end'] = passes_between['x_end'] * 1.2 passes_between['y_end'] = passes_between['y_end'] * 0.8 #Width Variable yo = passes_between.pass_count / passes_between.pass_count.max() b = 1 min_transparency = 0.3 color = np.array(to_rgba('#00bfff')) color = np.tile(color, (len(passes_between), 1)) c_transparency = passes_between.pass_count / passes_between.pass_count.max( ) c_transparency = (c_transparency * (1 - min_transparency)) + min_transparency color[:, 3] = c_transparency a = plt.scatter(passer_avg.y, passer_avg.x, s=100, c="#111111", facecolor='none', lw=1, cmap="winter", alpha=1, zorder=2, vmin=0, vmax=0.6, marker='h') c = plt.scatter(passer_avg.y, passer_avg.x, s=60, c='#FF0000', alpha=1, zorder=3, marker='h') pitch.arrows(passes_between.x, passes_between.y, passes_between.x_end, passes_between.y_end, color=color, ax=ax, zorder=1, width=1.5) cbar = plt.colorbar(a, orientation="horizontal", shrink=0.3, pad=0, ticks=[0, 0.2, 0.4, 0.6]) cbar.set_label('Expected Possession Value (EPV)', color='#a9a9a9', size=6) cbar.outline.set_edgecolor('#a9a9a9') cbar.ax.xaxis.set_tick_params(color='#a9a9a9') cbar.ax.xaxis.set_tick_params(labelcolor='#a9a9a9') cbar.ax.tick_params(labelsize=5) plt.gca().invert_xaxis() for index, row in passer_avg.iterrows(): pitch.annotate(row.name, xy=(row.x, row.y), c='#a9a9a9', va='center', ha='center', size=5, ax=ax) plt.text( 79, 2, "Positions = Median Location of Successful Passes\nArrows = Pass Direction\nTransparency = Frequency of Combination\nMinimum of 3 Passes ", color='#a9a9a9', fontsize=5, alpha=0.5, zorder=1) plt.text(80, 122, "Minutes 45-90", color='#a9a9a9', fontsize=5) plt.text(18, 122, "@nikhilrajesh231", color='#a9a9a9', fontsize=5) ax.set_title("Barcelona PV Pass Network\n5-2 vs Getafe (H)", fontsize=8, color="#a9a9a9", fontweight='bold', y=1.01) fig = plt.savefig('pn2.png', bbox_inches="tight", facecolor="#000000", dpi=600) return fig