#!/usr/bin/env python # coding: utf-8 # In[2]: import pandas as pd import numpy as np import scipy.stats as stats from scipy.stats import zscore import matplotlib.pyplot as plt from soccerplots.radar_chart import Radar from mplsoccer import PyPizza, add_image, FontManager import math from PIL import Image import imageio # In[307]: #Read in CSV file df = pd.read_csv('FbrefSB2122.csv') pd.set_option('display.max_rows', 500) pd.set_option('display.max_columns', 500) # In[308]: df.head() # In[309]: #Filter the dataframe by age and minutes played - 26 and younger, and 750 mins played df = df.loc[(df['Age']<27) & (df['Min']>750) & (df['Main Position']=='Centre-Back')] # In[310]: df.head() # In[311]: #Seperating dataframe for player key information df1 = df.filter(['Player','Squad','Main Position','Comp','Mins','Age'], axis=1) # In[312]: #Convert all numeric values to Z-Scores numeric_cols = df.select_dtypes(include=[np.number]).columns df2 = df[numeric_cols].apply(zscore) # In[313]: df2.head() # In[314]: #Combine both the player info dataframe and Z-Score data frame together #Values used to standarise z-scores to allow ratings to be on a 100 scale newdf = pd.concat([df1,df2 * 20 + 90], axis = 1) # In[315]: newdf.head() # In[316]: #List of all metrics, to create attributes and weightings newdf.columns.values.tolist() # In[317]: #Weight and Ratings for metrics #Minutes Played newdf['Minutes (12.5%)'] = newdf['Min'] #Defending newdf['ClearancesPer90'] = newdf['ClrPer90'] *0.2 newdf['DribblersTackledPer90'] = newdf['DrbTkl%Per90'] *0.3 newdf['ShotBlocksPer90'] = newdf['ShBlocksPer90'] *0.3 newdf['PAdjInterceptionsPer90'] = newdf['pAdjIntPer90'] *0.2 newdf['Defending (20%)'] = newdf['AerialWinsPer90'] + newdf['DribblersTackledPer90'] + newdf['ShotBlocksPer90'] + newdf['PAdjInterceptionsPer90'] #Aerial Ability newdf['AerialWinsPer90'] = newdf['AerialWinsPer90'] *0.35 newdf['AerialDuelSuccessPer90'] = newdf['AerialWin%Per90'] *0.65 newdf['Aerial (20%)'] = newdf['AerialWinsPer90'] + newdf['AerialDuelSuccessPer90'] #Front Foot newdf['MiddlesThirsPressures'] = newdf['Mid3rdPressPer90'] *0.15 newdf['PressuresPer90'] = newdf['PressSuccPer90'] *0.40 newdf['PressureSuccess'] = newdf['PressSucc%Per90'] *0.45 newdf['Front Foot (5%)'] = newdf['MiddlesThirsPressures'] + newdf['PressuresPer90'] + newdf['PressureSuccess'] #Ball Carrying newdf['ProgressiveCarriePer90'] = newdf['ProgCarriesPer90'] *0.4 newdf['CarriesToFinal3rdPer90'] = newdf['CarriesToFinal3rdPer90'] *0.2 newdf['TotalCarryDistancePer90'] = newdf['TotCarryDistPer90'] *0.2 newdf['ProgressiveCarryDistancePer90'] = newdf['PrgCarryDistPer90'] *0.2 newdf['Ball Carrying (15%)'] = newdf['ProgressiveCarriePer90'] + newdf['CarriesToFinal3rdPer90'] + newdf['TotalCarryDistancePer90'] + newdf['ProgressiveCarryDistancePer90'] #Ball Playing newdf['ProgressivePassesPer90'] = newdf['ProgPassesPer90'] *0.55 newdf['FinalThirdCompletedPassesPer90'] = newdf['Final1/3CmpPer90'] *0.25 newdf['PenaltyAreaCompletedPassesPer90'] = newdf['PenAreaCmpPer90'] *0.2 newdf['Ball Playing (15%)'] = newdf['ProgressivePassesPer90'] + newdf['FinalThirdCompletedPassesPer90'] + newdf['PenaltyAreaCompletedPassesPer90'] #Ball Retention newdf['ShortPassCompletion'] = newdf['ShortPassCmp%Per90'] *0.4 newdf['MediumPassCompletion'] = newdf['MedPassCmp%Per90'] *0.35 newdf['LongPassCompletion'] = newdf['LongPassCmp%Per90'] *0.15 newdf['Ball Retention (10%)'] = newdf['ShortPassCompletion'] + newdf['MediumPassCompletion'] + newdf['LongPassCompletion'] #Attacking Threat newdf['NPxGPer90'] = newdf['npxGPer90'] *0.4 newdf['ShotsPer90'] = newdf['ShotsPer90'] *0.15 newdf['AttackingBoxTouchesPer90'] = newdf['AttPenTouchPer90'] *0.3 newdf['Attacking Threat (2.5%)'] = newdf['NPxGPer90'] + newdf['ShotsPer90'] + newdf['AttackingBoxTouchesPer90'] # In[318]: newdf.head() # In[319]: #Filter the df to just see the attribute weightings and player info newdf.drop(newdf.columns.difference(['Player','Squad','Main Position','Comp','Mins','Minutes (12.5%)','Defending (20%)','Aerial (20%)','Front Foot (5%)','Ball Carrying (15%)','Ball Playing (15%)','Ball Retention (10%)','Attacking Threat (2.5%)']), 1, inplace=True) # In[320]: newdf.head() # In[321]: #Weight the overall ratings newdf['Minutes (12.5%)'] = newdf['Minutes (12.5%)'] *0.125 newdf['Defending (20%)'] = newdf['Defending (20%)'] *0.2 newdf['Aerial (20%)'] = newdf['Aerial (20%)'] *0.2 newdf['Front Foot (5%)'] = newdf['Front Foot (5%)'] *0.05 newdf['Ball Carrying (15%)'] = newdf['Ball Carrying (15%)'] *0.15 newdf['Ball Playing (15%)'] = newdf['Ball Playing (15%)'] *0.15 newdf['Ball Retention (10%)'] = newdf['Ball Retention (10%)'] *0.1 newdf['Attacking Threat (2.5%)'] = newdf['Attacking Threat (2.5%)'] *0.025 newdf['CB_Rating'] = newdf['Minutes (12.5%)'] + newdf['Defending (20%)'] + newdf['Aerial (20%)'] + newdf['Front Foot (5%)'] + newdf['Ball Carrying (15%)'] + newdf['Ball Playing (15%)'] + newdf['Ball Retention (10%)'] + newdf['Attacking Threat (2.5%)'] # In[322]: newdf # In[323]: #Round overall ratings newdf = newdf.round({'Minutes (12.5%)': 2}) newdf = newdf.round({'Defending (20%)': 2}) newdf = newdf.round({'Aerial (20%)': 2}) newdf = newdf.round({'Front Foot (5%)': 2}) newdf = newdf.round({'Ball Carrying (15%)': 2}) newdf = newdf.round({'Ball Playing (15%)': 2}) newdf = newdf.round({'Ball Retention (10%)': 2}) newdf = newdf.round({'Attacking Threat (2.5%)': 2}) newdf = newdf.round({'CB_Rating': 2}) newdf.sort_values("CB_Rating", ascending=False) # In[324]: #Download as CSV newdf.to_csv('StatsbombU26CBs.csv', index=False) # In[279]: #Below code is for Data Visual # In[280]: #Seperating dataframe from player key information dfviz = newdf.filter(['Player','Minutes (12.5%)','Defending (20%)','Aerial (20%)','Front Foot (5%)','Ball Carrying (15%)','Ball Playing (15%)','Ball Retention (10%)','Attacking Threat (2.5%)'], axis=1) # In[281]: #Params for data visual params = list(dfviz.columns) params = params[1:] params # In[282]: #Players to select for data visual dfviz.Player.unique() # In[401]: #New dataframe for player / edit name to change visual values = dfviz.loc[dfviz['Player']=='Niklas Süle'].reset_index() values = list(values.loc[0]) values = values[2:] # In[402]: #Check in place to ensure number of parameters and metric values are correct print(len(params),len(values)) # In[403]: #Values for the player selected above values # In[404]: #Getting the min and max values for the ranges for the data visual min_range = [] max_range = [] for x in params: a = min(dfviz[params][x]) b = max(dfviz[params][x]) min_range.append((a)) max_range.append((b)) # In[405]: #Check min values min_range # In[406]: #Check max values max_range # In[407]: #Creating pizza chart baker = PyPizza( params=params, background_color="white", straight_line_color="#000000", min_range=min_range, # min range values max_range=max_range, # max range values last_circle_color="#000000", last_circle_lw=2.5, straight_line_lw=1, other_circle_lw=0, other_circle_color="#000000", inner_circle_size=16.5, ) # plot pizza fig, ax = baker.make_pizza( values, # list of values figsize=(10, 10), # adjust figsize according to your need color_blank_space="same", # use same color to fill blank space blank_alpha=0.4, # alpha for blank-space colors kwargs_slices=dict( facecolor="#E40A27",edgecolor="#000000", zorder=2, linewidth=1 ), # values to be used when plotting slices kwargs_params=dict( color="#000000", fontsize=13, ), # values to be used when adding parameter kwargs_values=dict( color="#000000", fontsize=13, bbox=dict( edgecolor="#000000", facecolor="#E40A27", boxstyle="round,pad=0.2", lw=1 ) ) # values to be used when adding parameter-values ) # Add Title / Edit Player Name and Club fig.text( 0.515, 0.975, "Niklas Süle - Bayern Munich", size=18, fontweight='bold', ha="center", color="#000000" ) # Add Subtitle fig.text( 0.515, 0.956, "Centre Back Rating Breakdown | Top Five European Leagues 2021-22", size=14, ha="center", color="#000000" ) # add credits CREDIT_1 = "Graphic: @HenshawAnalysis" CREDIT_2 = "Data is via Statsbomb" CREDIT_3 = "Template: Centre Back Rating Breakdown" CREDIT_4 = "Notes: Value in brackets is the weighting for that attribute" fig.text( 0.935, 0.000, f"{CREDIT_1}\n{CREDIT_2}\n{CREDIT_3}\n{CREDIT_4}", size=9, color="#545454", ha="right" ) fig.text (0.511, 0.509, "Overall\nRating", size=12, ha="center", fontweight='bold') fig.text (0.511, 0.48, "119.04", size=16, ha="center", fontweight='bold') # add image im2 = imageio.imread('SB_LogoNew.png') ax_image = add_image( im2, fig, left=0.1, bottom=-0.09, width=0.22, height=0.22 ) # these values might differ when you are plotting plt.show() # In[ ]: # In[ ]: