In [7]:
dfd = DF_Dashboard(name='')

dashboard_title = '## Lionel Messi Dashboard'
dashboard_desc = "SELECT A SEASON to see Messi's shots, key passes, through balls, and successful dribbles (take-ons). Shots: excludes penalties, with the size of the circle relative to the StatsBomb xG value. Through Balls: passes that broke the defensive line. Successful passes to offside teammates are excluded from both pass maps."

dashboard = pn.Column(pn.Row(pn.Column(dashboard_title,align='center',sizing_mode='stretch_width'),pn.Spacer(width=360),pn.pane.PNG("stats-bomb-logo.png",align='center',width=200,height_policy='fit'),height_policy='min'),
                      pn.Row(pn.Column(dfd.param,align='end'),pn.Column(dashboard_desc,align='end',sizing_mode='stretch_both')),
                      pn.Row(pn.Column(pn.Row(dfd.shot_map),pn.Row(dfd.dribble_map)),pn.Column(pn.Row(dfd.pass_map),pn.Row(dfd.tb_map)),background='#22312b'))

dashboard.embed()
                                                                                                                       
In [1]:
import pandas as pd
from mplsoccer.pitch import Pitch
import matplotlib.pyplot as plt
import panel as pn
pn.extension()
import param
import ast
from matplotlib import rcParams
rcParams['text.color'] = '#c7d5cc'
rcParams["figure.facecolor"] = "#22312b"

pd.options.display.max_columns = None
%matplotlib inline
In [2]:
barca_burgundy = '#A50044'
barca_gold = '#EDBB00'
barca_blue = '#004D98'

usual_blue = '#5499C7'
usual_red = '#ba4f45'
In [3]:
lineups = pd.read_excel("Messi All Seasons Lineups.xlsx")
seasons = lineups.season_name.unique()
seasons = seasons[::-1]
In [4]:
player = 'Lionel Andrés Messi Cuccittini'

if len(lineups[lineups["player_nickname"] == player]) != 0:
    clean_player = player
else:
    clean_player = lineups[lineups["player_name"] == player]["player_nickname"].values[0]
In [5]:
all_shots = pd.read_excel("La Liga All Seasons - Shots (Parsed).xlsx")
shots = all_shots[all_shots["player"] == player].copy(deep=True)
del all_shots

passes = pd.read_excel("La Liga All Seasons - Passes - Lionel Andrés Messi Cuccittini (Parsed).xlsx")
passes["assisted_shot_id"] = passes["assisted_shot_id"].astype(str)
passes.drop(axis=1,labels='Unnamed: 0',inplace=True)

key_passes = passes[passes["assisted_shot_id"] != 'nan'].copy(deep=True)

all_dribbles = pd.read_excel("La Liga All Seasons - Dribbles (Parsed).xlsx")
dribbles = all_dribbles[all_dribbles["player"] == player].copy(deep=True)
del all_dribbles
In [6]:
class DF_Dashboard(param.Parameterized):
    
    Season = param.ObjectSelector(default=seasons[0], objects = seasons)
    
    def get_shot_data(self):
        
        mask1 = shots["season_name"] == self.Season
        mask2 = shots["outcome"] == "Goal"
        mask3 = shots["type"] != "Penalty"
        mask4 = shots["outcome"] != "Goal"

        non_pen_shots = shots[mask1 & mask3]
        non_pen_goals = shots[mask1 & mask2 & mask3]
        non_pen_missed = shots[mask1 & mask3 & mask4]

        return non_pen_shots,non_pen_goals,non_pen_missed
    
    def get_pass_data(self):

        mask1 = key_passes["season_name"] == self.Season
        mask2 = key_passes["shot_assist"] == True
        mask3 = key_passes["goal_assist"] == True

        season_shot = key_passes[mask1 & mask2]
        season_goal = key_passes[mask1 & mask3]
        
        return season_shot,season_goal
    
    def get_dribble_data(self):
        
        mask1 = dribbles["season_name"] == self.Season
        mask2 = dribbles["outcome"] == 'Complete'
        mask3 = dribbles["outcome"] == 'Incomplete'
        mask4 = dribbles["nutmeg"] == True
        dribble_success = dribbles[mask1 & mask2]
        season_dribbles = dribbles[mask1]
        nutmegs = dribbles[mask1 & mask4]
        
        return dribble_success, season_dribbles, nutmegs
    
    def get_throughball_data(self):

        mask1 = passes["season_name"] == self.Season
        mask2 = passes["through_ball"] == True
        mask3 = passes["shot_assist"] == True
        mask4 = passes["goal_assist"] == True
        mask5 = passes["outcome"].isna()
        mask6 = passes["outcome"].isin(['Incomplete', 'Out'])
        
        tb_incomplete = passes[mask1 & mask2 & mask6]
        tb_complete = passes[mask1 & mask2 & mask5]
        tb_shot = passes[mask1 & mask2 & mask3]
        tb_goal = passes[mask1 & mask2 & mask4]
        len_tb = len(tb_incomplete) + len(tb_complete)
        
        return tb_incomplete, tb_complete, tb_shot, tb_goal, len_tb
    
    def shot_map(inputs):
        season = inputs.Season
        player_non_pen_shots,player_non_pen_goals,player_non_pen_missed = inputs.get_shot_data()
        
        plt.style.use('ggplot')
        pitch = Pitch(pitch_type='statsbomb', orientation='vertical',view='half',
                      pitch_color='#22312b', line_color='#c7d5cc', linewidth=1,
                      constrained_layout=False, tight_layout=True)
        fig, ax = pitch.draw()
        
        ax.set_title('Shots: {} scored, {} xG'.format(len(player_non_pen_goals),player_non_pen_shots["statsbomb_xg"].sum().round(2)), fontsize=18, pad=12,color="#22312b")
        sc1 = pitch.scatter(player_non_pen_missed["start_location_x"], player_non_pen_missed["start_location_y"], c=usual_red, edgecolors='black', alpha = 0.8,
                           s=[xg*250 for xg in player_non_pen_missed["statsbomb_xg"]], ax=ax,label='Other')
        sc2 = pitch.scatter(player_non_pen_goals["start_location_x"], player_non_pen_goals["start_location_y"], c='#ADE0FC', edgecolors='black', alpha = 0.8,
                           s=[xg*250 for xg in player_non_pen_goals["statsbomb_xg"]], ax=ax,label='Goal')
        ax.legend(facecolor='#22312b', edgecolor='None', fontsize=11, loc='lower left')
        plt.close()
        
        return ax.figure
    
    def pass_map(inputs):
        season = inputs.Season
        player_season_shot,player_season_goal = inputs.get_pass_data()
        
        plt.style.use('ggplot')
        pitch = Pitch(pitch_type='statsbomb', orientation='horizontal',
                      pitch_color='#22312b', line_color='#c7d5cc', linewidth=1,view='full',
                      constrained_layout=False, tight_layout=True)
        fig, ax = pitch.draw()
        
        ax.set_title('Key Passes: {}'.format(len(player_season_shot)+len(player_season_goal)), fontsize=18, pad=12,color="#22312b")
        
        pitch.arrows(player_season_shot["start_location_x"], player_season_shot["start_location_y"],
                     player_season_shot["end_location_x"], player_season_shot["end_location_y"], width=1.5,
                     headwidth=10, headlength=10, color=usual_red, ax=ax, label='[{}] assisted shot'.format(len(player_season_shot)))
        pitch.arrows(player_season_goal["start_location_x"], player_season_goal["start_location_y"],
                     player_season_goal["end_location_x"], player_season_goal["end_location_y"], width=1.5,
                     headwidth=10, headlength=10, color='#ADE0FC', ax=ax, label='[{}] assisted goal'.format(len(player_season_goal)))
        ax.legend(facecolor='#22312b', handlelength=2, edgecolor='None', fontsize=11, loc='upper left')
        plt.close()
        
        return ax.figure
    
    def dribble_map(inputs):
        season = inputs.Season
        dribble_success, all_dribbles, nutmegs = inputs.get_dribble_data()
        grid=(6,5)
        
        pitch = Pitch(pitch_type='statsbomb',orientation='horizontal',pitch_color='#22312b', line_color='#22312b',
                      linewidth=1, line_zorder=1, constrained_layout=False, tight_layout=True)
        fig, ax = pitch.draw()
        
        bin_statistic = pitch.bin_statistic(dribble_success["start_location_x"], dribble_success["start_location_y"], statistic='count', bins=grid)
        pitch.heatmap(bin_statistic, ax=ax, cmap='Reds')
        pitch.scatter(dribble_success["start_location_x"], dribble_success["start_location_y"], c=usual_blue, s=5, zorder=2, ax=ax, label='[{}] completed'.format(len(dribble_success)))
        pitch.scatter(nutmegs["start_location_x"], nutmegs["start_location_y"], marker='*', c='yellow', edgecolors='black', s=50, zorder=3, ax=ax, label='[{}] nutmegs'.format(len(nutmegs)))
        ax.legend(facecolor='#22312b', edgecolor='None', fontsize=11, handletextpad=0, loc='upper left')
        ax.set_title('Dribbles', fontsize=18, pad=12,color="#22312b")
        plt.close()
        
        return ax.figure
    
    def tb_map(inputs):
        season = inputs.Season
        tb_incomplete, tb_complete, tb_shot, tb_goal, len_tb = inputs.get_throughball_data()
        
        plt.style.use('ggplot')
        pitch = Pitch(pitch_type='statsbomb', orientation='horizontal',
                      pitch_color='#22312b', line_color='#c7d5cc', linewidth=1,
                      constrained_layout=False, tight_layout=True)
        fig, ax = pitch.draw()
        
        ax.set_title('Through Balls: {} attempted'.format(len(tb_incomplete)+len(tb_complete)), fontsize=18, pad=12,color="#22312b")
        
        pitch.arrows(tb_incomplete["start_location_x"], tb_incomplete["start_location_y"],
                    tb_incomplete["end_location_x"], tb_incomplete["end_location_y"], width=1.5,
                     headwidth=10, headlength=10, color=usual_red, ax=ax, label='[{}] incomplete'.format(len(tb_incomplete)))
        pitch.arrows(tb_complete["start_location_x"], tb_complete["start_location_y"],
                     tb_complete["end_location_x"], tb_complete["end_location_y"], width=1.5,
                     headwidth=10, headlength=10, color='#ADE0FC', ax=ax, label='[{}] complete: {}%'.format(len(tb_complete), round(len(tb_complete)/(len(tb_complete)+len(tb_incomplete)) *100,1)))

        ax.legend(facecolor='#22312b', handlelength=2, edgecolor='None', fontsize=11, loc='upper left')
        plt.close()
        
        return ax.figure