<jupyter_start><jupyter_text>KMeans Clustering on whole league  - Objectives -  1 - defensive feature clustering  1.1 - Use an elbow plot to choose optimal k value. 1.2 - Observe clusters over PCA graph to look for outliers.  1.3 - Observe clusters over key scaled features.  2 - Offensive feature clustering.  2.1 - Use an elbow plot to choose optimal k value.  2.2 - Observe clusters over PCA graph to look for outliers.  2.3 - Observe clusters over key scaled features.<jupyter_code>import pandas as pd 
import matplotlib.pyplot as plt
import seaborn as sns
from sklearn.pipeline import make_pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.cluster import KMeans
from sklearn.decomposition import PCA

# loading data 

df = pd.read_csv('../data/final_per_90_and_pAdj.csv')
df.info()
# pulling out defensive features for clustering 
def_stats = df.loc[df['Nineties']>1][[ 'Nineties','pAdj_Total_tackles', 'pAdj_Tackles_Won','Aerial_win_pct',

       'pAdj_Num_Dribblers_tackled', 'pAdj_Num_Dribbled_past','pAdj_Blocks',
       'pAdj_Interceptions', 'pAdj_Clearences',
       'pAdj_Fouls', 'pAdj_def_interceptions',
       'pAdj_Recoveries', 'pAdj_Aerial_Duels_lost',
       'True_tackle_pct', 'pAdj_Tackle_int_blocks']]
def_stats.iloc[:3,0:4]<jupyter_output><empty_output><jupyter_text>1 Defensive feature clustering  1.1 Use elbow plot to choose k value of 4<jupyter_code># Create scaler: scaler
scaler = StandardScaler()

scaler.fit(def_stats)
scaled_stats= scaler.transform(def_stats)


ks = range(1, 15)
inertias = []

for k in ks:
    # Create a KMeans instance with k clusters: model
    model = KMeans(n_clusters=k)
    
    # Fit model to samples
    model.fit(scaled_stats)
    
    # Append the inertia to the list of inertias
    inertias.append(model.inertia_)
    
# Plot ks vs inertias
plt.plot(ks, inertias, '-o')
plt.xlabel('number of clusters, k')
plt.ylabel('inertia')
plt.xticks(ks)
plt.show()<jupyter_output><empty_output><jupyter_text>1.2 Observe clusters over PCA components<jupyter_code># Create scaler: scaler
scaler = StandardScaler()
# Create KMeans instance: kmeans

kmeans = KMeans(n_clusters=4)


model = kmeans.fit(scaled_stats)
print('interita :',model.inertia_)
labels = model.predict(scaled_stats)

def_pca = PCA().fit(scaled_stats)
def_pca_x = def_pca.transform(scaled_stats)
def_pca_df = pd.DataFrame(def_pca_x[:,:2])
sns.set_style('ticks')
fig, ax = plt.subplots()
fig.set_size_inches(18.5, 10.5)
data = def_pca_x[:,0:2]
x = def_pca_x[:, 0]
y = def_pca_x[:, 1]

c = labels


pc_var = 100 * def_pca.explained_variance_ratio_.cumsum()[1]
sns.set_style("whitegrid")
g = sns.scatterplot(data=def_pca_df, x =x, y=y,hue=c,
#                     cmap="plasma",
                    palette=["C0", "C1", "C2","C3",
#                              "k"
                            ], 
                    ax=ax).set(title=f' clusters shown over defensive stats PCA, {pc_var:.1f}% variance explained',
                              xlabel='first component',ylabel='second component')


p=df.loc[df['Nineties']>1]['player_name']
for p, x, y in zip(p, x, y):
    if x >6:
        plt.annotate(p, (x, y))
    if y> 3.6:
        plt.annotate(p, (x,y))
        

plt.show()<jupyter_output>interita : 5130.9751582064555<jupyter_text>Observation - Most defenders are in cluster 1 and 3 which we see at the top and right side of the graph. players whos features show the most variance between the two PCA are labeled above.<jupyter_code>dfc = pd.DataFrame({'cluster_label':labels,'name':df.loc[df['Nineties']>1]['player_name'],
                    'Position':df.loc[df['Nineties']>1]['Position'],
                   'PCA_first_component':def_pca_x[:, 0],
                   'PCA_second_component':def_pca_x[:,1],'Ninties':df.loc[df['Nineties']>1]['Nineties']})
dfc.loc[dfc['Position']=='DF']['cluster_label'].value_counts()<jupyter_output><empty_output><jupyter_text>1.2 - Observe clusters over key defensive features.<jupyter_code>xs = def_stats.iloc[:,1]
ys = def_stats.iloc[:,3]

# # Make a scatter plot of xs and ys, using labels to define the colors

fig, (ax1, ax2) = plt.subplots(1, 2)
sns.set_style("whitegrid")
fig.set_size_inches(18.5, 10.5)
g = sns.scatterplot(data=def_stats, x=xs,y =ys,hue=labels,palette=["C0", "C1", "C2","C3"],
               ax=ax1 ).set(title='Aerial win pct vs total tackles with cluster hues',
                            xlabel='pAdj_Total_tackles',
                           ylabel='Aerial_win_pct')

b = sns.scatterplot(data=scaled_stats, x=def_stats.iloc[:,-2],y =def_stats.iloc[:,-1],hue=labels,palette=["C0", "C1", "C2","C3"],
               ax=ax2 ).set(title='tackle int blocks vs True tackle pct with cluster hues',
                            xlabel='True_tackle_pct',ylabel='pAdj_Tackle_int_blocks')



plt.show()


sns.set_style("whitegrid")
g = sns.jointplot(x=def_stats.iloc[:,-1] ,
            y=def_stats.iloc[:,-4],
            data=def_stats,
#             xlim=(0.1, 1.0), 
                  palette=["C0", "C1", "C2","C3",
#                            "k"
                          ] ,
                  hue=labels,
#                   alpha=0.4,
                  
                 ) 
g.plot_joint(sns.kdeplot, color="r", zorder=0, levels=2)
# g.plot(sns.kdeplot, sns.histplot)

plt.show()
plt.clf()<jupyter_output><empty_output><jupyter_text>2 - KMeans for attacking features<jupyter_code>df.columns.values
# select attacking features
att_stats = df.loc[df['Nineties']>5][['Nineties', 'xA',
       'Key_pass', 'Comp_prog', 
        'Total_Prg_Dist', 'Short_Cmp', 'Short_Att',
       'Short_Cmp_pct', 'Medium_Cmp', 'Medium_Att', 'Medium_Cmp_pct',
       'Long_Cmp', 'Long_Att', 'Long_Cmp_pct', 'touches',
       'touches_mid_3rd',
       'touches_att_3rd', 'touches_att_box', 'dribble_Succ',
       'dribble_Att', 'dribble_Succ_pct', 'num_dribble_past',
       'dribble_megs','carries', 'carries_prog_dist',
       'carries_prog', 'carries_att_3rd', 'carries_att_box',
       'miss_control', 'dispossed', 'recep_targ', 'recep_succ',
       'recept_pct', 'Fouls_drawn', 'Offsides', 'Crosses', 
        'PK_won','Aerial_win_pct', 'Gls','Sh','SoT', 'SoT%',
       'G/Sh', 'G/SoT', 'xG', 'npxG',
       'npxG/Sh', 'np:G-xG', 'avg_shrt+med_pass_pct',
       'pct_long_balls', 'prog_carry+lng_comp+crosses',
       'attacking_touches'
                                     ]]<jupyter_output><empty_output><jupyter_text>2.1 Use elbow plot to choose k value of 4 clusters.<jupyter_code>scaler = StandardScaler()
scaler.fit(att_stats)
att_scaled_stats= scaler.transform(att_stats)

ks = range(1, 15)
inertias = []

for k in ks:
    # Create a KMeans instance with k clusters: model
    model = KMeans(n_clusters=k)
    
    # Fit model to samples
    model.fit(att_scaled_stats)
    
    # Append the inertia to the list of inertias
    inertias.append(model.inertia_)
    
# Plot ks vs inertias
plt.plot(ks, inertias, '-o')
plt.xlabel('number of clusters, k')
plt.ylabel('inertia')
plt.xticks(ks)
plt.show()<jupyter_output><empty_output><jupyter_text>2.2 Observe clusters over PCA components to view players with most variance from cluster<jupyter_code># Create KMeans instance: kmeans

kmeans = KMeans(n_clusters=4)


model = kmeans.fit(att_scaled_stats)
print('interita :',model.inertia_)
att_labels = model.predict(att_scaled_stats)

att_pca = PCA().fit(att_scaled_stats)
att_pca_x = att_pca.transform(att_scaled_stats)
att_pca_df = pd.DataFrame(att_pca_x[:,:2])
sns.set_style('whitegrid')
fig, ax = plt.subplots()
fig.set_size_inches(18.5, 10.5)
data = att_pca_x[:,0:2]
x = att_pca_x[:, 0]
y = att_pca_x[:, 1]

c = att_labels


pc_var = 100 * att_pca.explained_variance_ratio_.cumsum()[1]
g = sns.scatterplot(data=att_pca_x[:,0:2], x =att_pca_x[:, 0], y=att_pca_x[:, 1],
                    hue=c,palette=["C0", "C1", "C2","C3", 
#                                    "k"
                                  ],
                    ax=ax)
plt.xlabel('First component')
plt.ylabel('Second component')
plt.title(f' defensive stats PCA, {pc_var:.1f}% variance explained')
p=df.loc[df['Nineties']>1]['player_name']
for p, x, y in zip(p, x, y):
    if x >10:
        plt.annotate(p, (x, y))
    if y> 8:
        plt.annotate(p, (x,y))
plt.show()<jupyter_output>interita : 14402.502646817773<jupyter_text>pca scatter of first two components show players with the largest variance of features in relationt to their cluster at edges of graph and are labeled above.<jupyter_code>dfc = pd.DataFrame({'cluster_label':att_labels,'name':df.loc[df['Nineties']>5]['player_name'],
                    'Position':df.loc[df['Nineties']>5]['Position'],
                   'PCA_first_component':att_pca_x[:, 0],
                   'PCA_second_component':att_pca_x[:,1],'Ninties':df.loc[df['Nineties']>5]['Nineties']})
dfc['cluster_label'].value_counts()
dfc.loc[dfc['Position']=='MF']['cluster_label'].value_counts()
dfc.loc[dfc['Position']=='DF']['cluster_label'].value_counts()<jupyter_output><empty_output><jupyter_text>2.2 - Observe clusters over key offensive features.<jupyter_code># # Make a scatter plot of xs and ys, using labels to define the colors

fig, (ax1, ax2) = plt.subplots(1, 2)
sns.set_style("whitegrid")
fig.set_size_inches(18.5, 10.5)
g = sns.scatterplot(data=att_stats, x=att_stats[ 'prog_carry+lng_comp+crosses'],
                    y =att_stats['attacking_touches']
                    ,hue=att_labels, 
                    palette=["C0", "C1", "C2","C3"],
               ax=ax1 ).set(title='Attacking touches vs progressive carry+ long ball and crosses with cluster hues',
                            xlabel='prog_carry+lng_comp+crosses',
                           ylabel='attacking_touches')


b = sns.scatterplot(data=att_stats, x=att_stats['npxG'],y =att_stats['xA'],hue=att_labels,
                    palette=["C0", "C1", "C2","C3"],
               ax=ax2 ).set(title='xA vs npxG with cluster hues',
                            xlabel='xA',ylabel='npxG')



plt.show()<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.14401440144014402, 'fraction_numerical': 0.0204020402040204, 'mean_word_length': 3.4543429844097995, 'pattern_counts': {'":': 0, '<': 39, '<?xml version=': 0, '>': 53, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 3, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '10', 'dir': 'jupyter-structured-clean-dedup', 'id': '299622', 'license': 'MIT', 'n_tokens_mistral': 3924, 'n_tokens_neox': 3733, 'n_words': 725, 'path': 'alt_work/modeling/KMeans_clustering.ipynb', 'repo_name': 'misterrustia/MLS_clustering_Captsone', 'size': '9999'}