#!/usr/bin/env python # coding: utf-8 # # Link between free space and 3-points efficiency # # After modelling both model of space occupation and comparing them, we focus on the correlation between space occupation and 3-point performance. To do so, we browse all the games we have, we track when there are 3-point shots and then memorize the evolution of pressure on the shooter 3 seconds before he shots. The algorithm is not presented here, but is available as a python file : track_shoot.py. # # Here we extract the informations we want from the data we collected. # # ## Data import # ----- # # The shots are memorized in two csv files : df_plot_mean and df_shots calculated thanks to python_file shots_statistics.py. They contain the same information but aren't structured in the same way (df_plot_mean's structure let us plot averaged evolution). They are composed of the following columns : # * D : evolution of the shooter's *free space* ($\delta_{space}^*$ distance to the closest defender) 3 seconds before the shot. # * T : It the same but *free space* is calculated as the time (in second) needed by the closest defender to join the position of the shooter ($\delta_{time}^*$). # * Release time : corresponds to the time between the reception of the ball and the shot. It is negative : -2 means that the shooter kept the ball 2 seconds before shooting. # * Time : corresponds to time values linked to free space evolution. # * player_id : a list which contains shooters' ID. # * x_shot,y_shot : position of the player at the release. # * x_ball, y_ball, z_ball : ball's trajectory. # * quarter,clock,Match_id # * Shot_type : type of shots (catch-and-shoot or pull-up) # * Shot_result : differentiate hits or miss # # In[1]: import pandas as pd import ast df_plot_mean=pd.read_csv('data/df_plot_mean.csv',index_col=[0]) df_shots=pd.read_csv('data/df_shots.csv',index_col=[0],converters={1:ast.literal_eval,2:ast.literal_eval,3:ast.literal_eval,7:ast.literal_eval,8:ast.literal_eval,9:ast.literal_eval,18:ast.literal_eval,19:ast.literal_eval,20:ast.literal_eval}) df_stats=pd.read_csv('data/df_stats.csv',index_col=[0]) # In[2]: print('number of shots:',len(df_shots)) print(df_stats['total_cas'].sum(),df_stats['total_cas'].sum()/26295*100) print(df_stats['success'].sum(),df_stats['miss'].sum(),df_stats['success'].sum()/26295*100) print(df_stats['success_cas'].sum(),df_stats['miss_cas'].sum(),df_stats['success_cas'].sum()/18896*100) print(len(df_shots.query('Shot_type=="pull-up 3P" and Shot_result==1'))/len(df_shots.query('Shot_type=="pull-up 3P"'))) # ## *Free space* evolution before a 3-point shot # ------ # # ### Plot all shots # In[2]: import numpy as np import seaborn as sns import matplotlib.pyplot as plt # In[39]: fig=plt.figure(figsize=(15,10)) for row in df_shots.itertuples(): Time=getattr(row,'Time') D=getattr(row,'D') plt.plot(Time,D,'k-',alpha=0.005) plt.xlim((-3.2,0.8)) plt.ylim((0,30)) # ### Mean evolution # # First we compute a function to plot the evolution of *free space* averaged on all the shots. Let's note that we round the values of time with a precision of 0.01 second. Yet the precision of position data is only 0.04 seconds. # # Let's note that we delet some shots because the values of time are wrong : the clock stops but the evolution continue to be captured therefore, if we don't do that, we have false values for a certain value of time. # In[5]: def averaged_evolution(df,sd=None,hue=None,palette=['blue'],style=None,fontsize='medium',size=None): ## rename columns to have good labels ## df2=df.rename(columns={"Time": "time [s]",'D':r'$<\delta_{d}^*(t)$> [feet]','T':r'$<\delta_{t}^*(t)$> [s]'}) ### plot ### ax = sns.lineplot(x="time [s]", y=r'$<\delta_{d}^*(t)$> [feet]', data=df2,palette=palette,ci=sd,hue=hue,style=style,size=size) plt.axvline(0, color='black',linestyle="dashed",lw=0.5) plt.legend(loc='lower left',fontsize=fontsize) plt.show() plt.clf() ax = sns.lineplot(x="time [s]", y=r'$<\delta_{t}^*(t)$> [s]', data=df2,palette=palette,ci=sd,hue=hue,style=style,size=size) plt.axvline(0, color='black',linestyle="dashed",lw=0.5) plt.legend(loc='lower left',fontsize=fontsize) plt.show() plt.clf() # In[16]: df_plot_mean=df_plot_mean.query('Time>-3. and Time<0.8') # In[5]: averaged_evolution(df_plot_mean) # In[6]: averaged_evolution(df_plot_mean) # We see that there is some noise. To calculate the plot sns.lineplot take each value of time and make a mean over all the pressure value associated. If we count the number of pressure values per time value we can see that there isn't an equilibrium as there are more of multiple of 0.04 : # In[8]: print('count',df_plot_mean.groupby('Time').count()) # Our aim is to make mean for each value of time over the 26325 shots. To do so, we will aggregate values around multiple of 0.04 seconds with the following function : # In[170]: def aggregating_04(row): number=row['Time'] q=number//0.04 if abs(round((q*0.04-number),2))<=0.02: return(q*0.04) else : return((q+1)*0.04) # In[171]: df_plot_mean['Time']=df_plot_mean.apply(aggregating_04,axis=1) # In[17]: averaged_evolution(df_plot_mean) # The result is better here. Now let's see if we plot the standard deviation : # In[18]: averaged_evolution(df_plot_mean,sd='sd') # In[9]: averaged_evolution(df_plot_mean,sd='sd') # ### Different types of shots # # We distinguish two types of shots : # * catch-and-shoot shot : when a player immediately shot after receiving the ball (2 seconds after) # * pull-up shot : when a player shot after dribbling # # In fact some shots can be in neither category : wait more than two seconds without dribbling. But we admit that this is only a small part of shots. Therefore to distinguish both types we look at the value TIME_TO_SHOOT. # # We found that there were 78% of catch-and-shoot shots. Yet our games are from 2013 to 2016, according to https://www.thespax.com/nba/three-point-shooting-part-i-the-dying-catch-and-shoot-shot/, there were about 75% of catch-and-shoot shots. Our value is closed to the reality. # In[19]: averaged_evolution(df_plot_mean,palette=['blue','orange'],hue='Shot_type') # In[21]: averaged_evolution(df_plot_mean,palette=['blue','orange'],hue='Shot_type',sd='sd') # ### Difference between success and miss # # We want to know if the pressure exerced on a player has an influence on his 3-point performance. # In[22]: averaged_evolution(df_plot_mean,palette=['blue','orange'],hue='Shot_type',style='Shot result',fontsize='small') # ### Curry's case # In[23]: df_curry_mean=df_plot_mean.query('player_id==201939').copy() averaged_evolution(df_curry_mean) # In[24]: averaged_evolution(df_curry_mean,sd='sd') # In[25]: averaged_evolution(df_curry_mean,palette=['blue','orange'],hue='Shot_type') # In[27]: averaged_evolution(df_curry_mean,palette=['blue','orange'],hue='Shot_type',sd='sd') # In[28]: averaged_evolution(df_curry_mean,palette=['blue','orange'],hue='Shot_type',style='Shot result') # ### Compare Curry to global behaviour # In[29]: def averaged_evolution_two_df(df,df_curry,sd=None,hue=None,palette=['blue'],style=None,size=None): ## rename columns to have good labels ## df2=pd.concat([df,df_curry],ignore_index=True) players=['all' for k in range(len(df))]+['Curry' for k in range(len(df_curry))] df2['Player']=players df2=df2.rename(columns={"Time": "time [s]",'D':r'$<\delta_{d}^*(t)$> [feet]','T':r'$<\delta_{t}^*(t)$> [s]'}) ### plot ### ax = sns.lineplot(x="time [s]", y=r'$<\delta_{d}^*(t)$> [feet]', data=df2,palette=palette,ci=sd,hue=hue,style=style,size=size) plt.axvline(0, color='black',linestyle="dashed",lw=0.5) plt.legend(loc='lower left',fontsize='small') plt.show() plt.clf() ax = sns.lineplot(x="time [s]", y=r'$<\delta_{t}^*(t)$> [s]', data=df2,palette=palette,ci=sd,hue=hue,style=style,size=size) plt.axvline(0, color='black',linestyle="dashed",lw=0.5) plt.legend(loc='lower left',fontsize='small') #plt.savefig('Comparison_curry_t',dpi=72) plt.show() plt.clf() # In[31]: averaged_evolution_two_df(df_plot_mean,df_curry_mean,sd=None,hue='Shot_type',palette=['blue','orange'],style=None,size='Player') # ## Curry superimposed shots # In[32]: df_curry=df_shots.query('player_id==201939').copy() fig, (ax1, ax2) = plt.subplots(1, 2,figsize=(20,7)) k=0 for row in df_curry.itertuples(): Time=getattr(row,'Time') D=getattr(row,'D') T=getattr(row,'T') ax1.plot(Time,D,'k-',alpha=0.1) ax2.plot(Time,T,'k-',alpha=0.1) k+=1 ax1.set_xlim((-3.2,0.8)) ax1.set_ylim((0,30)) ax2.set_xlim((-3.2,0.8)) ax2.set_ylim((0,2)) # In[113]: fig, (ax1, ax2) = plt.subplots(1, 2,figsize=(18,7)) df_curry_pull_up=df_shots.query('player_id==201939 and Shot_type=="pull-up 3P"').copy() df_curry_catch=df_shots.query('player_id==201939 and Shot_type=="catch-and-shoot 3P"').copy() for row in df_curry_pull_up.itertuples(): Time=getattr(row,'Time') D=getattr(row,'D') T=getattr(row,'T') ax1.plot(Time,D,'b-',alpha=0.1) #ax2.plot(Time,T,'b-',alpha=0.1) k+=1 for row in df_curry_catch.itertuples(): Time=getattr(row,'Time') D=getattr(row,'D') T=getattr(row,'T') ax2.plot(Time,D,'r-',alpha=0.1) #ax2.plot(Time,T,'r-',alpha=0.1) sns.lineplot(x="Time", y='D', data=df_curry_mean[df_curry_mean['Shot_type']=="pull-up 3P"],hue='Shot_type',palette=['black'],ax=ax1,size_order=[60]) ax1.set_xlim((-3.2,0.8)) ax1.set_ylim((0,30)) sns.lineplot(x="Time", y='D', data=df_curry_mean[df_curry_mean['Shot_type']=="catch-and-shoot 3P"],hue='Shot_type',palette=['black'],ax=ax2,size_order=[60]) ax2.set_xlim((-3.2,0.8)) ax2.set_ylim((0,30)) # In[36]: fig, (ax1, ax2) = plt.subplots(1, 2,figsize=(20,7)) #for row in df_curry_pull_up.iloc[:3].itertuples(): # Time=getattr(row,'Time') # D=getattr(row,'D') # T=getattr(row,'T') # tts=getattr(row,'Time_to_shoot')[0] # ax1.axvline(tts, color='b',linestyle="dashed",lw=0.5) # ax2.axvline(tts, color='b',linestyle="dashed",lw=0.5) # ax1.plot(Time,D,'b-',alpha=0.8) # ax2.plot(Time,T,'b-',alpha=0.8) for row in df_curry_catch.iloc[100:101].itertuples(): Time=getattr(row,'Time') D=getattr(row,'D') T=getattr(row,'T') tts=getattr(row,'release_time') print(getattr(row,'Match_id'),getattr(row,'quarter'),getattr(row,'clock'),getattr(row,'player_id')) ax1.axvline(tts, color='black',linestyle="dashed",lw=0.5) ax2.axvline(tts, color='black',linestyle="dashed",lw=0.5) ax1.plot(Time,D,'r-',alpha=0.8) ax2.plot(Time,T,'r-',alpha=0.8) ax1.set_xlim((-3.2,0.8)) ax1.set_ylim((0,30)) ax2.set_xlim((-3.2,0.8)) ax2.set_ylim((0,2)) # ### Comparing two players with high percentage # In[45]: df_other_mean=df_plot_mean.query('player_id==202691').copy() averaged_evolution_two_df(df_other_mean,df_curry_mean,sd=None,hue='Shot_type',palette=['blue','orange'],style='player_id') # ### Comparing two players : one with high and the other with low percentage # In[76]: fig, ((ax1, ax2),(ax3,ax4)) = plt.subplots(2, 2,figsize=(20,14)) df_other_mean=df.query('player_id==202323').copy() df_curry_pull_up=df_shots.query('player_id==201939 and Shot_type=="pull-up 3P"').copy() df_other_pull_up=df_shots.query('player_id==202323 and Shot_type=="pull-up 3P"').copy() df_curry_catch=df_shots.query('player_id==201939 and Shot_type=="catch-and-shoot 3P"').copy() df_other_catch=df_shots.query('player_id==202323 and Shot_type=="catch-and-shoot 3P"').copy() print('number of shots Curry:',len(df_curry_pull_up)+len(df_curry_catch)) print('percentage of CandS Curry:',len(df_curry_catch)/(len(df_curry_catch)+len(df_curry_pull_up))) print('number of shots Other:',len(df_other_pull_up)+len(df_other_catch)) print('percentage of CandS Other:',len(df_other_catch)/(len(df_other_catch)+len(df_other_pull_up))) for row in df_curry_pull_up.itertuples(): Time=getattr(row,'Time') D=getattr(row,'D') T=getattr(row,'T') ax1.plot(Time,D,'b-',alpha=0.1) #ax3.plot(Time,T,'b-',alpha=0.1) for row in df_curry_catch.itertuples(): Time=getattr(row,'Time') D=getattr(row,'D') T=getattr(row,'T') ax3.plot(Time,D,'b-',alpha=0.1) #ax3.plot(Time,T,'b-',alpha=0.1) for row in df_other_pull_up.itertuples(): Time=getattr(row,'Time') D=getattr(row,'D') T=getattr(row,'T') ax2.plot(Time,D,'r-',alpha=0.1) #ax2.plot(Time,T,'r-',alpha=0.1) for row in df_other_catch.itertuples(): Time=getattr(row,'Time') D=getattr(row,'D') T=getattr(row,'T') ax4.plot(Time,D,'r-',alpha=0.1) ax1.set_xlim((-3.2,0.8)) ax1.set_ylim((0,30)) sns.lineplot(x="Time", y='D', data=df_curry_mean[df_curry_mean['Shot type']=="pull-up 3P"],hue='Shot type',palette=['black'],ax=ax1,size_order=[60]) ax2.set_xlim((-3.2,0.8)) ax2.set_ylim((0,30)) sns.lineplot(x="Time", y='D', data=df_other_mean[df_other_mean['Shot type']=="pull-up 3P"],hue='Shot type',palette=['black'],ax=ax2,size_order=[60]) ax3.set_xlim((-3.2,0.8)) ax3.set_ylim((0,30)) sns.lineplot(x="Time", y='D', data=df_curry_mean[df_curry_mean['Shot type']=="catch-and-shoot 3P"],hue='Shot type',palette=['black'],ax=ax3,size_order=[60]) ax4.set_xlim((-3.2,0.8)) ax4.set_ylim((0,30)) sns.lineplot(x="Time", y='D', data=df_other_mean[df_other_mean['Shot type']=="catch-and-shoot 3P"],hue='Shot type',palette=['black'],ax=ax4,size_order=[60]) # In[213]: df_other_mean=df_plot_mean.query('player_id==203490').copy() def averaged_evolution_two_players(df_player1,df_player2,sd=None,hue=None,palette=['blue'],style=None,size=None): ## rename columns to have good labels ## df=pd.concat([df_player1,df_player2],ignore_index=True) df=df.rename(columns={"Time": "time [s]",'D':r'$<\delta_{d}^*(t)$> [feet]','T':r'$<\delta_{t}^*(t)$> [s]'}) ### plot ### ax = sns.lineplot(x="time [s]", y=r'$<\delta_{d}^*(t)$> [feet]', data=df,palette=palette,ci=sd,hue=hue,style=style,size=size) plt.axvline(0, color='black',linestyle="dashed",lw=0.5) plt.legend(loc='lower left',fontsize='small') plt.show() plt.clf() ax = sns.lineplot(x="time [s]", y=r'$<\delta_{t}^*(t)$> [s]', data=df,palette=palette,ci=sd,hue=hue,style=style,size=size) plt.axvline(0, color='black',linestyle="dashed",lw=0.5) plt.legend(loc='lower left',fontsize='small') #plt.savefig('Comparison_curry_t',dpi=72) plt.show() plt.clf() averaged_evolution_two_df(df_other_mean,df_curry_mean,sd=None,hue='Shot_type',palette=['blue','orange'],style='player_id') # ## Link between several attributes # ---- # In[5]: def d_reception(row): "Calculate distance of the closest player at ball reception" D=row['D'] Time=row['Time'] TTS=row['release_time'] if TTS<-3: return(D[0]) i=0 while i=len(D): return D[0] return D[i] def t_reception(row): "Calculate distance of the closest player at ball reception" T=row['T'] Time=row['Time'] TTS=row['release_time'] if TTS<-3: return(T[0]) i=0 while i=len(T): return T[0] return T[i] def d_release(row): "Calculate distance of the closest player at ball release" D=row['D'] Time=row['Time'] ind=Time.index(0.) return D[ind] def t_release(row): "Calculate distance of the closest player at ball release" T=row['T'] Time=row['Time'] ind=Time.index(0.) return T[ind] df_shots['d_release']=df_shots.apply(d_release,axis=1) df_shots['t_release']=df_shots.apply(t_release,axis=1) df_shots['d_reception']=df_shots.apply(d_reception,axis=1) df_shots['t_reception']=df_shots.apply(t_reception,axis=1) # In[58]: from scipy import stats g=sns.jointplot(x='d_reception',y='release_time', data=df_shots.query('Shot_type=="catch-and-shoot 3P" and d_reception<30'),kind='reg') g.annotate(stats.pearsonr) # In[165]: g = sns.JointGrid(x='d_reception',y='release_time', data=df_shots.query('player_id==203914 and Shot_type=="catch-and-shoot 3P"')) g.plot_joint(sns.regplot,color='blue') g.plot_marginals(sns.distplot,color='blue') #g.annotate(stats.pearsonr) g.x=df_shots.query('player_id==202691 and Shot_type=="catch-and-shoot 3P"')['d_reception'] g.y=df_shots.query('player_id==202691 and Shot_type=="catch-and-shoot 3P"')['release_time'] g.plot_joint(sns.regplot,color='red') g.plot_marginals(sns.distplot,color='red') #g.annotate(stats.pearsonr) g.ax_joint.set_xlim((0,25)) #df_shots.query('player_id==202691 and Shot_type=="catch-and-shoot 3P"').plot(x='d_reception',y='Time_to_shoot',alpha=0.7,kind='scatter',ax=ax) #df_shots.query('player_id==202331 and Shot_type=="catch-and-shoot 3P"').plot(x='d_reception',y='Time_to_shoot',alpha=0.7,kind='scatter',ax=ax,color='red') # In[249]: from scipy import stats g = sns.JointGrid(x='t_reception',y='release_time', data=df_shots.query('player_id==202691 and Shot_type=="catch-and-shoot 3P" and Shot_result==0')) g.plot_joint(sns.regplot,color='blue') g.plot_marginals(sns.distplot,color='blue') g.x=df_shots.query('player_id==202691 and Shot_type=="catch-and-shoot 3P" and Shot_result==1')['t_reception'] g.y=df_shots.query('player_id==202691 and Shot_type=="catch-and-shoot 3P" and Shot_result==1')['release_time'] g.plot_joint(sns.regplot,color='red') g.plot_marginals(sns.distplot,color='red') g.annotate(stats.pearsonr) #g.ax_joint.set_xlim((0,25)) # In[55]: fig,ax=plt.subplots(1,1,figsize=(10,10)) players=df_stats.query('total_cas>100').index df_shots_mean=df_shots.query('player_id in @players and Shot_type=="catch-and-shoot 3P"')[['player_id','release_time','d_reception','d_release']].groupby('player_id').mean() #df_plot_shots=df_shots_mean.join(df_stats.query('total_cas>100')) #df_plot_shots['player_id']=df_shots_mean.index #df_shots_mean.plot(x='d_reception',y='Time_to_shoot',kind='scatter',ax=ax) p=sns.scatterplot(x=df_shots.query('Shot_type=="catch-and-shoot 3P"')['d_reception'],y='d_release',palette="Set2", data=df_shots.query('Shot_type=="catch-and-shoot 3P"'),ax=ax,size='release_time',sizes=(20, 500),size_norm=(-1.5,0.5)) ax.axis('equal') ax.set_xlim((0,40)) ax.set_ylim((0,40)) #for line in range(df_plot_shots.shape[0]): # p.text(-df_plot_shots.iloc[line]['release_time'], df_plot_shots.iloc[line]['d_release'], df_plot_shots.iloc[line]['player_id'], horizontalalignment='center', verticalalignment='top',size='small', color='black', weight='semibold') # In[57]: g = sns.regplot(x='d_reception',y='d_release', data=df_shots.query('Shot_type=="catch-and-shoot 3P" and player_id==201939')) #g.plot_joint(sns.regplot) import scipy slope, intercept, r_value, p_value, std_err = scipy.stats.linregress(x=g.get_lines()[0].get_xdata(),y=g.get_lines()[0].get_ydata()) # In[59]: from scipy import stats #fig,ax=plt.subplots(1,1,figsize=(15,10)) players=df_stats.query('total_cas>100').index df_shots_mean=df_shots.query('player_id in @players and Shot_type=="catch-and-shoot 3P"')[['player_id','release_time','d_reception','d_release']].groupby('player_id').mean() #df_plot_shots=df_shots_mean.join(df_stats.query('total_cas>100')) #df_plot_shots['player_id']=df_shots_mean.index #df_shots_mean.plot(x='d_reception',y='Time_to_shoot',kind='scatter',ax=ax) #p=sns.scatterplot(x=df_shots.query('Shot_type=="catch-and-shoot 3P" and player_id==201939')['d_reception'],y='d_release',palette="Set2", data=df_shots.query('Shot_type=="catch-and-shoot 3P" and player_id==201939'),ax=ax,size='release_time',sizes=(20, 500),size_norm=(-1.5,0.5)) g = sns.JointGrid(x='d_reception',y='d_release', data=df_shots.query('Shot_type=="catch-and-shoot 3P" and player_id==201939'),height=10) g.plot_joint(sns.regplot,ci=None) #p=sns.regplot(x=df_shots.query('Shot_type=="catch-and-shoot 3P" and player_id==201939')['d_reception'],y='d_release', data=df_shots.query('Shot_type=="catch-and-shoot 3P" and player_id==201939'),ax=ax) g.annotate(stats.pearsonr) g.x=df_shots.query('Shot_type=="catch-and-shoot 3P" and player_id==203914')['d_reception'] g.y=df_shots.query('Shot_type=="catch-and-shoot 3P" and player_id==203914')['d_release'] g.plot_joint(sns.regplot,ci=None) g.annotate(stats.pearsonr) g.x=df_shots.query('Shot_type=="catch-and-shoot 3P" and player_id==201143')['d_reception'] g.y=df_shots.query('Shot_type=="catch-and-shoot 3P" and player_id==201143')['d_release'] g.plot_joint(sns.regplot,ci=None) #p=sns.scatterplot(x=df_shots.query('Shot_type=="catch-and-shoot 3P" and player_id==1718')['d_reception'],y='d_release',palette="Set2", data=df_shots.query('Shot_type=="catch-and-shoot 3P" and player_id==1718'),ax=ax,size='release_time',sizes=(20, 500),size_norm=(-1.5,0.5)) #for line in range(df_plot_shots.shape[0]): # p.text(-df_plot_shots.iloc[line]['release_time'], df_plot_shots.iloc[line]['d_release'], df_plot_shots.iloc[line]['player_id'], horizontalalignment='center', verticalalignment='top',size='small', color='black', weight='semibold') # In[265]: from scipy import stats g = sns.JointGrid(x='t_reception',y='release_time', data=df_shots.query('player_id==202691 and Shot_type=="catch-and-shoot 3P"')) g.plot_joint(sns.regplot,color='blue') g.plot_marginals(sns.distplot,color='blue') g.annotate(stats.pearsonr) # In[276]: g = sns.JointGrid(x='d_release',y='release_time', data=df_shots.query('player_id==202691 and Shot_type=="catch-and-shoot 3P"')) g.plot_joint(sns.regplot,color='blue') g.plot_marginals(sns.distplot,color='blue') g.annotate(stats.pearsonr) # In[61]: fig,ax=plt.subplots(1,1,figsize=(10,10)) p=sns.kdeplot(df_shots.query('player_id==203914 and Shot_type=="catch-and-shoot 3P"')['d_release'],df_shots.query('player_id==203914 and Shot_type=="catch-and-shoot 3P"')['release_time'],cmap="Blues") p=sns.kdeplot(df_shots.query('player_id==202691 and Shot_type=="catch-and-shoot 3P"')['d_release'],df_shots.query('player_id==202691 and Shot_type=="catch-and-shoot 3P"')['release_time'],cmap="Reds") p=sns.kdeplot(df_shots.query('player_id==200794 and Shot_type=="catch-and-shoot 3P"')['d_release'],df_shots.query('player_id==200794 and Shot_type=="catch-and-shoot 3P"')['release_time'],cmap="Greens") # In[62]: fig,ax=plt.subplots(1,1,figsize=(10,10)) p=sns.scatterplot(x='d_release',y='release_time', data=df_shots.query('Shot_type=="catch-and-shoot 3P"')) # In[63]: df_shots.query('Shot_type=="catch-and-shoot 3P"')['d_release'].mean() # In[64]: fig,ax=plt.subplots(1,1,figsize=(15,10)) players=df_stats.query('total_cas>100').index df_shots_mean=df_shots.query('player_id in @players and Shot_type=="catch-and-shoot 3P"')[['player_id','release_time','d_reception','d_release']].groupby('player_id').mean() df_plot_shots=df_shots_mean.join(df_stats.query('total_cas>100')) df_plot_shots['player_id']=df_shots_mean.index #df_shots_mean.plot(x='d_reception',y='Time_to_shoot',kind='scatter',ax=ax) p=sns.scatterplot(x='d_reception',y='d_release',palette="Set2", data=df_plot_shots,hue='player_id',ax=ax,size='release_time',sizes=(20, 500),size_norm=(-1.,-0.5)) # In[65]: fig,ax=plt.subplots(1,1,figsize=(15,10)) players=df_stats.query('total_cas>100').index df_shots_mean=df_shots.query('player_id in @players and Shot_type=="catch-and-shoot 3P"')[['player_id','release_time','d_reception','d_release']].groupby('player_id').mean() p=sns.scatterplot(x=df_shots.query('Shot_type=="catch-and-shoot 3P" and player_id==201939')['d_reception'],y='d_release',palette="RdBu", data=df_shots.query('Shot_type=="catch-and-shoot 3P" and player_id==201939'),ax=ax,hue='release_time') for line in range(df_shots.query('Shot_type=="catch-and-shoot 3P" and player_id==201939').shape[0]): p.text(df_shots.query('Shot_type=="catch-and-shoot 3P" and player_id==201939').iloc[line]['d_reception'], df_shots.query('Shot_type=="catch-and-shoot 3P" and player_id==201939').iloc[line]['d_release'], df_shots.query('Shot_type=="catch-and-shoot 3P" and player_id==201939').iloc[line]['shot_id'], horizontalalignment='center', verticalalignment='top',size='small', color='black', weight='semibold') # In[193]: fig,ax=plt.subplots(1,1,figsize=(15,10)) players=df_stats.query('total_cas>100').index df_shots_mean=df_shots.query('player_id in @players and Shot_type=="catch-and-shoot 3P"')[['player_id','release_time','d_reception','d_release']].groupby('player_id').mean() p=sns.scatterplot(x=df_shots.query('Shot_type=="catch-and-shoot 3P" and player_id==201939')['t_reception'],y='t_release',palette="Set2", data=df_shots.query('Shot_type=="catch-and-shoot 3P" and player_id==201939'),ax=ax,size='release_time',sizes=(20, 500),size_norm=(-1.5,-0.5)) for line in range(df_shots.query('Shot_type=="catch-and-shoot 3P" and player_id==201939').shape[0]): p.text(df_shots.query('Shot_type=="catch-and-shoot 3P" and player_id==201939').iloc[line]['t_reception'], df_shots.query('Shot_type=="catch-and-shoot 3P" and player_id==201939').iloc[line]['t_release'], df_shots.query('Shot_type=="catch-and-shoot 3P" and player_id==201939').iloc[line]['shot_id'], horizontalalignment='center', verticalalignment='top',size='small', color='black', weight='semibold') # In[66]: fig,ax=plt.subplots(1,1,figsize=(15,10)) players=df_stats.query('total_cas>100').index df_shots_mean=df_shots.query('player_id in @players and Shot_type=="catch-and-shoot 3P"')[['player_id','release_time','d_reception','d_release']].groupby('player_id').mean() p=sns.scatterplot(x=df_shots.query('Shot_type=="catch-and-shoot 3P" and player_id==201939')['t_reception'],y='release_time',palette="Set2", data=df_shots.query('Shot_type=="catch-and-shoot 3P" and player_id==201939'),ax=ax,size='release_time',sizes=(20, 500),size_norm=(-1.5,-0.5)) for line in range(df_shots.query('Shot_type=="catch-and-shoot 3P" and player_id==201939').shape[0]): p.text(df_shots.query('Shot_type=="catch-and-shoot 3P" and player_id==201939').iloc[line]['t_reception'], df_shots.query('Shot_type=="catch-and-shoot 3P" and player_id==201939').iloc[line]['release_time'], df_shots.query('Shot_type=="catch-and-shoot 3P" and player_id==201939').iloc[line]['shot_id'], horizontalalignment='center', verticalalignment='top',size='small', color='black', weight='semibold') # In[67]: fig,ax=plt.subplots(1,1,figsize=(15,10)) players=df_stats.query('total_cas>100').index df_shots_mean=df_shots.query('player_id in @players and Shot_type=="catch-and-shoot 3P"')[['player_id','release_time','d_reception','d_release','t_reception']].groupby('player_id').mean() p=sns.scatterplot(x=df_shots.query('Shot_type=="catch-and-shoot 3P" and player_id==202691')['d_reception'],y='d_release',palette="Set2", data=df_shots.query('Shot_type=="catch-and-shoot 3P" and player_id==202691'),ax=ax,size='release_time',sizes=(20, 500),size_norm=(-1.5,-0.5)) for line in range(df_shots.query('Shot_type=="catch-and-shoot 3P" and player_id==202691').shape[0]): p.text(df_shots.query('Shot_type=="catch-and-shoot 3P" and player_id==202691').iloc[line]['d_reception'], df_shots.query('Shot_type=="catch-and-shoot 3P" and player_id==202691').iloc[line]['d_release'], df_shots.query('Shot_type=="catch-and-shoot 3P" and player_id==202691').iloc[line]['shot_id'], horizontalalignment='center', verticalalignment='top',size='small', color='black', weight='semibold') # In[238]: fig,ax=plt.subplots(1,1,figsize=(15,10)) p=sns.scatterplot(x=df_shots.query('Shot_type=="catch-and-shoot 3P" and player_id==202691')['t_reception'],y='t_release',palette="Set2", data=df_shots.query('Shot_type=="catch-and-shoot 3P" and player_id==202691'),ax=ax,size='release_time',sizes=(20, 200),size_norm=(-1.5,-0.5)) for line in range(df_shots.query('Shot_type=="catch-and-shoot 3P" and player_id==202691').shape[0]): p.text(df_shots.query('Shot_type=="catch-and-shoot 3P" and player_id==202691').iloc[line]['t_reception'], df_shots.query('Shot_type=="catch-and-shoot 3P" and player_id==202691').iloc[line]['t_release'], df_shots.query('Shot_type=="catch-and-shoot 3P" and player_id==202691').iloc[line]['shot_id'], horizontalalignment='center', verticalalignment='top',size='small', color='black', weight='semibold') # In[68]: fig,ax=plt.subplots(1,1,figsize=(10,10)) p=sns.scatterplot(x=df_shots.query('Shot_type=="catch-and-shoot 3P" and player_id==202691')['t_reception'],y='d_release',palette="Set2", data=df_shots.query('Shot_type=="catch-and-shoot 3P" and player_id==202691'),ax=ax,size='release_time',sizes=(20, 200),size_norm=(-1.5,-0.5)) for line in range(df_shots.query('Shot_type=="catch-and-shoot 3P" and player_id==202691').shape[0]): p.text(df_shots.query('Shot_type=="catch-and-shoot 3P" and player_id==202691').iloc[line]['t_reception'], df_shots.query('Shot_type=="catch-and-shoot 3P" and player_id==202691').iloc[line]['d_release'], df_shots.query('Shot_type=="catch-and-shoot 3P" and player_id==202691').iloc[line]['shot_id'], horizontalalignment='center', verticalalignment='top',size='small', color='black', weight='semibold') # In[70]: g = sns.jointplot(x='d_reception',y='d_release', data=df_shots.query('Shot_type=="catch-and-shoot 3P"'),kind='hex',height=10,joint_kws=dict(gridsize=100)) g.ax_joint.set_xlim((0,25)) g.ax_joint.set_ylim((0,25)) g.ax_joint.plot([0, 1], [0, 1], transform=ax.transAxes) # In[71]: fig,axs=plt.subplots(3,3,sharex=True,sharey=True,figsize=(12,12)) players=[201939,202691,203914,200794,2594,977,202695,2747,203918] axs=[axs[0][0],axs[0][1],axs[0][2],axs[1][0],axs[1][1],axs[1][2],axs[2][0],axs[2][1],axs[2][2]] for k in range(len(players)): p=players[k] ax=axs[k] ax.set_xlim((0,25)) ax.set_ylim((0,25)) ax.plot([0, 1], [0, 1], transform=ax.transAxes,color='k',linestyle='--') df=df_shots.query('Shot_type=="catch-and-shoot 3P" and player_id==@p') #hb=ax.hexbin(df['d_reception'],df['d_release'],cmap='Blues',gridsize=50) #ax.scatter(df['d_reception'],df['d_release'],alpha=0.9) kd=sns.regplot(df['d_reception'],df['d_release'],ax=ax,color='blue') # In[72]: fig,axs=plt.subplots(3,3,sharex=True,sharey=True,figsize=(12,12)) players=[201939,202691,203914,200794,2594,977,202695,2747,203918] axs=[axs[0][0],axs[0][1],axs[0][2],axs[1][0],axs[1][1],axs[1][2],axs[2][0],axs[2][1],axs[2][2]] for k in range(len(players)): p=players[k] ax=axs[k] ax.set_xlim((0,25)) ax.set_ylim((0,25)) ax.axhline(7,color='k',linestyle='--') ax.plot([0, 1], [0, 1], transform=ax.transAxes,color='k',linestyle='--') df=df_shots.query('Shot_type=="catch-and-shoot 3P" and player_id==@p') #hb=ax.hexbin(df['d_reception'],df['d_release'],cmap='Blues',gridsize=50) #ax.scatter(df['d_reception'],df['d_release'],alpha=0.9) kd=sns.scatterplot(df['d_reception'],df['d_release'],ax=ax,hue=-df['release_time'],hue_norm=(0.3,1)) # In[352]: fig,axs=plt.subplots(3,3,sharex=True,sharey=True,figsize=(12,12)) players=[201939,202691,203914,200794,2594,977,202695,2747,203918] axs=[axs[0][0],axs[0][1],axs[0][2],axs[1][0],axs[1][1],axs[1][2],axs[2][0],axs[2][1],axs[2][2]] for k in range(len(players)): p=players[k] ax=axs[k] ax.axhline(0.5,color='k',linestyle='--') ax.plot([0, 1], [0, 1], transform=ax.transAxes,color='k',linestyle='--') df=df_shots.query('Shot_type=="catch-and-shoot 3P" and player_id==@p') #hb=ax.hexbin(df['d_reception'],df['d_release'],cmap='Blues',gridsize=50) #ax.scatter(df['d_reception'],df['d_release'],alpha=0.9) kd=sns.scatterplot(df['t_reception'],df['t_release'],ax=ax) # In[180]: fig,axs=plt.subplots(3,3,sharex=True,sharey=True,figsize=(12,12)) players=[201939,202691,201587,200794,2594,977,202695,2747,203918] axs=[axs[0][0],axs[0][1],axs[0][2],axs[1][0],axs[1][1],axs[1][2],axs[2][0],axs[2][1],axs[2][2]] for k in range(len(players)): p=players[k] ax=axs[k] ax.axhline(0.77,color='k',linestyle='--') #ax.plot([0, 1], [0, 1], transform=ax.transAxes,color='k',linestyle='--') df=df_shots.query('Shot_type=="catch-and-shoot 3P" and player_id==@p and btpl==True') #hb=ax.hexbin(df['d_reception'],df['d_release'],cmap='Blues',gridsize=50) #ax.scatter(df['d_reception'],df['d_release'],alpha=0.9) kd=sns.scatterplot(df['t_reception'],-df['release_time'],ax=ax,alpha=0.8) # In[69]: fig,axs=plt.subplots(3,3,sharex=True,sharey=True,figsize=(12,12)) players=[201939,202691,201587,200794,2594,977,202695,2747,203918] axs=[axs[0][0],axs[0][1],axs[0][2],axs[1][0],axs[1][1],axs[1][2],axs[2][0],axs[2][1],axs[2][2]] for k in range(len(players)): p=players[k] ax=axs[k] ax.axhline(7,color='k',linestyle='--') ax.axvline(0.73,color='k',linestyle='--') #ax.plot([0, 1], [0, 1], transform=ax.transAxes,color='k',linestyle='--') df=df_shots.query('Shot_type=="catch-and-shoot 3P" and player_id==@p and btpl==True') #hb=ax.hexbin(df['d_reception'],df['d_release'],cmap='Blues',gridsize=50) #ax.scatter(df['d_reception'],df['d_release'],alpha=0.9) kd=sns.scatterplot(-df['release_time'],df['d_release'],ax=ax,hue=df['d_reception'],hue_norm=(0,16),alpha=0.8) # In[70]: fig,axs=plt.subplots(3,3,sharex=True,sharey=True,figsize=(12,12)) players=[201939,202691,201587,200794,2594,977,202695,2747,203918] axs=[axs[0][0],axs[0][1],axs[0][2],axs[1][0],axs[1][1],axs[1][2],axs[2][0],axs[2][1],axs[2][2]] for k in range(len(players)): p=players[k] ax=axs[k] ax.axhline(7,color='k',linestyle='--') ax.axvline(0.68,color='k',linestyle='--') #ax.set_xlim((0,1.5)) #ax.plot([0, 1], [0, 1], transform=ax.transAxes,color='k',linestyle='--') df=df_shots.query('Shot_type=="catch-and-shoot 3P" and player_id==@p') #hb=ax.hexbin(df['d_reception'],df['d_release'],cmap='Blues',gridsize=50) #ax.scatter(df['d_reception'],df['d_release'],alpha=0.9) kd=sns.scatterplot(-df['release_time'],df['d_release'],ax=ax,hue=df['t_reception'],hue_norm=(0.3,1),alpha=0.8) # In[73]: fig,axs=plt.subplots(3,3,sharex=True,sharey=True,figsize=(12,12)) players=[201939,202691,200755,200794,2594,977,202695,2747,203918] axs=[axs[0][0],axs[0][1],axs[0][2],axs[1][0],axs[1][1],axs[1][2],axs[2][0],axs[2][1],axs[2][2]] for k in range(len(players)): p=players[k] ax=axs[k] ax.axhline(7,color='k',linestyle='--') ax.axvline(0.73,color='k',linestyle='--') #ax.plot([0, 1], [0, 1], transform=ax.transAxes,color='k',linestyle='--') df=df_shots.query('Shot_type=="catch-and-shoot 3P" and player_id==@p and btpl==True') #hb=ax.hexbin(df['d_reception'],df['d_release'],cmap='Blues',gridsize=50) #ax.scatter(df['d_reception'],df['d_release'],alpha=0.9) kd=sns.kdeplot(-df['release_time'],df['d_release'],ax=ax,n_levels=15) # In[185]: fig,axs=plt.subplots(3,3,sharex=True,sharey=True,figsize=(12,12)) players=[201939,202691,201587,200794,2594,977,202695,2747,203918] axs=[axs[0][0],axs[0][1],axs[0][2],axs[1][0],axs[1][1],axs[1][2],axs[2][0],axs[2][1],axs[2][2]] for k in range(len(players)): p=players[k] ax=axs[k] #ax.axhline(7,color='k',linestyle='--') #ax.axvline(0.73,color='k',linestyle='--') #ax.plot([0, 1], [0, 1], transform=ax.transAxes,color='k',linestyle='--') df=df_shots.query('Shot_type=="catch-and-shoot 3P" and player_id==@p and btpl==True') #hb=ax.hexbin(-df['release_time'],df['d_release'],cmap='Blues',gridsize=10,bins=10) ax.scatter(-df['release_time'],df['t_release'],alpha=0.9) #kd=sns.kdeplot(-df['release_time'],df['d_release'],ax=ax,n_levels=15) # In[386]: fig,axs=plt.subplots(3,3,sharex=True,sharey=True,figsize=(12,12)) players=[201939,202691,201587,200794,2594,977,202695,2747,203918] axs=[axs[0][0],axs[0][1],axs[0][2],axs[1][0],axs[1][1],axs[1][2],axs[2][0],axs[2][1],axs[2][2]] for k in range(len(players)): p=players[k] ax=axs[k] ax.axhline(0.5,color='k',linestyle='--') ax.axvline(0.73,color='k',linestyle='--') #ax.plot([0, 1], [0, 1], transform=ax.transAxes,color='k',linestyle='--') df=df_shots.query('Shot_type=="catch-and-shoot 3P" and player_id==@p') #hb=ax.hexbin(df['d_reception'],df['d_release'],cmap='Blues',gridsize=50) #ax.scatter(df['d_reception'],df['d_release'],alpha=0.9) kd=sns.scatterplot(-df['release_time'],df['t_release'],ax=ax,alpha=0.8) # In[380]: fig,axs=plt.subplots(3,3,sharex=True,sharey=True,figsize=(12,12)) players=[201939,202691,201587,200794,2594,977,202695,2747,203918] axs=[axs[0][0],axs[0][1],axs[0][2],axs[1][0],axs[1][1],axs[1][2],axs[2][0],axs[2][1],axs[2][2]] for k in range(len(players)): p=players[k] ax=axs[k] ax.set_xlim((0,2)) ax.set_ylim((0,20)) ax.axhline(7,color='k',linestyle='--') #ax.plot([0, 1], [0, 1], transform=ax.transAxes,color='k',linestyle='--') df=df_shots.query('Shot_type=="catch-and-shoot 3P" and player_id==@p') #hb=ax.hexbin(df['d_reception'],df['d_release'],cmap='Blues',gridsize=50) #ax.scatter(df['d_reception'],df['d_release'],alpha=0.9) kd=sns.regplot(df['t_reception'],df['d_release'],ax=ax,color='blue') # In[74]: fig,axs=plt.subplots(3,3,sharex=True,sharey=True,figsize=(12,12)) players=[201939,202691,201587,200794,2594,977,202695,2747,203918] axs=[axs[0][0],axs[0][1],axs[0][2],axs[1][0],axs[1][1],axs[1][2],axs[2][0],axs[2][1],axs[2][2]] for k in range(len(players)): p=players[k] ax=axs[k] ax.set_xlim((0,1.5)) #ax.set_ylim((0,20)) #ax.axhline(7,color='k',linestyle='--') #ax.plot([0, 1], [0, 1], transform=ax.transAxes,color='k',linestyle='--') df=df_shots.query('Shot_type=="catch-and-shoot 3P" and player_id==@p and btpl==True') #hb=ax.hexbin(df['d_reception'],df['d_release'],cmap='Blues',gridsize=50) #ax.scatter(df['d_reception'],df['d_release'],alpha=0.9) kd=sns.regplot(df['t_reception'],-df['release_time'],ax=ax,color='blue') # In[75]: fig,axs=plt.subplots(3,3,sharex=True,sharey=True,figsize=(12,12)) players=[201939,202691,201587,200794,2594,977,202695,2747,203918] axs=[axs[0][0],axs[0][1],axs[0][2],axs[1][0],axs[1][1],axs[1][2],axs[2][0],axs[2][1],axs[2][2]] for k in range(len(players)): p=players[k] ax=axs[k] ax.set_xlim((0,20)) #ax.set_ylim((0,20)) #ax.axhline(7,color='k',linestyle='--') #ax.plot([0, 1], [0, 1], transform=ax.transAxes,color='k',linestyle='--') df=df_shots.query('Shot_type=="catch-and-shoot 3P" and player_id==@p and btpl==True') #hb=ax.hexbin(df['d_reception'],df['d_release'],cmap='Blues',gridsize=50) #ax.scatter(df['d_reception'],df['d_release'],alpha=0.9) kd=sns.regplot(df['d_reception'],-df['release_time'],ax=ax,color='blue') # In[76]: fig,ax=plt.subplots(1,1,figsize=(10,10)) ax.axhline(7,color='k',linestyle='--') ax.axvline(0.68,color='k',linestyle='--') df=df_shots.query('Shot_type=="catch-and-shoot 3P" and btpl==True')[['d_release','d_reception','t_reception','release_time']] #hb=ax.hexbin(-df['release_time'],df['d_release'],cmap='Blues',gridsize=20) ax.scatter(-df['release_time'],df['d_release'],cmap='Blues',alpha=0.05) hb=sns.kdeplot(-df['release_time'],df['d_release']) # In[27]: fig,axs=plt.subplots(4,4,sharex=True,sharey=True,figsize=(10,10)) #players=[203490,2594,977,201569,202325,101123,1626156,101141,1717,202695,200755,202691,201939,200768,201142,202083] #axs=[axs[0][0],axs[0][1],axs[0][2],axs[1][0],axs[1][1],axs[1][2],axs[2][0],axs[2][1],axs[2][2]] for k in range(len(players)): p=players[k] ax=axs[k//4][k%4] ax.set_xlim((0,1.5)) #ax.set_ylim((0,20)) ax.axhline(0.68,color='k',linestyle='--') ax.axvline(0.68,color='k',linestyle='--') ax.set_xticks([0,0.2,0.4,0.6,0.8,1,1.2,1.4]) #ax.plot([0, 1], [0, 1], transform=ax.transAxes,color='k',linestyle='--') df=df_shots.query('Shot_type=="catch-and-shoot 3P" and player_id==@p and btpl==True') #hb=ax.hexbin(df['d_reception'],df['d_release'],cmap='Blues',gridsize=50) #ax.scatter(df['d_reception'],df['d_release'],alpha=0.9) kd=sns.regplot(df['t_reception'],-df['release_time'],ax=ax,color='blue',scatter_kws={'alpha':0.5}) if k%4==0: if k//4!=3: ax.xaxis.set_visible(False) ax.set_ylabel('release time [s]',fontsize='large') else: ax.set_xlabel(r'$\delta_{time}^*(t_{catch})$ [s]',fontsize='large') ax.set_ylabel('release time [s]',fontsize='large') else : if k//4!=3: ax.xaxis.set_visible(False) ax.yaxis.set_visible(False) else : ax.yaxis.set_visible(False) ax.set_xlabel(r'$\delta_{time}^*(t_{catch})$ [s]',fontsize='large') ax.set_title(info_players.loc[p]['lastName']+' '+str(df_stats.loc[p]['percentage_cas'])+'%') plt.tight_layout() plt.savefig('images/t_recep_release.jpg',dpi=150) # In[11]: fig,axs=plt.subplots(4,4,sharex=True,sharey=True,figsize=(10,10)) #players=[203490,2594,977,201569,202325,101123,1626156,101141,1717,202695,200755,202691,201939,200768,201142,202083] #axs=[axs[0][0],axs[0][1],axs[0][2],axs[1][0],axs[1][1],axs[1][2],axs[2][0],axs[2][1],axs[2][2]] for k in range(len(players)): p=players[k] ax=axs[k//4][k%4] ax.set_xlim((0,1.5)) #ax.set_ylim((0,20)) ax.axhline(0.68,color='k',linestyle='--') ax.axvline(0.68,color='k',linestyle='--') ax.set_xticks([0,0.2,0.4,0.6,0.8,1,1.2,1.4]) #ax.plot([0, 1], [0, 1], transform=ax.transAxes,color='k',linestyle='--') df=df_shots.query('Shot_type=="catch-and-shoot 3P" and player_id==@p and btpl==True') #hb=ax.hexbin(df['d_reception'],df['d_release'],cmap='Blues',gridsize=50) #ax.scatter(df['d_reception'],df['d_release'],alpha=0.9) kd=sns.regplot(df['t_reception'],-df['release_time'],ax=ax,color='blue',scatter_kws={'alpha':0.5}) if k%4==0: if k//4!=3: ax.xaxis.set_visible(False) ax.set_ylabel('release time [s]',fontsize='large') else: ax.set_xlabel(r'$\delta_{time}^*(t_{catch})$ [s]',fontsize='large') ax.set_ylabel('release time [s]',fontsize='large') else : if k//4!=3: ax.xaxis.set_visible(False) ax.yaxis.set_visible(False) else : ax.yaxis.set_visible(False) ax.set_xlabel(r'$\delta_{time}^*(t_{catch})$ [s]',fontsize='large') ax.set_title(info_players.loc[p]['lastName']+' '+str(df_stats.loc[p]['percentage_cas'])+'%') plt.tight_layout() plt.savefig('images/t_recep_release.jpg',dpi=150) # In[149]: fig,axs=plt.subplots(4,4,sharex=True,sharey=True,figsize=(12,12)) #players=[203490,2594,977,201569,202325,101123,1626156,101141,1717,202695,200755,202691,201939,200768,201142,202083] #axs=[axs[0][0],axs[0][1],axs[0][2],axs[1][0],axs[1][1],axs[1][2],axs[2][0],axs[2][1],axs[2][2]] for k in range(len(players)): p=players[k] ax=axs[k//4][k%4] ax.set_xlim((0,1.5)) ax.axhline(7,color='k',linestyle='--') ax.axvline(0.68,color='k',linestyle='--') #ax.set_ylim((0,20)) #ax.axhline(7,color='k',linestyle='--') #ax.plot([0, 1], [0, 1], transform=ax.transAxes,color='k',linestyle='--') df=df_shots.query('Shot_type=="catch-and-shoot 3P" and player_id==@p and btpl==True') #hb=ax.hexbin(df['d_reception'],df['d_release'],cmap='Blues',gridsize=50) #ax.scatter(df['d_reception'],df['d_release'],alpha=0.9) kd=sns.regplot(df['t_reception'],df['d_release'],ax=ax,color='blue') # In[79]: fig,axs=plt.subplots(4,4,sharex=True,sharey=True,figsize=(10,10)) #players=[203490,2594,977,201569,202325,101123,1626156,101141,1717,202695,200755,202691,201939,200768,201142,202083] #axs=[axs[0][0],axs[0][1],axs[0][2],axs[1][0],axs[1][1],axs[1][2],axs[2][0],axs[2][1],axs[2][2]] for k in range(len(players)): p=players[k] ax=axs[k//4][k%4] ax.set_xlim((0,1.5)) ax.set_ylim((0,16)) ax.axhline(2,color='k',linestyle='--',linewidth=0.4) ax.axhline(4,color='k',linestyle='--',linewidth=0.4) ax.axhline(6,color='k',linestyle='--') ax.axvline(0.68,color='k',linestyle='--') ax.set_yticks([0,2,4,6,8,10,12,14,16,18,20]) #ax.plot([0, 1], [0, 1], transform=ax.transAxes,color='k',linestyle='--') df=df_shots.query('Shot_type=="catch-and-shoot 3P" and player_id==@p and btpl==True') #kd=sns.kdeplot(-df['release_time'],df['d_release'],ax=ax,n_levels=12) sc=sns.scatterplot(-df['release_time'],df['d_release'],ax=ax,alpha=0.5,hue=df['Shot_result'],palette=['red','blue'],legend=False) #kd=sns.regplot(-df['release_time'],df['d_release'],ax=ax,color='blue') #hb=ax.hexbin(-df['release_time'],df['d_release'],cmap='Blues',gridsize=10) if k%4==0: if k//4!=3: ax.xaxis.set_visible(False) ax.set_ylabel(r'$\delta_{space}^*(t=t_{shot})$ [feet]',fontsize='large') else: ax.set_xlabel('release time [s]',fontsize='large') ax.set_ylabel(r'$\delta_{space}^*(t=t_{shot})$ [feet]',fontsize='large') else : if k//4!=3: ax.xaxis.set_visible(False) ax.yaxis.set_visible(False) else : ax.yaxis.set_visible(False) ax.set_ylim((0,16)) ax.set_xlabel('release time [s]',fontsize='large') ax.set_title(info_players.loc[p]['lastName']+' '+str(df_stats.loc[p]['percentage_cas'])+'%') plt.tight_layout() # In[12]: fig,axs=plt.subplots(4,4,sharex=True,sharey=True,figsize=(12,12)) #players=[203490,2594,977,201569,202325,101123,1626156,101141,1717,202695,200755,202691,201939,200768,201142,202083] #axs=[axs[0][0],axs[0][1],axs[0][2],axs[1][0],axs[1][1],axs[1][2],axs[2][0],axs[2][1],axs[2][2]] for k in range(len(players)): p=players[k] ax=axs[k//4][k%4] ax.set_xlim((0,1.5)) ax.set_ylim((0,20)) ax.axhline(7,color='k',linestyle='--') ax.axvline(0.68,color='k',linestyle='--') #ax.plot([0, 1], [0, 1], transform=ax.transAxes,color='k',linestyle='--') df=df_shots.query('Shot_type=="catch-and-shoot 3P" and player_id==@p and btpl==True') kd=sns.scatterplot(-df['release_time'],df['d_release'],ax=ax,alpha=0.5) #kd=sns.regplot(-df['release_time'],df['d_release'],ax=ax,color='blue') # In[66]: players=[203490,2594,977,201569,202325,101123,1626156,101141,1717,202695,200755,202691,201939,200768,201142,202083] players=df_stats.loc[players].sort_values('percentage_cas',ascending=False).index.tolist() # In[123]: df_stats.query('total_cas>100').sort_values(by='percentage_cas',ascending=True).head() # In[203]: print(df_shots.query('Shot_type=="catch-and-shoot 3P"')['release_time'].median()) print(df_shots.query('Shot_type=="catch-and-shoot 3P"')['t_reception'].median()) df_shots.query('Shot_type=="catch-and-shoot 3P"')['d_release'].median() # ## Look at opponent angle # ---- # In[239]: def unit_vector(vector): """ Returns the unit vector of the vector. """ return vector / np.linalg.norm(vector) def angle_between(v1, v2): """ Returns the angle in radians between vectors 'v1' and 'v2':: >>> angle_between((1, 0, 0), (0, 1, 0)) 1.5707963267948966 >>> angle_between((1, 0, 0), (1, 0, 0)) 0.0 >>> angle_between((1, 0, 0), (-1, 0, 0)) 3.141592653589793 """ v1_u = unit_vector(v1) v2_u = unit_vector(v2) return np.rad2deg(np.arccos(np.clip(np.dot(v1_u, v2_u), -1.0, 1.0))) def opponent_angle(row): opp_pos=row['opp_position_release'] player_pos=row['player_position_release'] if player_pos[0]>94//2: basket_pos=[94-5.25,25] else : basket_pos=[5.25,25] v1=[basket_pos[0]-player_pos[0],basket_pos[1]-player_pos[1]] v2=[opp_pos[0]-player_pos[0],opp_pos[1]-player_pos[1]] return(angle_between(v1,v2)) df_shots['opp_angle']=df_shots.apply(opponent_angle,axis=1) # In[244]: sns.kdeplot(df_shots.query('player_id==202691')['opp_angle']) # ## Plot distance closest defender # ---- # In[29]: def opp_position_release(row): Time=row['Time'] ind=Time.index(0.) return(row['opp_pos'][ind]) def player_position_release(row): Time=row['Time'] ind=Time.index(0.) return(row['shooter_pos'][ind]) df_shots['opp_position_release']=df_shots.apply(opp_position_release,axis=1) df_shots['player_position_release']=df_shots.apply(player_position_release,axis=1) # In[40]: def distance(a,b): #a = (x,y) point de départ ; b = (i,j) point d'arrivée ; v = norme pour l'instant return np.sqrt((a[0]-b[0])**2+(a[1]-b[1])**2) def behind_three_point_line(row): p=row['player_position_release'] x_ball=row['x_ball'] if x_ball[-1]>94/2: where=0 else : where=1 coin=False if where==1 : basket_pos=[5.25,25] if p[0]<15: coin=True else : basket_pos=[94-5.25,25] if p[0]>(94-15): coin=True if coin : if 023.5 : #In fact 23.75 but we take a marge to have all shoots return (True) else: return (False) df_shots['btpl']=df_shots.apply(behind_three_point_line,axis=1) # In[73]: print(len(df_shots),len(df_shots.query('btpl==True'))) m1=df_shots.query('btpl==True and Shot_type=="catch-and-shoot 3P"').groupby('Shot_result').count().loc[0,'D'] s1=df_shots.query('btpl==True and Shot_type=="catch-and-shoot 3P"').groupby('Shot_result').count().loc[1,'D'] m2=df_shots.groupby('Shot_result').count().loc[0,'D'] s2=df_shots.groupby('Shot_result').count().loc[1,'D'] print(s1/(s1+m1),s2/(s2+m2)) print(len(df_shots.query('Shot_type=="catch-and-shoot 3P"'))/len(df_shots)*100) print(len(df_shots.query('Shot_type=="catch-and-shoot 3P" and btpl==True'))/len(df_shots.query("btpl==True"))*100) # In[41]: fig,ax=plt.subplots(1,1,figsize=(6,6)) df=df_shots.query('player_id==201939 and btpl==True') for i in range(len(df)): x1=df.iloc[i]['player_position_release'][0] x2=df.iloc[i]['opp_position_release'][0] y1=50-df.iloc[i]['player_position_release'][1] y2=50-df.iloc[i]['opp_position_release'][1] if x1>94/2: x1=94-x1 x2=94-x2 y1=50-y1 y2=50-y2 if i!=len(df)-1: plt.plot([x1,x2],[y1,y2],'k',alpha=0.6) if df.iloc[i]['Shot_result']==1: plt.plot(x1,y1,'bo',alpha=0.6) else: plt.plot(x1,y1,'ro',alpha=0.6) else : plt.plot([x1,x2],[y1,y2],'k',alpha=0.6,label='distance closest defender') if df.iloc[i]['Shot_result']==1: plt.plot(x1,y1,'bo',alpha=0.6,label='success') else: plt.plot(x1,y1,'ro',alpha=0.6,label='miss') #plt.legend() field = plt.imread("Images/fullcourt1.png") plt.imshow(field, extent=[0,50,0,50]) plt.axis('off') # In[46]: df=df_shots.query('player_id==201939') for i in range(len(df)): x1=df.iloc[i]['player_position_release'][0] x2=df.iloc[i]['opp_position_release'][0] y1=df.iloc[i]['player_position_release'][1] y2=df.iloc[i]['opp_position_release'][1] plt.plot([x1,x2],[y1,y2]) plt.plot(x1,y1,'o') # ## Study of ball trajectory # ----- # # In[10]: import matplotlib.pyplot as plt from scipy.optimize import curve_fit import numpy as np # In[8]: def distance_to_basket(row): z_ball=row['z_ball'] x_ball=row['x_ball'] y_ball=row['y_ball'] if x_ball[-1]>94//2: basket_pos=[94-5.25,25] else : basket_pos=[5.25,25] d_basket=[] for k in range(len(x_ball)): d_basket.append(-np.sqrt((x_ball[k]-basket_pos[0])**2+(y_ball[k]-basket_pos[1])**2)) return(d_basket) def shoot_traj(df_traj,i): z_ball=df_traj.query('shot_id==@i')['z_ball'].iloc[0] d_basket=df_traj.query('shot_id==@i')['d_basket'].iloc[0] fig,(ax1,ax2)=plt.subplots(1,2,figsize=(15,5)) ax1.plot(df_traj.query('shot_id==@i')['Time'].iloc[0],z_ball) ax2.plot(df_traj.query('shot_id==@i')['d_basket'].iloc[0],z_ball) #plt.axvline(-22, color='black',linestyle="dashed",lw=0.5) #plt.axvline(-23.75, color='black',linestyle="dashed",lw=0.5) #ax1.set_ylim((0,100)) plt.show() df_shots['d_basket']=df_shots.apply(distance_to_basket,axis=1) # In[5]: shoot_traj(df_shots,401) # In[11]: def z_angle(row): z_ball=row['z_ball'] d_basket=row['d_basket'] angle=[] for k in range(len(d_basket)-1): z1=z_ball[k] z2=z_ball[k+1] d1=d_basket[k] d2=d_basket[k+1] if (d2-d1)<=0: angle.append(np.degrees(np.arctan((z2-z1)/(d2-d1)))+180) else : if (z2-z1)<=0: angle.append(np.degrees(np.arctan((z2-z1)/(d2-d1)))+360) else: angle.append(np.degrees(np.arctan((z2-z1)/(d2-d1)))) return(angle) df_shots['angle']=df_shots.apply(z_angle,axis=1) # In[4]: def traj(x, velocity, angle, h, g=9.8): angle = np.deg2rad(angle) lhs = x * np.tan(angle) rhs_top = g * x ** 2 rhs_bottom = (2*(velocity)**2) * (np.cos(angle)**2) return h+lhs - (rhs_top / rhs_bottom) # In[376]: import matplotlib.pyplot as plt from scipy.optimize import curve_fit import numpy as np def test(df_traj): n=0 s=11 print(len(df_traj.query('precise_angle<30'))) Time=df_traj.query('precise_angle<30').iloc[s]['Time'] time_end=-1 z_ball=df_traj.query('precise_angle<30').iloc[s]['z_ball'] angle=df_traj.query('precise_angle<30').iloc[s]['angle'] time_start=z_ball.index(max(z_ball)) time_start-=1 print(time_start,z_ball[time_start]) while z_ball[time_start]>8.2 and (3012: time_end+=1 time_end-=1 #while time_startangle[time_start] or angle[time_start]>70): # time_start+=1 print(time_start) #time_start-=6 #time_start=0 z1=df_traj.query('precise_angle<30').iloc[s]['z_ball'][time_start:time_end] x1=np.array(df_traj.query('precise_angle<30').iloc[s]['d_basket'][time_start:time_end]) x1=x1-x1[0] #print(Time[time_start]) plt.plot(x1, z1, 'b-', label='data') popt, pcov = curve_fit(traj, x1, z1, p0=[19,45,8]) plt.plot(x1, traj(x1, *popt), 'r-', label='fit: a=%5.3f, b=%5.3f, c=%5.3f' % tuple(popt)) #print(df_shots.query('precise_angle_bis>70').iloc[s]['angle'][time_start]) print(popt[1]%90) print(angle[time_start]) print(len(x1)) #print(df_traj.query('precise_angle>70').iloc[s][['shot_id','Match_id','quarter','clock']]) test(df_shots) # In[452]: sns.kdeplot(df_shots['precise_angle']) sns.kdeplot(df_shots.query('player_id==201939')['precise_angle']) # ### Angle and distance to basket # In[243]: def release_d_basket(row): x=row['x_shooter'] y=row['y_shooter'] x_ball=row['x_ball'] if x_ball[-1]>94//2: basket_pos=[94-5.25,25] else : basket_pos=[5.25,25] return(np.sqrt((x-basket_pos[0])**2+(y-basket_pos[1])**2)) df_shots['release_d_basket']=df_shots.apply(release_d_basket,axis=1) # In[384]: g=sns.jointplot(x='release_d_basket',y='precise_angle', data=df_shots.query('2530').index df_shots_mean=df_shots.query('player_id in @players')[['player_id','precise_angle']].groupby('player_id').mean() print(df_shots.query('player_id in @players')[['player_id','precise_angle']].mean()) df_plot_shots=df_shots_mean.join(df_stats.query('total>30')) df_plot_shots['player_id']=df_shots_mean.index #df_shots_mean.plot(x='d_reception',y='Time_to_shoot',kind='scatter',ax=ax) p=sns.scatterplot(x='precise_angle',y='percentage',palette="Set2", data=df_plot_shots,hue='player_id',ax=ax) for line in range(df_plot_shots.shape[0]): p.text(df_plot_shots.iloc[line]['precise_angle'], df_plot_shots.iloc[line]['percentage'], df_plot_shots.iloc[line]['player_id'], horizontalalignment='center', verticalalignment='top',size='small', color='black', weight='semibold') slope, intercept, r_value, p_value, std_err = stats.linregress(df_plot_shots['precise_angle'], df_plot_shots['percentage']) print('R^2 : ',r_value**2) # In[436]: fig,ax=plt.subplots(1,1,figsize=(15,10)) players=df_stats.query('total>30').index df_shots_mean=df_shots.query('player_id in @players')[['player_id','precise_angle','d_closest_release']].groupby('player_id').mean() print(df_shots.query('player_id in @players')[['player_id','precise_angle','d_closest_release']].mean()) df_plot_shots=df_shots_mean.join(df_stats.query('total>30')) df_plot_shots['player_id']=df_shots_mean.index #df_shots_mean.plot(x='d_reception',y='Time_to_shoot',kind='scatter',ax=ax) p=sns.scatterplot(x='precise_angle',y='d_closest_release',palette="Set2", data=df_plot_shots,hue='player_id',ax=ax) for line in range(df_plot_shots.shape[0]): p.text(df_plot_shots.iloc[line]['precise_angle'], df_plot_shots.iloc[line]['d_closest_release'], df_plot_shots.iloc[line]['player_id'], horizontalalignment='center', verticalalignment='top',size='small', color='black', weight='semibold') slope, intercept, r_value, p_value, std_err = stats.linregress(df_plot_shots['precise_angle'], df_plot_shots['d_closest_release']) print('R^2 : ',r_value**2) # In[439]: g = sns.JointGrid(x='precise_angle',y='d_closest_release', data=df_shots.query('player_id==202695')) g.plot_joint(sns.scatterplot,color='blue',alpha=0.6) g.plot_marginals(sns.distplot,color='blue') g.x=df_shots.query('player_id==201939')['precise_angle'] g.y=df_shots.query('player_id==201939')['d_closest_release'] g.plot_joint(sns.scatterplot,color='red',alpha=0.6) g.plot_marginals(sns.distplot,color='red') g.ax_joint.set_xlim((40,60)) # ## Classify shots # ---- # In[161]: from sklearn.cluster import KMeans from sklearn.cluster import AgglomerativeClustering from scipy.cluster.hierarchy import linkage # In[372]: df_shots_catch=df_shots.query('Shot_type=="catch-and-shoot 3P"') def prepare_df_kmean_T(row): T=row['T'] Time=row['Time'] ind=Time.index(0.) if ind-75>0: if ind+200: if ind+20 [feet]','T':r'$<\delta_{t}^*(t)$> [s]'}) ax = sns.lineplot(x="time [s]", y=r'$<\delta_{d}^*(t)$> [feet]', data=df2,palette=palette,ci=sd,hue=hue,style=style,size=size,label='pull-up') plt.plot(Time[1:-4],c[0],color='orange',linestyle='-',label='catch-and-shoot 1') plt.plot(Time[1:-4],c[1],color='orange',linestyle='--',label='catch-and-shoot 2') plt.axvline(0, color='black',linestyle="dashed",lw=0.5) plt.legend(loc='lower left',fontsize=fontsize) plt.annotate('shot time',(-0.37,12.5)) newax = fig.add_axes([0.63, 0.65, 0.2, 0.2], anchor='NE', zorder=1) newax.imshow(im) newax.axis('off') plt.show() plt.clf() im = plt.imread(get_sample_data('/Users/gabin/Ordinateur/Documents/CENTRALE_LYON_1A/PaR/bakset-image.png')) ### plot ### fig,ax=plt.subplots(1,1,figsize=(4.5,3)) ax = sns.lineplot(x="time [s]", y=r'$<\delta_{t}^*(t)$> [s]', data=df2,palette=palette,ci=sd,hue=hue,style=style,size=size,label='pull-up') plt.plot(Time[1:-4],c[0],color='orange',linestyle='-',label='catch-and-shoot 1') plt.plot(Time[1:-4],c[1],color='orange',linestyle='--',label='catch-and-shoot 2') plt.axvline(0, color='black',linestyle="dashed",lw=0.5) plt.legend(loc='lower left',fontsize=fontsize) plt.annotate('shot time',(-0.37,0.84)) newax = fig.add_axes([0.63, 0.65, 0.2, 0.2], anchor='NE', zorder=1) newax.imshow(im) newax.axis('off') plt.show() plt.clf() # In[312]: 4.5*4/6 # In[350]: kmean_ev(df_plot_mean.query('Shot_type=="pull-up 3P"'),c,Time,sd=None,hue=None,palette=['blue'],style=None,fontsize='medium',size=None) # In[302]: kmean_ev(df_plot_mean.query('Shot_type=="pull-up 3P"'),c,Time,sd=None,hue=None,palette=['blue'],style=None,fontsize='medium',size=None) # ## Free space evolution for 50 randomly chosen shots # ---- # In[591]: import random as rd catch=[] pull=[] for k in range(50): s=rd.randint(0,17000) df=df_shots.iloc[s] if df['Shot_type']=="catch-and-shoot 3P": catch.append(s) plt.plot(df['Time'],df['D'],c='orange',alpha=0.3) else: pull.append(s) plt.plot(df['Time'],df['D'],c='blue',alpha=0.2) plt.xlim((-3.2,1)) # In[559]: def running_mean(x, N): cumsum = np.cumsum(np.insert(x, 0, 0)) return (cumsum[N:] - cumsum[:-N]) / N # In[548]: fig,ax=plt.subplots(1,1,figsize=(4.5,3)) for c in catch[:-1]: df=df_shots.iloc[c] plt.plot(df['Time'],df['D'],c='orange',alpha=0.3) for c in pull[:-1]: df=df_shots.iloc[c] plt.plot(df['Time'],df['D'],c='blue',alpha=0.2) df=df_shots.iloc[catch[-1]] plt.plot(df['Time'],df['D'],c='orange',alpha=0.3,label="catch-and-shoot") df=df_shots.iloc[pull[-1]] plt.plot(df['Time'],df['D'],c='blue',alpha=0.2,label="pull") plt.xlabel("time [s]") plt.ylabel(r'$\delta_{d}^*(t)$ [feet]') plt.legend(loc='upper center') plt.axvline(0, color='black',linestyle="dashed",lw=0.5) plt.xlim((-3.2,1)) im = plt.imread(get_sample_data('/Users/gabin/Ordinateur/Documents/CENTRALE_LYON_1A/PaR/bakset-image.png')) plt.annotate('shot time',(-0.37,16)) newax = fig.add_axes([0.63, 0.65, 0.2, 0.2], anchor='NE', zorder=1) newax.imshow(im) newax.axis('off') # In[549]: fig,ax=plt.subplots(1,1,figsize=(4.5,3)) for c in catch[:-1]: df=df_shots.iloc[c] T=running_mean(df['T'],3) plt.plot(df['Time'][:-2],T,c='orange',alpha=0.3) for c in pull[:-1]: df=df_shots.iloc[c] T=running_mean(df['T'],3) plt.plot(df['Time'][:-2],T,c='blue',alpha=0.2) df=df_shots.iloc[catch[-1]] plt.plot(df['Time'],df['T'],c='orange',alpha=0.3,label="catch-and-shoot") df=df_shots.iloc[pull[-1]] plt.plot(df['Time'],df['T'],c='blue',alpha=0.2,label="pull") plt.legend(loc='upper center') plt.xlabel("time [s]") plt.ylabel(r'$\delta_{t}^*(t)$ [s]') plt.axvline(0, color='black',linestyle="dashed",lw=0.5) plt.xlim((-3.2,1)) im = plt.imread(get_sample_data('/Users/gabin/Ordinateur/Documents/CENTRALE_LYON_1A/PaR/bakset-image.png')) plt.annotate('shot time',(-0.37,1.05)) newax = fig.add_axes([0.63, 0.65, 0.2, 0.2], anchor='NE', zorder=1) newax.imshow(im) newax.axis('off') # ## *Free space* and 3P performance # ------ # # We want to quantify the following intuition : "the more free a shooter is, the more efficient he is". To do so, we evaluate 3-point efficiency function of the distance (and time) within the opponent defender is. # In[24]: t_abs=[0.15]+[0.1*(i+3) for i in range(12)] inferior_abs=[] fig,ax=plt.subplots(1,1,figsize=(4.5,3)) for d in t_abs: l=[7641,14919] m=df_shots.query("t_release<@d and btpl==True and shot_id not in @l").groupby('Shot_result').count().loc[0,'D'] s=df_shots.query("t_release<@d and btpl==True and shot_id not in @l").groupby('Shot_result').count().loc[1,'D'] #print(m,s,s/(s+m)) #print(m+s) inferior_abs.append(s/(s+m)*100) plt.vlines(t_abs[3], inferior_abs[0], inferior_abs[3], linestyle="dashed",lw=0.5) plt.hlines(inferior_abs[3], t_abs[0], t_abs[3], linestyle="dashed",lw=0.5) plt.axhline(34.7,linestyle="dashed",lw=0.5,color='red',label='average shooting percentage') plt.xlim((0.15,1.25)) plt.ylim((min(inferior_abs),37)) plt.xlabel(r'$\delta_{time}^*(0)$ inferior to [s]') plt.ylabel(r'3-point shooting percentage') plt.legend() plt.plot(t_abs,inferior_abs) print(inferior_abs[4]) # In[23]: fig,ax=plt.subplots(1,1,figsize=(4.5,3)) d_abs=[1*(i+1) for i in range(16)] inferior_abs=[] for d in d_abs: l=[7641,14919] #if d==2: # print(df_shots.query("1