コード例 #1
0
def turnovermap(Df,hometeam,homeid,awayteam,awayid):
    df = Df.copy()
    pitch = Pitch(pitch_type='statsbomb', figsize=(10,6), 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)&\
                            (type_displayName in ['Clearance','Tackle','Interception','Aerial','BlockedPass'])&\
                            (outcomeType_displayName=='Successful')")
    awaydef = df.query("(teamId==@awayid)&\
                            (type_displayName in ['Clearance','Tackle','Interception','Aerial','BlockedPass'])&\
                            (outcomeType_displayName=='Successful')")

    for i in homedef.index.tolist():
    	if(i<len(df)-1):
	        if((df.teamId[i+1]==homeid)&(df.type_displayName[i+1] in ['BallRecovery','Pass','TakeOn'])&
	            (df.outcomeType_displayName[i+1]=='Successful')):
	            pitch.scatter(homedef.x[i],80-homedef.y[i],marker='o',s=50,zorder=5,facecolors='#082630',
	                          edgecolors='#fee090',linewidth=3,ax=ax[0])
    for i in awaydef.index.tolist():
    	if(i<len(df)-1):
	        if((df.teamId[i+1]==homeid)&(df.type_displayName[i+1] in ['BallRecovery','Pass','TakeOn'])&
	            (df.outcomeType_displayName[i+1]=='Successful')):
	            pitch.scatter(awaydef.x[i],80-awaydef.y[i],marker='o',s=50,zorder=5,facecolors='#082630',
	                          edgecolors='#fee090',linewidth=3,ax=ax[1])
    ax[0].set_title(hometeam+'\n'+'Turnover creating'+'\n'+'Defensive activities',fontsize=30)        
    ax[1].set_title(awayteam+'\n'+'Turnover creating'+'\n'+'Defensive activities',fontsize=30)
    fig.text(0.0, 0.0, "Created by Soumyajit Bose / @Soumyaj15209314",fontstyle="italic",fontsize=15,color='#edece9')
    fig.text(0.0, 0.05, "Turnover creating defensive activities include tackles, interceptions, aerials, clearances,"
        +'\n'+" and blocked passes leading to winning possession",fontstyle="italic",fontsize=15,color='#edece9')
    # add_image(bu_alt, fig, left=0.9, bottom=0.01, width=0.07)
    return fig
コード例 #2
0
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
コード例 #3
0
def switches(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)&(type_displayName == 'Pass')&((endY-y)**2>=1600.0)")
    awaydef = df.query("(teamId==@awayid)&(type_displayName == 'Pass')&((endY-y)**2>=1600.0)")
    homemask = homedef.outcomeType_displayName == 'Successful'
    awaymask = awaydef.outcomeType_displayName == 'Successful'

    pitch.lines(homedef[homemask].x,80-homedef[homemask].y,homedef[homemask].endX,80-homedef[homemask].endY,
                zorder=5,color='#fee090',linewidth=2,comet=True,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.lines(awaydef[awaymask].x,80-awaydef[awaymask].y,awaydef[awaymask].endX,80-awaydef[awaymask].endY,
                zorder=5,color='#fee090',linewidth=2,comet=True,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'+'Switches',fontsize=30)        
    ax[1].set_title(awayteam+'\n'+'Switches',fontsize=30)
    fig.text(0.0, 0.0, "Created by Soumyajit Bose / @Soumyaj15209314",fontstyle="italic",fontsize=15,color='#edece9')
    fig.text(0.0, 0.05, "Red lines for unsuccessful switches, yellow for successful ones",
                                                        fontstyle="italic",fontsize=15,color='#edece9')
    # add_image(bu_alt, fig, left=0.9, bottom=0.01, width=0.07)
    return fig
コード例 #4
0
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
コード例 #5
0
def takeonmap(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)&(type_displayName == 'TakeOn')")
    awaydef = df.query("(teamId==@awayid)&(type_displayName == 'TakeOn')")
    homemask = homedef.outcomeType_displayName == 'Successful'
    awaymask = awaydef.outcomeType_displayName == 'Successful'

    pitch.scatter(homedef[homemask].x,80-homedef[homemask].y,marker='o',s=50,zorder=5,facecolors='#082630',
                          edgecolors='#fee090',linewidth=3,ax=ax[0])
    pitch.scatter(homedef[~homemask].x,80-homedef[~homemask].y,marker='o',s=50,zorder=5,facecolors='#082630',
                          edgecolors='tab:red',linewidth=3,ax=ax[0])
    
    pitch.scatter(awaydef[awaymask].x,80-awaydef[awaymask].y,marker='o',s=50,zorder=5,facecolors='#082630',
                          edgecolors='#fee090',linewidth=3,ax=ax[1])
    pitch.scatter(awaydef[~awaymask].x,80-awaydef[~awaymask].y,marker='o',s=50,zorder=5,facecolors='#082630',
                          edgecolors='tab:red',linewidth=3,ax=ax[1])

    ax[0].set_title(hometeam+'\n'+'TakeOns',fontsize=30)        
    ax[1].set_title(awayteam+'\n'+'TakeOns',fontsize=30)
    fig.text(0.0, 0.0, "Created by Soumyajit Bose / @Soumyaj15209314",fontstyle="italic",fontsize=15,color='#edece9')
    fig.text(0.0, 0.05, "Red markers for unsuccessful takeons, yellow for successful ones",
                                                        fontstyle="italic",fontsize=15,color='#edece9')
    # add_image(bu_alt, fig, left=0.9, bottom=0.01, width=0.07)
    return fig
コード例 #6
0
def ind_heatmap(Df, player):

    from matplotlib.colors import LinearSegmentedColormap
    import cmasher as cmr
    #from mplsoccer import VerticalPitch
    df = Df.copy()
    pitch = Pitch(pitch_type='uefa',
                  figsize=(10.5, 6.8),
                  line_zorder=2,
                  line_color='#636363',
                  orientation='horizontal',
                  constrained_layout=True,
                  tight_layout=False,
                  pitch_color='black')
    fig, ax = pitch.draw()
    df = df[df.name == player]
    touchdf = df[(df.isTouch == True) & (df.name == player)].reset_index()
    #pitch.kdeplot(touchdf.x, touchdf.y, ax=ax, cmap=cmap,
    #linewidths=0.3,fill=True,levels=1000)
    pitch.kdeplot(touchdf.x,
                  touchdf.y,
                  ax=ax,
                  cmap=cmr.voltage,
                  shade=True,
                  levels=1000)
    ax.set_title(player + ' Touch-based heatmap', fontsize=25, color='white')
    fig.text(0.2,
             0.0,
             "Created by Nikhil Rajesh / @nikhilrajesh231",
             fontstyle="italic",
             fontsize=15,
             color='black')
    fig.set_facecolor('black')
    ax.set_facecolor('black')
    return fig
コード例 #7
0
def init_pitch():
    pitch = Pitch(pitch_color=None, line_color='whitesmoke', stripe=False)
    fig, ax = pitch.draw()

    # SB coordinates start on the left side, so we should invert the axes
    ax.invert_yaxis()

    return fig, ax
コード例 #8
0
def alineacion_442(valor_total, edad):
    try:
        valor_jugador = valor_total / 11
        porteros = goalkeeper(1, valor_jugador, edad).reset_index()
        defensas = defenders(4, valor_jugador, edad).reset_index()
        medios = midfielders(4, valor_jugador, edad).reset_index()
        delanteros = forwards(2, valor_jugador, edad).reset_index()
        pitch = Pitch(pitch_color='grass', line_color='white', stripe=True)
        fig, ax = pitch.draw(figsize=(20, 20))
        annotation = ax.annotate(porteros['short_name'][0], (5, 40),
                                 fontsize=40,
                                 ha='center')
        annotation = ax.annotate(defensas['short_name'][0], (24, 30),
                                 fontsize=40,
                                 ha='center')
        annotation = ax.annotate(defensas['short_name'][1], (24, 52),
                                 fontsize=40,
                                 ha='center')
        annotation = ax.annotate(defensas['short_name'][2], (32, 12),
                                 fontsize=40,
                                 ha='center')
        annotation = ax.annotate(defensas['short_name'][3], (32, 68),
                                 fontsize=40,
                                 ha='center')
        annotation = ax.annotate(medios['short_name'][0], (60, 30),
                                 fontsize=40,
                                 ha='center')
        annotation = ax.annotate(medios['short_name'][1], (60, 52),
                                 fontsize=40,
                                 ha='center')
        annotation = ax.annotate(medios['short_name'][2], (60, 12),
                                 fontsize=40,
                                 ha='center')
        annotation = ax.annotate(medios['short_name'][3], (60, 68),
                                 fontsize=40,
                                 ha='center')
        annotation = ax.annotate(delanteros['short_name'][0], (89, 24),
                                 fontsize=40,
                                 ha='center')
        annotation = ax.annotate(delanteros['short_name'][1], (89, 60),
                                 fontsize=40,
                                 ha='center')
        plt.savefig('output/images/442.jpg')
        result = pd.concat([porteros, defensas, medios,
                            delanteros]).reset_index()
        result = result[[
            'short_name', 'nationality', 'position', 'age', 'wage_eur',
            'value_eur', 'value_pred'
        ]]
        return result
    except:
        plt.savefig('output/images/442.jpg')
        return "No se han encontrado jugadores con esos parametros"
コード例 #9
0
ファイル: dataFoot.py プロジェクト: CamilleGAR/TP-DataFoot
def show_buts(club_name):
    identifiant_club = df_2.loc[df_2['name'] == club_name, ['wyId']]
    identifiant_club = identifiant_club.iat[0,0]
    
    df_goals = df_4.loc[(df_4['teamId'] == identifiant_club) & (df_4['subEventName'] == 'Goal kick')]
    
    x, y = list(), list()
    for i in df_goals['positions']:
        x.append(i[1]['x'])
        y.append(i[1]['y'])
    
    pitch = Pitch(pitch_color='grass', line_color='white', stripe=True)
    fig, ax = pitch.draw()
    sc = pitch.scatter(y, x, s=100, ax=ax)
コード例 #10
0
def createShotmap(match_data, events_df, team, pitchcolor, shotcolor, goalcolor, titlecolor, legendcolor, marker_size):
    # getting team id and venue
    if match_data['home']['name'] == team:
        teamId = match_data['home']['teamId']
        venue = 'home'
    else:
        teamId = match_data['away']['teamId']
        venue = 'away'
        
    # getting opponent   
    if venue == 'home':
        opponent = match_data['away']['name']
    else:
        opponent = match_data['home']['name']
        
    total_shots = events_df.loc[[9 in row for row in list(events_df['satisfiedEventsTypes'])]]
    team_shots = total_shots.loc[total_shots['teamId'] == teamId].reset_index(drop=True)
    mask_goal = team_shots.isGoal == True

    # Setup the pitch
    pitch = Pitch(pitch_type='statsbomb', orientation='vertical', pitch_color=pitchcolor, line_color='#c7d5cc',
                  figsize=(16, 11), view='half', pad_top=2, tight_layout=True)
    fig, ax = pitch.draw()


    # Plot the goals
    pitch.scatter(team_shots[mask_goal].x/100*120, 80-team_shots[mask_goal].y/100*80, s=marker_size,
                  edgecolors='black', c=goalcolor, zorder=2,
                  label='goal', ax=ax)
    pitch.scatter(team_shots[~mask_goal].x/100*120, 80-team_shots[~mask_goal].y/100*80,
                  edgecolors='white', c=shotcolor, s=marker_size, zorder=2,
                  label='shot', ax=ax)
    # Set the title
    ax.set_title(f'{team} shotmap \n vs {opponent}', fontsize=30, color=titlecolor)

    # set legend
    leg = ax.legend(facecolor=pitchcolor, edgecolor='None', fontsize=20, loc='lower center', handlelength=4)
    leg_texts = leg.get_texts() # list of matplotlib Text instances.
    leg_texts[0].set_color(legendcolor)
    leg_texts[1].set_color(legendcolor)
    
    # Set the figure facecolor
    fig.set_facecolor(pitchcolor)
コード例 #11
0
def passtypes(Df,team,teamid):
    df = Df.copy()
    # matchdict = Dict
    pitch = Pitch(pitch_type='statsbomb', figsize=(11,6), line_zorder=2, layout=(2,3), view='half',
                  line_color='#c7d5cc', orientation='vertical',constrained_layout=True, tight_layout=False)
    fig, ax = pitch.draw()    
    
    passdf = df.query("(type_displayName == 'Pass')&(outcomeType_displayName=='Successful')\
                         &(teamId==@teamid)").reset_index()
    
    passdf['y'] = 80 - passdf['y']
    passdf['endY'] = 80 - passdf['endY']

    progtocentre = passdf.query("(x<80)&(endX>80)&(endY>18)&(endY<62)")[['x','y','endX','endY']]
    wingplay = passdf.query("(x<80)&(endX>80)&((endY<18)or(endY>62))")[['x','y','endX','endY']]
    allbox = passdf.query("(endX>102)&(endY>18)&(endY<62)")[['x','y','endX','endY']]
    wingtobox = passdf.query("(x>80)&((y<18)or(y>62))&(endX>102)&(endY>18)&(endY<62)")[['x','y','endX','endY']]
    halfspaceplay = passdf.query("(x>80)&(((y>18)&(y<30))or((y>50)&(y<62)))&(endX>x)")[['x','y','endX','endY']]
    zone14play = passdf.query("(x>80)&(x<102)&(y>30)&(y<50)&(endX>x)")[['x','y','endX','endY']]

    pitch.lines(progtocentre.x, progtocentre.y, progtocentre.endX, progtocentre.endY, transparent=True, lw=2, 
                comet=True, color='#a1d76a',ax=ax[0,0])
    ax[0,0].set_title('Middle 3rd'+'\n'+'to Centre of final 3rd',fontsize=15)
    pitch.lines(wingplay.x, wingplay.y, wingplay.endX, wingplay.endY, transparent=True, lw=2, 
                comet=True, color='#a1d76a',ax=ax[0,1])
    ax[0,1].set_title('Middle 3rd'+'\n'+'to wing of final 3rd',fontsize=15)
    pitch.lines(allbox.x, allbox.y, allbox.endX, allbox.endY, transparent=True, lw=2, comet=True,
                color='#a1d76a',ax=ax[0,2])
    ax[0,2].set_title('All passes to box',fontsize=15)
    pitch.lines(wingtobox.x, wingtobox.y, wingtobox.endX, wingtobox.endY, transparent=True, lw=2, comet=True,
                color='#a1d76a',ax=ax[1,0])
    ax[1,0].set_title('Wing to box',fontsize=15)
    pitch.lines(halfspaceplay.x, halfspaceplay.y, halfspaceplay.endX, halfspaceplay.endY, transparent=True, 
                lw=2, comet=True, color='#a1d76a',ax=ax[1,1])
    ax[1,1].set_title('Attacking Passes'+'\n'+'From halfspace',fontsize=15)
    pitch.lines(zone14play.x, zone14play.y, zone14play.endX, zone14play.endY, transparent=True, lw=2, comet=True, 
                color='#a1d76a',ax=ax[1,2])
    ax[1,2].set_title('Attacking Passes'+'\n'+'From Zone 14',fontsize=15)
    fig.suptitle(team+' Progressive/Attacking Passes',fontsize=20)
    fig.text(0.05, -0.05, "Created by Soumyajit Bose / @Soumyaj15209314",fontstyle="italic",fontsize=15,color='#edece9')
    # add_image(bu_alt, fig, left=0.9, bottom=0.9, width=0.07)
    return fig
コード例 #12
0
def defensesmap(Df,team,teamid):
    df = Df.copy()
    pitch = Pitch(pitch_type='statsbomb', figsize=(10,6), line_zorder=2, layout=(1,2),
                  line_color='k', orientation='horizontal',constrained_layout=True, tight_layout=False)
    fig, ax = pitch.draw()
    
    defensedf = df.query("(type_displayName in ['Aerial','Clearance','Interception','Tackle','BlockedPass','Challenge'])\
                         &(teamId==@teamid)").reset_index()
    defensedf['defensive'] = [1 for i in range(len(defensedf))]
    for i in range(len(defensedf)):
        if(defensedf.loc[i,['type_displayName']][0]=='Aerial'):
            quals = defensedf.quals[i]
            if(286 in quals):
                defensedf.loc[i,['defensive']] = 0
        if(defensedf.loc[i,['type_displayName']][0]=='Challenge'):
            quals = defensedf.quals[i]
            if(286 in quals):
                defensedf.loc[i,['defensive']] = 0
    defensedf = defensedf[defensedf.defensive==1]
    defensedf['y'] = 80 - defensedf['y']
    ppda = defensedf[defensedf.x>=48]
    ppda = ppda.query("type_displayName in ['Interception','Tackle','Challenge']")
    deepdf = defensedf[defensedf.x<48]
    bin_statistic = pitch.bin_statistic(ppda.x, ppda.y, statistic='count', bins=(25, 25))
    bin_statistic['statistic'] = gaussian_filter(bin_statistic['statistic'], 1)
    pcm = pitch.heatmap(bin_statistic, ax=ax[0], cmap='Reds', edgecolors=None)
    ax[0].set_title(team+'\n'+' Pressurizing'+'\n'+ 'Defensive activities',fontsize=30)
    bin_statistic = pitch.bin_statistic(deepdf.x, deepdf.y, statistic='count', bins=(25, 25))
    bin_statistic['statistic'] = gaussian_filter(bin_statistic['statistic'], 1)
    pcm = pitch.heatmap(bin_statistic, ax=ax[1], cmap='Reds', edgecolors=None)
    # cbar = fig.colorbar(pcm, ax=ax[1])
    ax[1].set_title(team+'\n'+' Goal Protecting'+'\n'+'Defensive activities',fontsize=30)
    fig.text(0.0, 0.0, "Created by Soumyajit Bose / @Soumyaj15209314",fontstyle="italic",fontsize=15,color='#edece9')
    fig.text(0.0, 0.15, "Pressurizing defensive activities include tackles, interceptions and challenges"+'\n'+
     "made high up in opposition territory",fontstyle="italic",fontsize=15,color='#edece9')
    fig.text(0.0, 0.05, "Goal protecting defensive activities include tackles, interceptions, defensive aerials, challenges,"
        +'\n'+"clearances and blocked passes deep in own territory",fontstyle="italic",fontsize=15,color='#edece9')
    # add_image(bu_alt, fig, left=0.9, bottom=0.01, width=0.07)
    return fig
コード例 #13
0
def touchmap(Df,team,teamid):
    df = Df.copy()
    pitch = Pitch(pitch_type='statsbomb', figsize=(12,7), line_zorder=2, layout=(4,4),
                  line_color='k', orientation='horizontal',constrained_layout=True, tight_layout=False)
    fig, ax = pitch.draw()
    
    touchdf = df[(df.isTouch==True)&(df.teamId==teamid)&(df.name!='')].reset_index()
    touchdf['y'] = 80 - touchdf['y']
    players = touchdf.name.unique().tolist()
    Nplayers = len(players)
    for i in range(Nplayers):
        pdf = touchdf[touchdf.name==players[i]]
        bin_statistic = pitch.bin_statistic(pdf.x, pdf.y, statistic='count', bins=(25, 25))
        bin_statistic['statistic'] = gaussian_filter(bin_statistic['statistic'], 1)
        pcm = pitch.heatmap(bin_statistic, ax=ax[i//4,i%4], cmap='Reds', edgecolors=None)
        ax[i//4,i%4].set_title(players[i],fontsize=15)
    for i in range(Nplayers,16):
        ax[i//4,i%4].remove()
    
    fig.text(0.0, 0.0, "Created by Soumyajit Bose / @Soumyaj15209314",fontstyle="italic",fontsize=15,color='#edece9')
    fig.text(0.3, 1.01, team+" Touch-based heatmaps",fontsize=25,color='#edece9')
    # add_image(bu_alt, fig, left=0.95, bottom=0.97, width=0.07)
    return fig
コード例 #14
0
def progpassplotter(Df,team,teamid):
	pitch = Pitch(pitch_type='statsbomb', figsize=(12,10), line_zorder=2, layout=(4,4), view='full',
                  line_color='#c7d5cc', orientation='horizontal',constrained_layout=True, tight_layout=False)
	fig, ax = pitch.draw()
	df = Df[(Df.teamId==teamid)&(Df.name!='')].reset_index()
	players = df.name.unique().tolist()
	Nplayers = len(players)
	for i in range(Nplayers):
		p = players[i]
		Passp = playerpasses(df,p)
		pitch.lines(Passp.x, Passp.y, Passp.endX, Passp.endY, transparent=True, lw=2, 
			comet=True, color='#a1d76a',ax=ax[i//4,i%4])
		ax[i//4,i%4].set_title(p,fontsize=15)

	for i in range(Nplayers,16):
		ax[i//4,i%4].remove()

	fig.text(0.05, -0.04, "Created by Soumyajit Bose / @Soumyaj15209314",fontstyle="italic",fontsize=15,color='#edece9')
	# add_image(bu_alt, fig, left=0.85, bottom=-0.07, width=0.05)
	fig_htext(s = "<Completed Progressive Passes> by all players of "+team,
	          x = 0.1, y = 1, highlight_colors = ['#a1d76a'],
	          highlight_weights=['bold'],
	          string_weight='bold',fontsize=20,color='#edece9')
	return fig
コード例 #15
0
ファイル: plot_pitches.py プロジェクト: oruburos/mplsoccer
Basics
======

First we import the Pitch class and set the matplotlib style sheet.
"""
import matplotlib.pyplot as plt
from mplsoccer.pitch import Pitch
plt.style.use('ggplot')

##############################################################################
# Draw a pitch on a new axis
# --------------------------
# Let's plot on a new axis first.

pitch = Pitch(figsize=(8, 4))  # specifying figure size is optional (width, height)
fig, ax = pitch.draw()

##############################################################################
# Draw on an existing axis
# ------------------------
# mplsoccer also plays nicely with other matplotlib figures. To draw a pitch on an
# existing matplotlib axis specify an ``ax`` in the ``draw`` method.

fig, ax = plt.subplots(nrows=1, ncols=2)
pitch = Pitch()
pitch.draw(ax=ax[1])

##############################################################################
# Supported data providers
# ------------------------
# mplsoccer supports 7 pitch types by specifying the ``pitch_type`` argument:
コード例 #16
0
def shotMapMatch(shots_home, shots_away, mask_goal_h, mask_goal_a, home_name, away_name, home_score, away_score):
    """
    Creates a combined shot map (similar to caley style) for a both teams on a full, horizontal pitch
        
    Parameters
    ----------
    shots_XXXX : A pandas dataframe
        - Subset of team dataframe for home and away
        - contains ['id', 'minute', 'X', 'Y', 'player', 'shotType', 'situation', 'result', 'xG', 'pos_x', 'pos_y']
        - pos_x and pos_y are scaled to the 120x80 statsbomb sized pitch
        
    mask_goal_X : Pandas index mask
        - Mask for all goals separated home and away
        - Lets us separate points where the shot is scored
        
    team_name : string
        - Name of home/away team
        
    score : int
        - Actual team score
        - used for display options
        
    Returns
    -------
    shotmap : figure
        - Pitch shot map for a both teams 
    
    """
    
    max_marker_size = 500
    
    home_xg = round(shots_home['xG'].sum(),1)
    away_xg = round(shots_away['xG'].sum(),1)

    fig, ax = plt.subplots(figsize=(10,6))
    fig.set_facecolor('#3d4849')
    ax.patch.set_facecolor('#3d4849')

    pitch = Pitch(pitch_type='statsbomb', orientation='horizontal',
                  pitch_color='#22312b', line_color='#c7d5cc', figsize=(10,6),
                  constrained_layout=False, tight_layout=True, view='full',
                  pad_top=2)

    # Home
    pitch.scatter(120-shots_home[~mask_goal_h].pos_x, 80-shots_home[~mask_goal_h].pos_y,
                  s=shots_home[~mask_goal_h].xG*max_marker_size, edgecolors='white', c='#1f77b4', 
                  marker='s', zorder=1, label=home_name, ax=ax, alpha=0.8)

    pitch.scatter(120-shots_home[mask_goal_h].pos_x, 80-shots_home[mask_goal_h].pos_y,
                  edgecolors='black', c='white', s=shots_home[mask_goal_h].xG*max_marker_size, 
                  zorder=2, marker='s', alpha=0.95, ax=ax)

    # Away
    pitch.scatter(shots_away[~mask_goal_a].pos_x, shots_away[~mask_goal_a].pos_y,
                  s=shots_away[~mask_goal_a].xG*max_marker_size, edgecolors='white', c='#ff7f0e', 
                  marker='s', zorder=1, label=away_name, ax=ax, alpha=0.8)

    pitch.scatter(shots_away[mask_goal_a].pos_x, shots_away[mask_goal_a].pos_y,
                  edgecolors='black', c='white', s=shots_away[mask_goal_a].xG*max_marker_size, 
                  zorder=2, marker='s', alpha=0.95, label='Goal', ax=ax)

    pitch.draw(ax=ax)

    # Flip so goal is on bottom
    plt.gca().invert_yaxis()

    # Set the title
    ax.set_title(f'{home_name} (H) vs {away_name} (A) Shot Map', fontsize=20, color='w')
    legend = plt.legend(loc='center', markerscale=1, framealpha=1.0, bbox_to_anchor=[0.5, 0.88])
    # make the markers the same size in the legend
    for handle in legend.legendHandles:
        handle.set_sizes([100])
    
    # these are matplotlib.patch.Patch properties
    props = dict(boxstyle='round', facecolor='white', alpha=1.0)
    textstr = f'Score: (H) {home_score} - {away_score} (A)\nxG: (H) {home_xg} - {away_xg} (A)'
    ax.text(0.5, 0.125, textstr, transform=ax.transAxes, fontsize=14,
        verticalalignment='top', bbox=props, horizontalalignment='center')

    plt.show()
コード例 #17
0
def shotMapTeam(shots, mask_goal, home_name, away_name, home=True):
    """
    Creates a team shot map (similar to caley style) for a single team on half pitch
        
    Parameters
    ----------
    shots : A pandas dataframe
        - Subset of team dataframe
        - contains ['id', 'minute', 'X', 'Y', 'player', 'shotType', 'situation', 'result', 'xG', 'pos_x', 'pos_y']
        - pos_x and pos_y are scaled to the 120x80 statsbomb sized pitch
        
    mask_goal : Pandas index mask
        - Mask for all goals
        - Lets us separate points where the shot is scored
        
    team_name : string
        - Name of home/away team
        
    home : boolean
        - Defaults to true
        - True if looking at home team's shots.
        - Responsible for changing draw color options and title text
        
    Returns
    -------
    shotmap : figure
        - Pitch shot map for a single team 
    
    """
    
    max_marker_size = 500
    
    ## Plotting options for single team or both teams
    orientation = 'vertical'
    view = 'half'
    
    if home:
        color = '#1f77b4'
        team_name = home_name
        opp_name = away_name
    else:
        color = '#ff7f0e'
        team_name = away_name
        opp_name = home_name
        
    
    fig, ax = plt.subplots(figsize=(10,6))
    fig.set_facecolor('#3d4849')
    ax.patch.set_facecolor('#3d4849')

    pitch = Pitch(pitch_type='statsbomb', orientation=orientation,
                  pitch_color='#22312b', line_color='#c7d5cc', figsize=(8,5.5),
                  constrained_layout=False, tight_layout=True, view=view,
                  pad_top=2)

    pitch.scatter(shots[~mask_goal].pos_x, shots[~mask_goal].pos_y,
                  s=shots[~mask_goal].xG*max_marker_size, edgecolors='white', c=color, 
                  marker='s', zorder=1, label='Shot', ax=ax, alpha=0.8)

    pitch.scatter(shots[mask_goal].pos_x, shots[mask_goal].pos_y,
                  edgecolors='black', c='white', s=shots[mask_goal].xG*max_marker_size, 
                  zorder=2, marker='s', alpha=0.95, label='Goal', ax=ax)

    pitch.draw(ax=ax)

    # Flip so goal is on bottom
    plt.gca().invert_yaxis()

    # Set the title
    ax.set_title(f'{team_name} Shots \n vs {opp_name}', fontsize=20, color='w')
コード例 #18
0
def getTeamSuccessfulBoxPasses(events_df, teamId, team, pitch_color, cmap):
    """
    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.
    
    pitch_color : color of the pitch.
    
    cmap : color design of the pass lines. 
           You can select more cmaps here: 
               https://matplotlib.org/3.1.0/tutorials/colors/colormaps.html

    Returns
    -------
    Pitch Plot.

    """
    
    # Get Total Passes
    passes_df = events_df.loc[[row['displayName'] == 'Pass' for row in list(events_df['type'])]].reset_index(drop=True)
    
    # Get Team Passes
    team_passes = passes_df.loc[passes_df['teamId'] == teamId]
        
    # Extracting Box Passes from Total Passes
    box_passes = team_passes.copy()
    for i,pas in box_passes.iterrows():
        X = pas["x"]/100*120
        Xend = pas["endX"]/100*120
        Y = pas["y"]/100*80
        Yend = pas["endY"]/100*80
        if Xend >= 102 and Yend >= 18 and Yend <= 62:
            if X >=102 and Y >= 18 and Y <= 62:
                box_passes = box_passes.drop([i])
            else:
                pass
        else:
            box_passes = box_passes.drop([i])
            
    successful_box_passes = box_passes.copy()
    unsuccessful_box_passes = box_passes.copy()
    for i,pas in box_passes.iterrows():
        if pas['outcomeType']['value'] == 0:
            successful_box_passes = successful_box_passes.drop([i])
        else:
            unsuccessful_box_passes = unsuccessful_box_passes.drop([i])
        
    
    pitch = Pitch(pitch_type='statsbomb', orientation='vertical', pitch_color=pitch_color, line_color='#c7d5cc',
                  figsize=(16, 11), view='half', pad_top=2, tight_layout=True)
    fig, ax = pitch.draw()
    
    # Plot the completed passes
    pitch.lines(successful_box_passes.x/100*120, 80-successful_box_passes.y/100*80,
                successful_box_passes.endX/100*120, 80-successful_box_passes.endY/100*80,
                lw=5, opp_transparent=True, opp_comet=True, cmap=cmap,
                label='Successful Passes', ax=ax)
    
    pitch.scatter(successful_box_passes.x/100*120, 80-successful_box_passes.y/100*80,
                  edgecolors='white', c='white', s=50, zorder=2,
                  ax=ax)
    
    # Set the title
    fig.suptitle(f'Completed Box Passes - {team}', fontsize=15)
    
    # Set the subtitle
    ax.set_title('Data : Whoscored', fontsize=8, loc='right', fontstyle='italic', fontweight='bold')
    
    # set legend
    #ax.legend(facecolor='#22312b', edgecolor='None', fontsize=8, loc='lower center', handlelength=4)
    
    # Set the figure facecolor
    fig.set_facecolor(pitch_color) 
コード例 #19
0
def createAttPassNetworks(match_data, matches_df, events_df, team, pitch_color, max_lw, 
                          marker_size, marker_color, marker_label='kit_no', marker_label_size=20):
    
    """
    

    Parameters
    ----------
    match_data : Data containing everything about the match
    
    matches_df : DataFrame containing match data.
    
    events_df : DataFrame containing event data for that match.
    
    team : Name of the required team.
    
    pitch_color : color of the pitch and figure.
    
    max_lw : maximum line width of network lines.
    
    marker_size : size of the circle markers.
    
    marker_color : color of the circle markers.

    
    Returns
    -------
    Pitch Plot.
    """
        
        
    # getting match_id
    matchId = match_data['matchId']
    
    
    # getting team id and venue
    if match_data['home']['name'] == team:
        teamId = match_data['home']['teamId']
        venue = 'home'
    else:
        teamId = match_data['away']['teamId']
        venue = 'away'
    
    
    # getting opponent   
    if venue == 'home':
        opponent = match_data['away']['name']
    else:
        opponent = match_data['home']['name']
    
    
    # getting player dictionary
    team_players_dict = {}
    for player in match_data[venue]['players']:
        team_players_dict[player['playerId']] = player['name']
        
        
    # getting player dictionary with kit no
    team_playerskitno_dict = {}
    for player in matches_df[venue][matchId]['players']:
        team_playerskitno_dict[player['shirtNo']] = player['name']
    
    
    # getting minute of first substitution
    for i,row in events_df.iterrows():
        if row['type']['displayName'] == 'SubstitutionOn' and row['teamId'] == teamId:
            sub_minute = str(row['minute'])
            break
    
    
    # getting players dataframe
    match_players_df = pd.DataFrame()
    player_names = []
    player_ids = []
    player_pos = []
    player_kit_number = []


    for player in match_data[venue]['players']:
        player_names.append(player['name'])
        player_ids.append(player['playerId'])
        player_pos.append(player['position'])
        player_kit_number.append(player['shirtNo'])

    match_players_df['playerId'] = player_ids
    match_players_df['playerName'] = player_names
    match_players_df['playerPos'] = player_pos
    match_players_df['playerKitNumber'] = player_kit_number
    
    
    # extracting passes
    passes_df = events_df.loc[events_df['teamId'] == teamId].reset_index().drop('index', axis=1)
    passes_df.dropna(subset=["playerId"], inplace=True)
    passes_df.insert(27, column='playerName', value=[team_players_dict[i] for i in list(passes_df['playerId'])])
    passes_df.insert(28, column='passRecipientId', value=passes_df['playerId'].shift(-1))  
    passes_df.insert(29, column='passRecipientName', value=passes_df['playerName'].shift(-1))  
    passes_df.dropna(subset=["passRecipientName"], inplace=True)
    passes_df = passes_df.loc[[row['displayName'] == 'Pass' for row in list(passes_df['type'])]].reset_index(drop=True)
    passes_df = passes_df.loc[[row['displayName'] == 'Successful' for row in list(passes_df['outcomeType'])]].reset_index(drop=True)
    index_names = passes_df.loc[passes_df['playerName']==passes_df['passRecipientName']].index
    passes_df.drop(index_names, inplace=True)
    passes_df = passes_df.merge(match_players_df, on=['playerId', 'playerName'], how='left', validate='m:1')
    passes_df = passes_df.merge(match_players_df.rename({'playerId': 'passRecipientId', 'playerName':'passRecipientName'},
                                                        axis='columns'), on=['passRecipientId', 'passRecipientName'],
                                                        how='left', validate='m:1', suffixes=['', 'Receipt'])
    passes_df = passes_df[passes_df['playerPos'] != 'Sub']
    
    
    # getting team formation
    formation = match_data[venue]['formations'][0]['formationName']
    formation = '-'.join(formation)
    
    
    # getting player average locations
    location_formation = passes_df[['playerKitNumber', 'x', 'y']]
    average_locs_and_count = location_formation.groupby('playerKitNumber').agg({'x': ['mean'], 'y': ['mean', 'count']})
    average_locs_and_count.columns = ['x', 'y', 'count']
    
    
    # filtering progressive passes 
    passes_df = passes_df.loc[passes_df['EPV_difference'] > 0]

    
    # getting separate dataframe for selected columns 
    passes_formation = passes_df[['id', 'playerKitNumber', 'playerKitNumberReceipt']].copy()
    passes_formation['EPV'] = passes_df['EPV_difference']


    # getting dataframe for passes between players
    passes_between = passes_formation.groupby(['playerKitNumber', 'playerKitNumberReceipt']).agg({ 'id' : 'count', 'EPV' : 'sum'}).reset_index()
    passes_between.rename({'id': 'pass_count'}, axis='columns', inplace=True)
    passes_between = passes_between.merge(average_locs_and_count, left_on='playerKitNumberReceipt', right_index=True)
    passes_between = passes_between.merge(average_locs_and_count, left_on='playerKitNumber', right_index=True,
                                          suffixes=['', '_end'])
    
    
    # filtering passes
    pass_filter = int(passes_between['pass_count'].mean())
    passes_between = passes_between.loc[passes_between['pass_count'] > pass_filter*2]

    
    # calculating the line width 
    max_line_width = max_lw
    passes_between['width'] = passes_between.pass_count / passes_between.pass_count.max() * max_line_width
    passes_between = passes_between.reset_index(drop=True)
    
    
    # setting color to make the lines more transparent when fewer passes are made
    min_transparency = 0.3
    color = np.array(to_rgba('white'))
    color = np.tile(color, (len(passes_between), 1))
    c_transparency = passes_between.EPV / passes_between.EPV.max()
    c_transparency = (c_transparency * (1 - min_transparency)) + min_transparency
    color[:, 3] = c_transparency
    passes_between['alpha'] = color.tolist()
    
    
    # Plotting name on markers
    if marker_label == 'name':
        average_locs_and_count.index = average_locs_and_count.index.map(team_playerskitno_dict)
    
    
    # plotting
    pitch = Pitch(pitch_type='statsbomb', orientation='horizontal',
                  pitch_color=pitch_color, line_color='#c7d5cc', figsize=(16, 11),
                  constrained_layout=True, tight_layout=False)
    fig, ax = pitch.draw()
    
    average_locs_and_count['zorder'] = list(np.linspace(2,6,11, dtype='int'))
    pitch.lines(passes_between.x/100*120, 80-passes_between.y/100*80,
                passes_between.x_end/100*120, 80-passes_between.y_end/100*80, lw=passes_between.width,
                color=color, zorder=1, ax=ax)
    for index, row in average_locs_and_count.iterrows():
        pitch.scatter(row.x/100*120, 80-row.y/100*80, s=marker_size,
                      color=marker_color, edgecolors='black', linewidth=1, 
                      alpha=1, zorder=row.zorder, ax=ax)
    
    
    for index, row in average_locs_and_count.iterrows():
        pitch.annotate(row.name, xy=(row.x/100*120, 80-row.y/100*80), family='DejaVu Sans', c='white', 
                       va='center', ha='center', zorder=row.zorder, size=marker_label_size, weight='bold', ax=ax)
    ax.set_title("{} Progressive Pass Network vs {}".format(team, opponent), size=15, y=0.97, color='#c7d5cc')
    fig.set_facecolor(pitch_color)
コード例 #20
0
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)
コード例 #21
0
def createPassNetworks(match_data, matches_df, events_df, team,
                       pitch_color, max_lw, marker_size, marker_color, marker_label='kit_no', marker_label_size=20):
    """
    

    Parameters
    ----------
    match_data : Data containing everything about the match
    
    matches_df : DataFrame containing match data.
    
    events_df : DataFrame containing event data for that match.
    
    team : Name of the required team.
    
    pitch_color : color of the pitch and figure.
    
    max_lw : maximum line width of network lines.
    
    marker_size : size of the circle markers.
    
    marker_color : color of the circle markers.
    
    
    Returns
    -------
    Pitch Plot.
    """
    
    matchId = match_data['matchId']

    
    # getting team id and venue
    if match_data['home']['name'] == team:
        teamId = match_data['home']['teamId']
        venue = 'home'
    else:
        teamId = match_data['away']['teamId']
        venue = 'away'
        
    # getting opponent   
    if venue == 'home':
        opponent = match_data['away']['name']
    else:
        opponent = match_data['home']['name']
    
    team_players_dict = {}
    for player in matches_df[venue][matchId]['players']:
        team_players_dict[player['playerId']] = player['name']
    
    team_playerskitno_dict = {}
    for player in matches_df[venue][matchId]['players']:
        team_playerskitno_dict[player['shirtNo']] = player['name']
    
    passes_df = events_df.loc[[row['displayName'] == 'Pass' for row in list(events_df['type'])]].reset_index(drop=True)
    passes_df = passes_df.loc[passes_df['teamId'] == teamId].reset_index().drop('index', axis=1)
    passes_df = passes_df.loc[[row['displayName'] == 'Successful' for row in list(passes_df['outcomeType'])]].reset_index(drop=True)
    
    
            
    passes_df.insert(27, column='playerName', value=[team_players_dict[i] for i in list(passes_df['playerId'])])
    passes_df.insert(28, column='passRecipientId', value=passes_df['playerId'].shift(-1))  
    passes_df.insert(29, column='passRecipientName', value=passes_df['playerName'].shift(-1))  
    passes_df.dropna(subset=["passRecipientName"], inplace=True)
    
    match_players_df = pd.DataFrame()
    player_names = []
    player_ids = []
    player_pos = []
    player_kit_number = []
    
    
    for player in matches_df[venue][matchId]['players']:
                player_names.append(player['name'])
                player_ids.append(player['playerId'])
                player_pos.append(player['position'])
                player_kit_number.append(player['shirtNo'])
                
    match_players_df['playerId'] = player_ids
    match_players_df['playerName'] = player_names
    match_players_df['playerPos'] = player_pos
    match_players_df['playerKitNumber'] = player_kit_number

    passes_df = passes_df.merge(match_players_df, on=['playerId', 'playerName'], how='left', validate='m:1')
    passes_df = passes_df.merge(match_players_df.rename({'playerId': 'passRecipientId', 'playerName':'passRecipientName'},
                                                        axis='columns'), on=['passRecipientId', 'passRecipientName'],
                                                        how='left', validate='m:1', suffixes=['', 'Receipt'])
    passes_df = passes_df[passes_df['playerPos'] != 'Sub']
    passes_formation = passes_df[['id', 'playerKitNumber', 'playerKitNumberReceipt']].copy()
    location_formation = passes_df[['playerKitNumber', 'x', 'y']]
    
    average_locs_and_count = location_formation.groupby('playerKitNumber').agg({'x': ['mean'], 'y': ['mean', 'count']})
    average_locs_and_count.columns = ['x', 'y', 'count']
    
    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(average_locs_and_count, left_on='kitNo_min', right_index=True)
    passes_between = passes_between.merge(average_locs_and_count, left_on='kitNo_max', right_index=True,
                                          suffixes=['', '_end'])
    
    ##############################################################################
    # Calculate the line width and marker sizes relative to the largest counts
    
    max_line_width = max_lw
    passes_between['width'] = passes_between.pass_count / passes_between.pass_count.max() * max_line_width
    #average_locs_and_count['marker_size'] = (average_locs_and_count['count']
    #                                         / average_locs_and_count['count'].max() * max_marker_size)
    
    ##############################################################################
    # Set color to make the lines more transparent when fewer passes are made
    
    min_transparency = 0.3
    color = np.array(to_rgba('white'))
    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
    
    
    # Plotting name on markers
    if marker_label == 'name':
        average_locs_and_count.index = average_locs_and_count.index.map(team_playerskitno_dict)

    
    ##############################################################################
    # Plotting
    
    
    pitch = Pitch(pitch_type='statsbomb', orientation='horizontal',
                  pitch_color=pitch_color, line_color='#c7d5cc', figsize=(16, 11),
                  constrained_layout=True, tight_layout=False)
    fig, ax = pitch.draw()
    pitch.lines(passes_between.x/100*120, 80-passes_between.y/100*80,
                passes_between.x_end/100*120, 80-passes_between.y_end/100*80, lw=passes_between.width,
                color=color, zorder=1, ax=ax)
    pitch.scatter(average_locs_and_count.x/100*120, 80-average_locs_and_count.y/100*80, s=marker_size,
                  color=marker_color, edgecolors='black', linewidth=1, alpha=1, ax=ax)
    for index, row in average_locs_and_count.iterrows():
        pitch.annotate(row.name, xy=(row.x/100*120, 80-row.y/100*80), c='white', va='center', ha='center', size=marker_label_size, weight='bold', ax=ax)
    ax.set_title("{} Pass Network vs {}".format(team, opponent), size=15, y=0.97, color='#c7d5cc')
    fig.set_facecolor(pitch_color)
コード例 #22
0
def createPVFormationMap(match_data, events_df, team, color_palette,
                         markerstyle, markersize, markeredgewidth, labelsize,
                         labelcolor, ax):

    # getting team id and venue
    if match_data['home']['name'] == team:
        teamId = match_data['home']['teamId']
        venue = 'home'
    else:
        teamId = match_data['away']['teamId']
        venue = 'away'

    # getting opponent
    if venue == 'home':
        opponent = match_data['away']['name']
    else:
        opponent = match_data['home']['name']

    # getting player dictionary
    team_players_dict = {}
    for player in match_data[venue]['players']:
        team_players_dict[player['playerId']] = player['name']

    # getting minute of first substitution
    for i, row in events_df.iterrows():
        if row['type'] == 'SubstitutionOn' and row['teamId'] == teamId:
            sub_minute = str(row['minute'])
            break

    # getting players dataframe
    match_players_df = pd.DataFrame()
    player_names = []
    player_ids = []
    player_pos = []
    player_kit_number = []

    for player in match_data[venue]['players']:
        player_names.append(player['name'])
        player_ids.append(player['playerId'])
        player_pos.append(player['position'])
        player_kit_number.append(player['shirtNo'])

    match_players_df['playerId'] = player_ids
    match_players_df['playerName'] = player_names
    match_players_df['playerPos'] = player_pos
    match_players_df['playerKitNumber'] = player_kit_number

    # extracting passes
    passes_df = events_df.loc[events_df['teamId'] ==
                              teamId].reset_index().drop('index', axis=1)
    passes_df['playerId'] = passes_df['playerId'].astype('float').astype(
        'Int64')
    if 'playerName' in passes_df.columns:
        passes_df = passes_df.drop(columns='playerName')
    passes_df.dropna(subset=["playerId"], inplace=True)
    passes_df.insert(
        27,
        column='playerName',
        value=[team_players_dict[i] for i in list(passes_df['playerId'])])
    if 'passRecipientId' in passes_df.columns:
        passes_df = passes_df.drop(columns='passRecipientId')
        passes_df = passes_df.drop(columns='passRecipientName')
    passes_df.insert(28,
                     column='passRecipientId',
                     value=passes_df['playerId'].shift(-1))
    passes_df.insert(29,
                     column='passRecipientName',
                     value=passes_df['playerName'].shift(-1))
    passes_df.dropna(subset=["passRecipientName"], inplace=True)
    passes_df = passes_df.loc[events_df['type'] == 'Pass', :].reset_index(
        drop=True)
    passes_df = passes_df.loc[events_df['outcomeType'] ==
                              'Successful', :].reset_index(drop=True)
    index_names = passes_df.loc[passes_df['playerName'] ==
                                passes_df['passRecipientName']].index
    passes_df.drop(index_names, inplace=True)
    passes_df = passes_df.merge(match_players_df,
                                on=['playerId', 'playerName'],
                                how='left',
                                validate='m:1')
    passes_df = passes_df.merge(match_players_df.rename(
        {
            'playerId': 'passRecipientId',
            'playerName': 'passRecipientName'
        },
        axis='columns'),
                                on=['passRecipientId', 'passRecipientName'],
                                how='left',
                                validate='m:1',
                                suffixes=['', 'Receipt'])
    # passes_df = passes_df[passes_df['playerPos'] != 'Sub']

    # Getting net possesion value for passes
    netPVPassed = passes_df.groupby(['playerId',
                                     'playerName'])['EPV'].sum().reset_index()
    netPVReceived = passes_df.groupby(['passRecipientId', 'passRecipientName'
                                       ])['EPV'].sum().reset_index()

    # Getting formation and player ids for first 11
    formation = match_data[venue]['formations'][0]['formationName']
    formation_positions = match_data[venue]['formations'][0][
        'formationPositions']
    playerIds = match_data[venue]['formations'][0]['playerIds'][:11]

    # Getting all data in a dataframe
    formation_data = []
    for playerId, pos in zip(playerIds, formation_positions):
        pl_dict = {'playerId': playerId}
        pl_dict.update(pos)
        formation_data.append(pl_dict)
    formation_data = pd.DataFrame(formation_data)
    formation_data['vertical'] = normalize(
        formation_data['vertical'], {
            'actual': {
                'lower': 0,
                'upper': 10
            },
            'desired': {
                'lower': 10,
                'upper': 110
            }
        })
    formation_data['horizontal'] = normalize(formation_data['horizontal'], {
        'actual': {
            'lower': 0,
            'upper': 10
        },
        'desired': {
            'lower': 80,
            'upper': 0
        }
    })
    formation_data = netPVPassed.join(formation_data.set_index('playerId'),
                                      on='playerId',
                                      how='inner').reset_index(drop=True)
    formation_data = formation_data.rename(columns={"EPV": "PV"})

    # Plotting
    pitch = Pitch(pitch_type='statsbomb',
                  pitch_color='#171717',
                  line_color='#5c5c5c',
                  goal_type='box')
    pitch.draw(ax=ax, constrained_layout=True, tight_layout=True)

    sns.scatterplot(x='vertical',
                    y='horizontal',
                    data=formation_data,
                    hue='PV',
                    s=markersize,
                    marker=markerstyle,
                    legend=False,
                    palette=color_palette,
                    linewidth=markeredgewidth,
                    ax=ax)

    ax.text(2, 78, '{}'.format('-'.join(formation)), size=20, c='grey')

    for index, row in formation_data.iterrows():
        pitch.annotate(str(round(row.PV * 100, 2)) + '%',
                       xy=(row.vertical, row.horizontal),
                       c=labelcolor,
                       va='center',
                       ha='center',
                       size=labelsize,
                       zorder=2,
                       weight='bold',
                       ax=ax)
        pitch.annotate(row.playerName,
                       xy=(row.vertical, row.horizontal + 5),
                       c=labelcolor,
                       va='center',
                       ha='center',
                       size=labelsize,
                       zorder=2,
                       weight='bold',
                       ax=ax)
コード例 #23
0
axes = axes.ravel()
pitch_kwargs = {'line_color': '#94A7AE', 'axis': True, 'label': True, 'pad_left': 0,
                'pad_right': 0, 'pad_top': 0, 'pad_bottom': 0, 'linewidth': 1} 
pitch_types = ['statsbomb', 'statsperform', 'tracab', 'wyscout', 'metricasports', 'opta', 'stats']
fontcolor = '#b6b9ea'
arrowprops = {'arrowstyle': '->', 'lw': 4,
              'connectionstyle': 'angle3,angleA=0,angleB=-90', 'color': fontcolor}
font_kwargs = {'fontsize': 14, 'ha': 'center', 'va': 'bottom', 'fontweight': 'bold',
               'fontstyle': 'italic', 'c': fontcolor}

for idx, pt in enumerate(pitch_types):
    if pt in ['tracab', 'metricasports']:
        pitch = Pitch(pitch_type=pt, pitch_length=105, pitch_width=68, **pitch_kwargs)     
    else:
        pitch = Pitch(pitch_type=pt, **pitch_kwargs)
    pitch.draw(axes[idx])
    xmin, xmax, ymin, ymax = pitch.extent
    if pitch.aspect != 1:
        text = 'data coordinates \n are square (1:1) \n scale up to a real-pitch size'
        axes[idx].annotate(text, xy=(xmin, ymin), xytext=(0 + (xmax - xmin)/2, ymin),
                           **font_kwargs)
    axes[idx].xaxis.set_ticks([xmin, xmax])
    axes[idx].yaxis.set_ticks([ymin, ymax])
    axes[idx].tick_params(labelsize=15)
    axes[idx].set_title(pt, fontsize=30, c='#9749b9', pad=15)
    if pitch.invert_y: 
        text = 'inverted y axis'
        if pt == 'stats':
            xytext = (0 + (xmax - xmin)/2, 50)
        else:
            xytext = (0 + (xmax - xmin)/2, ymin + (ymax - ymin)/2)            
コード例 #24
0
def createPassNetworks(match_data,
                       events_df,
                       matchId,
                       team,
                       max_line_width,
                       marker_size,
                       edgewidth,
                       dh_arrow_width,
                       marker_color,
                       marker_edge_color,
                       shrink,
                       ax,
                       kit_no_size=20):

    # getting team id and venue
    if match_data['home']['name'] == team:
        teamId = match_data['home']['teamId']
        venue = 'home'
    else:
        teamId = match_data['away']['teamId']
        venue = 'away'

    # getting opponent
    if venue == 'home':
        opponent = match_data['away']['name']
    else:
        opponent = match_data['home']['name']

    # getting player dictionary
    team_players_dict = {}
    for player in match_data[venue]['players']:
        team_players_dict[player['playerId']] = player['name']

    # getting minute of first substitution
    for i in events_df.index:
        if events_df.loc[i, 'type'] == 'SubstitutionOn' and events_df.loc[
                i, 'teamId'] == teamId:
            sub_minute = str(events_df.loc[i, 'minute'])
            break

    # getting players dataframe
    match_players_df = pd.DataFrame()
    player_names = []
    player_ids = []
    player_pos = []
    player_kit_number = []

    for player in match_data[venue]['players']:
        player_names.append(player['name'])
        player_ids.append(player['playerId'])
        player_pos.append(player['position'])
        player_kit_number.append(player['shirtNo'])

    match_players_df['playerId'] = player_ids
    match_players_df['playerName'] = player_names
    match_players_df['playerPos'] = player_pos
    match_players_df['playerKitNumber'] = player_kit_number

    # extracting passes
    passes_df = events_df.loc[events_df['teamId'] ==
                              teamId].reset_index().drop('index', axis=1)
    passes_df['playerId'] = passes_df['playerId'].astype('float').astype(
        'Int64')
    if 'playerName' in passes_df.columns:
        passes_df = passes_df.drop(columns='playerName')
    passes_df.dropna(subset=["playerId"], inplace=True)
    passes_df.insert(
        27,
        column='playerName',
        value=[team_players_dict[i] for i in list(passes_df['playerId'])])
    if 'passRecipientId' in passes_df.columns:
        passes_df = passes_df.drop(columns='passRecipientId')
        passes_df = passes_df.drop(columns='passRecipientName')
    passes_df.insert(28,
                     column='passRecipientId',
                     value=passes_df['playerId'].shift(-1))
    passes_df.insert(29,
                     column='passRecipientName',
                     value=passes_df['playerName'].shift(-1))
    passes_df.dropna(subset=["passRecipientName"], inplace=True)
    passes_df = passes_df.loc[events_df['type'] == 'Pass', :].reset_index(
        drop=True)
    passes_df = passes_df.loc[events_df['outcomeType'] ==
                              'Successful', :].reset_index(drop=True)
    index_names = passes_df.loc[passes_df['playerName'] ==
                                passes_df['passRecipientName']].index
    passes_df.drop(index_names, inplace=True)
    passes_df = passes_df.merge(match_players_df,
                                on=['playerId', 'playerName'],
                                how='left',
                                validate='m:1')
    passes_df = passes_df.merge(match_players_df.rename(
        {
            'playerId': 'passRecipientId',
            'playerName': 'passRecipientName'
        },
        axis='columns'),
                                on=['passRecipientId', 'passRecipientName'],
                                how='left',
                                validate='m:1',
                                suffixes=['', 'Receipt'])
    passes_df = passes_df[passes_df['playerPos'] != 'Sub']

    # getting team formation
    formation = match_data[venue]['formations'][0]['formationName']
    formation = '-'.join(formation)

    # getting player average locations
    location_formation = passes_df[['playerKitNumber', 'x', 'y']]
    average_locs_and_count = location_formation.groupby('playerKitNumber').agg(
        {
            'x': ['mean'],
            'y': ['mean', 'count']
        })
    average_locs_and_count.columns = ['x', 'y', 'count']

    # getting separate dataframe for selected columns
    passes_formation = passes_df[[
        'id', 'playerKitNumber', 'playerKitNumberReceipt'
    ]].copy()
    passes_formation['EPV'] = passes_df['EPV']

    # getting dataframe for passes between players
    passes_between = passes_formation.groupby(
        ['playerKitNumber', 'playerKitNumberReceipt']).agg({
            'id': 'count',
            'EPV': 'sum'
        }).reset_index()
    passes_between.rename({'id': 'pass_count'}, axis='columns', inplace=True)
    passes_between = passes_between.merge(average_locs_and_count,
                                          left_on='playerKitNumberReceipt',
                                          right_index=True)
    passes_between = passes_between.merge(average_locs_and_count,
                                          left_on='playerKitNumber',
                                          right_index=True,
                                          suffixes=['', '_end'])

    # filtering passes
    pass_filter = int(passes_between['pass_count'].mean())
    passes_between = passes_between.loc[
        passes_between['pass_count'] > pass_filter]

    # calculating the line width
    passes_between[
        'width'] = passes_between.pass_count / passes_between.pass_count.max(
        ) * max_line_width
    passes_between = passes_between.reset_index(drop=True)

    # setting color to make the lines more transparent when fewer passes are made
    min_transparency = 0.3
    color = np.array(to_rgba('white'))
    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
    passes_between['alpha'] = color.tolist()

    # separating paired passes from normal passes
    passes_between_threshold = 15
    filtered_pair_df = []
    pair_list = [
        comb
        for comb in combinations(passes_between['playerKitNumber'].unique(), 2)
    ]
    for pair in pair_list:
        df = passes_between[(
            (passes_between['playerKitNumber'] == pair[0]) &
            (passes_between['playerKitNumberReceipt'] == pair[1])) | (
                (passes_between['playerKitNumber'] == pair[1]) &
                (passes_between['playerKitNumberReceipt'] == pair[0]))]
        if df.shape[0] == 2:
            if (np.array(df.pass_count)[0] >= passes_between_threshold) and (
                    np.array(df.pass_count)[1] >= passes_between_threshold):
                filtered_pair_df.append(df)
                passes_between.drop(df.index, inplace=True)
    if len(filtered_pair_df) > 0:
        filtered_pair_df = pd.concat(filtered_pair_df).reset_index(drop=True)
        passes_between = passes_between.reset_index(drop=True)

    # plotting
    pitch = Pitch(pitch_type='opta',
                  pitch_color='#171717',
                  line_color='#5c5c5c',
                  goal_type='box')
    pitch.draw(ax=ax, constrained_layout=True, tight_layout=True)
    average_locs_and_count['zorder'] = list(np.linspace(1, 5, 11))
    for i in average_locs_and_count.index:
        pitch.scatter(average_locs_and_count.loc[i, 'x'],
                      average_locs_and_count.loc[i, 'y'],
                      s=marker_size,
                      color=marker_color,
                      edgecolors=marker_edge_color,
                      linewidth=edgewidth,
                      alpha=1,
                      zorder=average_locs_and_count.loc[i, 'zorder'],
                      ax=ax)

    for i in passes_between.index:
        x = passes_between.loc[i, 'x']
        y = passes_between.loc[i, 'y']
        endX = passes_between.loc[i, 'x_end']
        endY = passes_between.loc[i, 'y_end']
        coordsA = "data"
        coordsB = "data"
        con = ConnectionPatch([endX, endY], [x, y],
                              coordsA,
                              coordsB,
                              arrowstyle="simple",
                              shrinkA=shrink,
                              shrinkB=shrink,
                              mutation_scale=passes_between.loc[i, 'width'] *
                              max_line_width,
                              color=passes_between.loc[i, 'alpha'])
        ax.add_artist(con)

    if len(filtered_pair_df) > 0:
        for i in filtered_pair_df.index:
            x = filtered_pair_df.loc[i, 'x']
            y = filtered_pair_df.loc[i, 'y']
            endX = filtered_pair_df.loc[i, 'x_end']
            endY = filtered_pair_df.loc[i, 'y_end']
            coordsA = "data"
            coordsB = "data"
            con = ConnectionPatch([endX, endY], [x, y],
                                  coordsA,
                                  coordsB,
                                  arrowstyle="<|-|>",
                                  shrinkA=shrink,
                                  shrinkB=shrink,
                                  mutation_scale=dh_arrow_width,
                                  lw=filtered_pair_df.loc[i, 'width'] *
                                  max_line_width / 5,
                                  color=filtered_pair_df.loc[i, 'alpha'])
            ax.add_artist(con)

    for i in average_locs_and_count.index:
        pitch.annotate(i,
                       xy=(average_locs_and_count.loc[i, 'x'],
                           average_locs_and_count.loc[i, 'y']),
                       family='DejaVu Sans',
                       c='white',
                       va='center',
                       ha='center',
                       zorder=average_locs_and_count.loc[i, 'zorder'],
                       size=kit_no_size,
                       weight='bold',
                       ax=ax)
    ax.text(50,
            104,
            "{} (Mins 1-{})".format(team, sub_minute).upper(),
            size=10,
            fontweight='bold',
            ha='center',
            va='center')
    ax.text(2, 3, '{}'.format(formation), size=9, c='grey')
コード例 #25
0
passes_between['width'] = passes_between.pass_count / passes_between.pass_count.max() * max_line_width
average_locs_and_count['marker_size'] = (average_locs_and_count['count']
                                         / average_locs_and_count['count'].max() * max_marker_size)

##############################################################################
# Set color to make the lines more transparent when fewer passes are made

min_transparency = 0.3
color = np.array(to_rgba('white'))
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

##############################################################################
# Plotting

pitch = Pitch(pitch_type='statsbomb', orientation='horizontal',
              pitch_color='#22312b', line_color='#c7d5cc', figsize=(16, 11),
              constrained_layout=True, tight_layout=False)
fig, ax = pitch.draw()
pass_lines = pitch.lines(passes_between.x, passes_between.y,
                         passes_between.x_end, passes_between.y_end, lw=passes_between.width,
                         color=color, zorder=1, ax=ax)
pass_nodes = pitch.scatter(average_locs_and_count.x, average_locs_and_count.y, s=average_locs_and_count.marker_size,
                           color='red', edgecolors='black', linewidth=1, alpha=1, ax=ax)
for index, row in average_locs_and_count.iterrows():
    pitch.annotate(row.name, xy=(row.x, row.y), c='white', va='center', ha='center', size=16, weight='bold', ax=ax)
title = ax.set_title("{} {} Formation vs {}".format(team, formation, opponent), size=28, y=0.97, color='#c7d5cc')
fig.set_facecolor("#22312b")
コード例 #26
0
def passmap(Df,teamname,teamid,min1,max1):
	pitch = Pitch(pitch_type='statsbomb', figsize=(20,13), line_zorder=2, 
			  line_color='#c7d5cc', orientation='horizontal',constrained_layout=True, tight_layout=False)
	fig, ax = pitch.draw()
	df = Df.copy()
	df = df[(df.expandedMinute>=min1)&(df.expandedMinute<=max1)]    
	allplayers = df[(df.teamId==teamid)&(df.name!='')].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]))

	passdf = df.query("(type_displayName=='Pass')&(name in @players)&(receiver in @players)&\
						 (outcomeType_displayName == 'Successful')&(teamId==@teamid)")
	passdf['x'] = passdf['x']
	passdf['y'] = 80 - passdf['y']
	passdf['endX'] = passdf['endX']
	passdf['endY'] = 80 - passdf['endY']
	cols = ['name','receiver']
	gamedf = passdf[cols]
	totalpassdf = gamedf.groupby(cols).size().reset_index(name="count")
	totalpassdf[cols] = np.sort(totalpassdf[cols],axis=1)
	totalpassdf = totalpassdf.groupby(cols)['count'].agg(['sum']).reset_index()
	avg_x = []
	avg_y = []
	blank=np.zeros(len(totalpassdf))
	totalpassdf['passer_x'] = blank
	totalpassdf['passer_y'] = blank
	totalpassdf['receiver_x'] = blank
	totalpassdf['receiver_y'] = blank
	uniquenames = np.array(players)
	uniquejerseys = np.array(shirtNo)
	totalpasses = []
	for name in uniquenames:
		player_pass_df = passdf.query("(name == @name)")
		x = np.mean(player_pass_df['x'])
		y = np.mean(player_pass_df['y'])
		totalpasses.append(len(player_pass_df))
		avg_x.append(x)
		avg_y.append(y)
	for i in range(len(totalpassdf)):
		passername = totalpassdf.iloc[i,0]
		receivername = totalpassdf.iloc[i,1]
		totalpassdf.iloc[i,3] = avg_x[np.where(uniquenames==passername)[0][0]]
		totalpassdf.iloc[i,4] = avg_y[np.where(uniquenames==passername)[0][0]]
		totalpassdf.iloc[i,5] = avg_x[np.where(uniquenames==receivername)[0][0]]
		totalpassdf.iloc[i,6] = avg_y[np.where(uniquenames==receivername)[0][0]]
		link = totalpassdf.iloc[i,2]
		passerx = totalpassdf.iloc[i,3]
		receiverx = totalpassdf.iloc[i,5]
		passery = totalpassdf.iloc[i,4]
		receivery = totalpassdf.iloc[i,6]
		if(link>=1):
			ax.plot([passerx, receiverx],[passery, receivery],linewidth=link/2.5, color ='lightgrey')
	for indx in range(len(uniquenames)):
		name = uniquenames[indx]
		size = 50*totalpasses[np.where(uniquenames==name)[0][0]]
		avgx = avg_x[np.where(uniquenames==name)[0][0]]
		avgy = avg_y[np.where(uniquenames==name)[0][0]]
		jersey = shirtNo[np.where(uniquenames==name)[0][0]]
		ax.scatter(avgx,avgy,color='#d7191c',s=1000,zorder=3)
		ax.annotate(jersey, (avgx, avgy),alpha=1,fontsize=25,color='w',
						horizontalalignment='center',
						verticalalignment='center').set_path_effects([path_effects.Stroke(linewidth=2,
																			foreground='black'), path_effects.Normal()])
	ax.text(125,3,'#    Player (Acc passes)',fontsize=25)
	for i in range(12):
		ax.text(127,3+4*i,'|',fontsize=50)
	for i in range(30):
		ax.text(125+i,3.5,'_',fontsize=50)
#     ax.plot([126,3],[126,50])
	for indx in range(len(players)):
		ax.text(125,7+4*indx,str(shirtNo[indx]),fontsize=25)
	for indx in range(len(players)):
		ax.text(130,7+4*indx,players[indx]+'('+str(totalpasses[indx])+')',fontsize=25)
	ax.set_title(teamname+' Passmap, Exp. Minutes '+str(min1)+ " to "+str(max1),fontsize=50)
	fig.text(0.02, 0.05, "Created by Soumyajit Bose / @Soumyaj15209314",fontstyle="italic",fontsize=20,color='#edece9')
	fig.text(0.02, -0.05, "Acc passes mentioned in brackets next to player names "+"\n"
			 "Width of line is proportional to number of passes exchanged between two players"+"\n"+
			 "A minimum of 1 pass need to be exchanged to show up as a line",
			 fontstyle="italic",fontsize=25,color='#edece9')
	# add_image(bu_alt, fig, left=0.9, bottom=-0.05, width=0.07)
	return fig
コード例 #27
0
df = pd.read_csv('C:/Users/dev/Desktop/messibetis.csv')
df['x'] = df['x'] * 1.2
df['y'] = df['y'] * 0.8
df['endX'] = df['endX'] * 1.2
df['endY'] = df['endY'] * 0.8
fig, ax = plt.subplots(figsize=(13, 8.5))
fig.set_facecolor('#22312b')
ax.patch.set_facecolor('#22312b')

pitch = Pitch(pitch_type='statsbomb',
              pitch_color='#22312b',
              line_color='#c7d5cc',
              figsize=(16, 11),
              constrained_layout=True,
              tight_layout=False)
pitch.draw(ax=ax)
plt.gca().invert_yaxis()
kde = sns.kdeplot(df['x'],
                  df['y'],
                  shade=True,
                  shade_lowest=False,
                  alpha=0.5,
                  n_levels=11,
                  cmap='magma')
for x in range(len(df['x'])):
    if df['outcome'][x] == 'Successful':
        plt.plot((df['x'][x], df['endX'][x]), (df['y'][x], df['endY'][x]),
                 color='green')
        plt.scatter(df['x'][x], df['y'][x], color='Black')
plt.xlim(0, 120)
plt.ylim(0, 80)
コード例 #28
0
"""

from urllib.request import urlopen

from PIL import Image
import matplotlib.pyplot as plt

from mplsoccer.pitch import Pitch
from mplsoccer.utils import add_image

# opening the background image
# pic by webtreats: https://www.flickr.com/photos/webtreatsetc/
# available at: https://www.flickr.com/photos/webtreatsetc/5756834840
IMAGE_URL = 'https://live.staticflickr.com/5065/5756834840_e31c559b26_c_d.jpg'
image = Image.open(urlopen(IMAGE_URL))

pitch = Pitch(pitch_color='None')
fig, ax = pitch.draw(tight_layout=False)
# adding the image and the image credits
ax_image = add_image(image, fig, left=0, bottom=0, width=1, height=1)
ax.text(70, 75, 'cloud pic by\nwebtreats (flickr)', color='white')
# set the pitch to be plotted after the image
# note these numbers can be anything like 0.5, 0.2 as long
# as the image zorder is behind the pitch zorder
ax.set_zorder(1)
ax_image.set_zorder(0)
# save with 'tight' and no padding to avoid borders
# fig.savefig('cloud.png', bbox_inches='tight', pad_inches=0)

plt.show()  # If you are using a Jupyter notebook you do not need this line
コード例 #29
0
              tight_layout=False,
              constrained_layout=True)

# mplsoccer calculates the binned statistics usually from raw locations, such as pressure events
# for this example we will create a binned statistic dividing the pitch into thirds for one point (0, 0)
# we will fill this in a loop later with each team's statistics from the dataframe
bin_statistic = pitch.bin_statistic([0], [0], statistic='count', bins=(3, 1))

# load the StatsBomb logo
sb_logo = Image.open(
    urlopen((
        'https://github.com/statsbomb/open-data/blob/fb54bd7fe20dbd5299fafc64f1f6f0d919a5e40d/'
        'stats-bomb-logo.png?raw=true')))

# Plot
fig, axes = pitch.draw()
axes = axes.ravel()
teams = df['Squad'].values
vmin = df[pressure_cols].min().min(
)  # we normalise the heatmaps with the min / max values
vmax = df[pressure_cols].max().max()
for i, ax in enumerate(axes):
    ax.set_title(teams[i], fontsize=20)
    # fill in the bin statistics from df
    bin_statistic['statistic'] = df.loc[df.Squad == teams[i],
                                        pressure_cols].values
    heatmap = pitch.heatmap(bin_statistic,
                            ax=ax,
                            cmap='coolwarm',
                            vmin=vmin,
                            vmax=vmax)  # plot the heatmap
コード例 #30
0
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