def parse_ids(season_id, game_id, images): # pull common variables from the parameters file charts_units_lines = parameters.charts_units_lines files_root = parameters.files_root # generate date and team information schedule_csv = files_root + season_id + "_schedule.csv" schedule_df = pd.read_csv(schedule_csv) schedule_date = schedule_df[(schedule_df['GAME_ID'] == int(game_id))] date = schedule_date['DATE'].item() home = schedule_date['HOME'].item() away = schedule_date['AWAY'].item() teams = [away, home] # create variables that point to the .csv processed stats files for lines lines_file = files_root + 'stats_units_lines_onice.csv' # create dataframe objects that read in info from the .csv files lines_df = pd.read_csv(lines_file) max_toi = lines_df['TOI'].max() # choose colors for each team; set them in a list; generate a custom colormap for each team away_color = dict_team_colors.team_color_1st[away] home_color = dict_team_colors.team_color_1st[home] # change one team's color from its primary option to, depending on the opponent, either a second, third or fourth option try: away_color = mod_switch_colors.switch_team_colors(away, home)[0] home_color = mod_switch_colors.switch_team_colors(away, home)[1] except: pass team_colors = [away_color, home_color] away_cmap = clr.LinearSegmentedColormap.from_list('custom away', [(0, '#ffffff'), (1, away_color)], N=256) home_cmap = clr.LinearSegmentedColormap.from_list('custom home', [(0, '#ffffff'), (1, home_color)], N=256) ### ### 5v5 ### # loop through each team for team in teams: if team == away: team_color = team_colors[0] opponent_color = team_colors[1] team_color_map = plt.cm.get_cmap(away_cmap) opponent_color_map = plt.cm.get_cmap(home_cmap) if team == home: team_color = team_colors[1] opponent_color = team_colors[0] team_color_map = plt.cm.get_cmap(home_cmap) opponent_color_map = plt.cm.get_cmap(away_cmap) # create a lines dataframe; filter for team; sort by time on ice; keep the lines with the 8 highest totals; rank and then invert the rankings team_lines_df = lines_df.copy() team_lines_df = team_lines_df[(team_lines_df['TEAM'] == team)] team_lines_df = team_lines_df.sort_values(by=['TOI'], ascending=True) team_lines_df = team_lines_df.iloc[-8:] team_lines_df['RANK'] = team_lines_df['TOI'].rank(method='first') team_lines_df = team_lines_df.sort_values(by=['RANK'], ascending=True) team_lines_df['RANK'] -= 1 # remove zeros from the goals for and against columns team_lines_df['GF'] = team_lines_df['GF'].replace(0, np.NaN) team_lines_df['GA'] = team_lines_df['GA'].replace(0, np.NaN) # remove zeros from the differential column team_lines_df['SD'] = team_lines_df['SD'].replace(0, np.NaN) # make shots against negative values team_lines_df['GA'] *= -1 team_lines_df['SA'] *= -1 # create another lines dataframe with just the time on ice column; set a max value; scale each line's time on ice relative to the max value lines_toi = team_lines_df['TOI'] max_lines_toi = lines_toi.max() lines_toi_color = lines_toi / float(max_lines_toi) # connect team and opponent color map colors to each line's scaled time on ice lines_toi_color_map_for = team_color_map(lines_toi_color) lines_toi_color_map_against = opponent_color_map(lines_toi_color) # create a figure with two subplots sharing the y-axis fig = plt.figure(figsize=(8, 8)) grid = plt.GridSpec(1, 8, hspace=0.75, wspace=0.50) ax_lines_shots = fig.add_subplot(grid[0, 0:-2]) ax_lines_toi = fig.add_subplot(grid[0, -1]) # set the plot title fig.suptitle(date + ' Forward Lines On-Ice Shots\n\n') # set the axes titles ax_lines_shots.set_title('5v5 S', fontsize=10) ax_lines_toi.set_title('5v5 TOI', fontsize=10) # create bars for shots for and against as well as markers (to note the shot differential) for each line try: lines_SF_plot = team_lines_df.plot.barh( x='LINE', y='SF', stacked=True, color=lines_toi_color_map_for, width=0.25, legend=None, label='', ax=ax_lines_shots) except: pass try: lines_SA_plot = team_lines_df.plot.barh( x='LINE', y='SA', stacked=True, color=lines_toi_color_map_against, width=0.25, legend=None, label='', ax=ax_lines_shots) except: pass try: lines_GF_marker = team_lines_df.plot(x='GF', y='RANK', marker='D', markersize=5, markerfacecolor='None', markeredgecolor='white', linewidth=0, alpha=1, legend='', label='', ax=ax_lines_shots) except: pass try: lines_GA_marker = team_lines_df.plot(x='GA', y='RANK', marker='D', markersize=5, markerfacecolor='None', markeredgecolor='white', linewidth=0, alpha=1, legend='', label='', ax=ax_lines_shots) except: pass try: lines_SD_plot = team_lines_df.plot(x='SD', y='RANK', marker='|', markersize=15, markerfacecolor='None', markeredgecolor='white', linewidth=0, alpha=1, legend=None, label='', ax=ax_lines_shots) except: pass # plot the bars for time on ice try: toi_lines = team_lines_df.plot.barh(x='LINE', y='TOI', color='white', edgecolor=team_color, width=0.25, legend=None, label='', ax=ax_lines_toi) except: pass # remove the labels for each subplot ax_lines_shots.set_xlabel('') ax_lines_shots.set_ylabel('') ax_lines_toi.set_xlabel('') ax_lines_toi.set_ylabel('') # set vertical indicator for break-even shot differential ax_lines_shots.axvspan(0, 0, ymin=0, ymax=1, alpha=.25, linestyle=':', color='black') # change the tick parameters ax_lines_shots.tick_params( axis='both', which='both', bottom=False, top=False, left=False, labelleft=True, # labels along the left edge are on labelbottom=True) ax_lines_toi.tick_params( axis='both', which='both', bottom=False, top=False, left=False, labelleft=False, # labels along the left edge are off labelbottom=True) # change the y-axis label colors ax_lines_shots.tick_params(axis='y', which='both', labelcolor=team_color) # create a list of x-axis tick values contingent on the max values for shots for and against SF_max = lines_df['SF'] SF_max = SF_max.max() SA_max = lines_df['SA'] SA_max = SA_max.max() S_tickmax = int() if SF_max >= SA_max: S_tickmax = SF_max if SF_max < SA_max: S_tickmax = SA_max S_ticklabels = [] if S_tickmax <= 5: S_ticklabels = [-5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5] if S_tickmax > 5 and S_tickmax <= 10: S_ticklabels = [-10, -8, -6, -4, -2, 0, 2, 4, 6, 8, 10] if S_tickmax > 10 and S_tickmax <= 15: S_ticklabels = [-15, -12, -9, -6, -3, 0, 3, 6, 9, 12, 15] if S_tickmax > 15 and S_tickmax <= 20: S_ticklabels = [-20, -16, -12, -8, -4, 0, 4, 8, 12, 16, 20] if S_tickmax > 20 and S_tickmax <= 25: S_ticklabels = [-25, -20, -15, -10, -5, 0, 5, 10, 15, 20, 25] toi_tickmax = max_toi toi_ticklabels = [] if toi_tickmax <= 2: toi_ticklabels = [0, 2] if toi_tickmax > 2 and toi_tickmax <= 4: toi_ticklabels = [0, 4] if toi_tickmax > 4 and toi_tickmax <= 6: toi_ticklabels = [0, 6] if toi_tickmax > 6 and toi_tickmax <= 8: toi_ticklabels = [0, 8] if toi_tickmax > 8 and toi_tickmax <= 10: toi_ticklabels = [0, 10] if toi_tickmax > 10 and toi_tickmax <= 12: toi_ticklabels = [0, 12] if toi_tickmax > 12 and toi_tickmax <= 14: toi_ticklabels = [0, 14] if toi_tickmax > 14 and toi_tickmax <= 16: toi_ticklabels = [0, 16] if toi_tickmax > 16 and toi_tickmax <= 18: toi_ticklabels = [0, 18] if toi_tickmax > 18 and toi_tickmax <= 20: toi_ticklabels = [0, 20] # set vertical indicator for midpoint of time on ice max ax_lines_toi.axvspan(toi_ticklabels[1] / 2, toi_ticklabels[1] / 2, ymin=0, ymax=1, zorder=0, alpha=0.25, linestyle=':', color='black') ax_lines_toi.axvspan(toi_ticklabels[1], toi_ticklabels[1], ymin=0, ymax=1, zorder=0, alpha=0.25, linestyle=':', color='black') # use the newly-minted x-ticklabels to ensure the x-axis labels will always display as integers ax_lines_shots.set_xticks(S_ticklabels, minor=False) ax_lines_toi.set_xticks(toi_ticklabels, minor=False) # remove the borders to each subplot ax_lines_shots.spines["top"].set_visible(False) ax_lines_shots.spines["bottom"].set_visible(False) ax_lines_shots.spines["right"].set_visible(False) ax_lines_shots.spines["left"].set_visible(False) ax_lines_toi.spines["top"].set_visible(False) ax_lines_toi.spines["bottom"].set_visible(False) ax_lines_toi.spines["right"].set_visible(False) ax_lines_toi.spines["left"].set_visible(False) # add a legend for the shot type markers from matplotlib.lines import Line2D elements = [ Line2D([0], [0], marker='D', markersize=5, markerfacecolor='None', markeredgecolor='black', linewidth=0, alpha=1, label='Scored'), Line2D([0], [0], marker='|', markersize=13, markerfacecolor='None', markeredgecolor='black', linewidth=0, alpha=1, label='Differential') ] ax_lines_shots.legend(handles=elements, loc='center', bbox_to_anchor=(.5, -.1), ncol=2).get_frame().set_linewidth(0.0) # add text boxes with team names in white and with the team's color in the background fig.text(.425, 0.936, ' ' + away + ' ', color='white', fontsize='12', bbox=dict(facecolor=away_color, edgecolor='None')) fig.text(.525, 0.936, ' ' + home + ' ', fontsize='12', color='white', bbox=dict(facecolor=home_color, edgecolor='None')) fig.text(.490, 0.936, '@', color='black', fontsize='12', bbox=dict(facecolor='white', edgecolor='None')) ### ### SAVE TO FILE ### if team == away: plt.savefig(charts_units_lines + 'onice_shots_away_lines.png', bbox_inches='tight', pad_inches=0.2) elif team == home: plt.savefig(charts_units_lines + 'onice_shots_home_lines.png', bbox_inches='tight', pad_inches=0.2) # exercise a command-line option to show the current figure if images == 'show': plt.show() ### ### CLOSE ### plt.close(fig) # status update print('Plotting ' + team + ' lines 5v5 on-ice shots.') # status update print('Finished plotting 5v5 on-ice shots for lines.')
def parse_ids(season_id, game_id, images): # pull common variables from the parameters file charts_players_onice_situation = parameters.charts_players_onice_situation files_root = parameters.files_root # generate date and team information schedule_csv = files_root + season_id + "_schedule.csv" schedule_df = pd.read_csv(schedule_csv) schedule_date = schedule_df[(schedule_df['GAME_ID'] == int(game_id))] date = schedule_date['DATE'].item() home = schedule_date['HOME'].item() away = schedule_date['AWAY'].item() teams = [away, home] # create variables that point to the .csv processed stats files for the team and players team_file = files_root + 'stats_teams_situation.csv' players_file = files_root + 'stats_players_onice_situation.csv' # create a dataframe object that reads in info from the .csv files team_stats_df = pd.read_csv(team_file) players_df = pd.read_csv(players_file) # choose colors for each team; set them in a list; generate a custom colormap for each team away_color = dict_team_colors.team_color_1st[away] home_color = dict_team_colors.team_color_1st[home] # change one team's color from its primary option to, depending on the opponent, either a second, third or fourth option try: away_color = mod_switch_colors.switch_team_colors(away, home)[0] home_color = mod_switch_colors.switch_team_colors(away, home)[1] except: pass team_colors = [away_color, home_color] ### ### 5v5, PP, SH ### situations = ['Leading', 'Tied', 'Trailing'] # loop through each situation for situation in situations: if situation == 'Leading': home_situation = 'Leading' away_situation = 'Trailing' if situation == 'Tied': home_situation = 'Tied' away_situation = 'Tied' if situation == 'Trailing': home_situation = 'Trailing' away_situation = 'Leading' # loop through each team for team in teams: if team == away: team_color = team_colors[0] opponent_color = team_colors[1] situation = away_situation if team == home: team_color = team_colors[1] opponent_color = team_colors[0] situation = home_situation # create a dataframe from the team stats file for generating toi values for the different game states team_toi_df = team_stats_df.copy() team_all_toi = team_toi_df[(team_toi_df['TEAM'] == team) & (team_toi_df['STATE'] == 'ALL') & (team_toi_df['SITUATION'] == situation)] team_all_toi = team_all_toi['TOI'].item() team_5v5_toi = team_toi_df[(team_toi_df['TEAM'] == team) & (team_toi_df['STATE'] == '5v5') & (team_toi_df['SITUATION'] == situation)] team_5v5_toi = team_5v5_toi['TOI'].item() team_PP_toi = team_toi_df[(team_toi_df['TEAM'] == team) & (team_toi_df['STATE'] == 'PP') & (team_toi_df['SITUATION'] == situation)] team_PP_toi = team_PP_toi['TOI'].item() team_SH_toi = team_toi_df[(team_toi_df['TEAM'] == team) & (team_toi_df['STATE'] == 'SH') & (team_toi_df['SITUATION'] == situation)] team_SH_toi = team_SH_toi['TOI'].item() # create a dataframe; filter for team; sort by team, game state and position; rank by time on ice and then invert the rankings team_df = players_df.copy() team_df = team_df[(team_df['TEAM'] == team) & (team_df['POS'] != 'G')] # remove zeros from the differential column team_df['xGD'] = team_df['xGD'].replace(0, np.NaN) # make expected goals against negative team_df['xGA'] *= -1 # create a filtered dataframe for each game state; sort by team, game state and position; rank by time on ice and then invert the rankings team_5v5_df = team_df.copy() team_5v5_df = team_5v5_df[(team_5v5_df['STATE'] == '5v5') & (team_5v5_df['SITUATION'] == situation)] team_5v5_df = team_5v5_df.sort_values(by=['TOI'], ascending = True) team_5v5_df['RANK'] = team_5v5_df['TOI'].rank(method='first') team_5v5_df['RANK'] -= 1 team_PP_df = team_df.copy() team_PP_df = team_PP_df[(team_PP_df['STATE'] == 'PP') & (team_PP_df['TOI'] > 0) & (team_PP_df['SITUATION'] == situation)] team_PP_df = team_PP_df.sort_values(by=['TOI'], ascending = True) team_PP_df['RANK'] = team_PP_df['TOI'].rank(method='first') team_PP_df['RANK'] -= 1 team_SH_df = team_df.copy() team_SH_df = team_SH_df[(team_SH_df['STATE'] == 'SH') & (team_SH_df['TOI'] > 0) & (team_SH_df['SITUATION'] == situation)] team_SH_df = team_SH_df.sort_values(by=['TOI'], ascending = True) team_SH_df['RANK'] = team_SH_df['TOI'].rank(method='first') team_SH_df['RANK'] -= 1 # for each game state, create a dataframe with just the time on ice column; set a max value; scale each player's time on ice relative to the max toi_5v5 = team_5v5_df['TOI'] max_toi_5v5 = toi_5v5.max() toi_PP = team_PP_df['TOI'] max_toi_PP = toi_PP.max() toi_SH = team_SH_df['TOI'] max_toi_SH = toi_SH.max() # create a figure with six subplots arrangled complexly using a grid structure fig = plt.figure(figsize=(8,8)) grid = plt.GridSpec(5, 8, hspace=0.75, wspace=0.75) ax_5v5_xG = fig.add_subplot(grid[0:-2, :-1]) ax_5v5_toi = fig.add_subplot(grid[0:-2, 7]) ax_PP_xG = fig.add_subplot(grid[3:, :2]) ax_PP_toi = fig.add_subplot(grid[3:, 2]) ax_SH_xG = fig.add_subplot(grid[3:, 5:-1]) ax_SH_toi = fig.add_subplot(grid[3:, 7]) # set the plot title if team == away: fig.suptitle(date + ' Skaters On-Ice Expected Goals (Away ' + situation + ')\n\n') if team == home: fig.suptitle(date + ' Skaters On-Ice Expected Goals (Home ' + situation + ')\n\n') # set the axes titles ax_5v5_xG.set_title('5v5 xG', fontsize=10) ax_5v5_toi.set_title('5v5 TOI', fontsize=10) ax_PP_xG.set_title('PP xG', fontsize=10) ax_PP_toi.set_title('PP TOI', fontsize=10) ax_SH_xG.set_title('SH xG', fontsize=10) ax_SH_toi.set_title('SH TOI', fontsize=10) # for each state, plot the bars for expected goals and a marker expected goal differential try: xGF_5v5_plot = team_5v5_df.plot.barh(x='PLAYER', y='xGF', color=team_color, edgecolor='None', width=0.75, legend=None, label='', ax=ax_5v5_xG); except: pass try: xGA_5v5_plot = team_5v5_df.plot.barh(x='PLAYER', y='xGA', color=opponent_color, edgecolor='None', width=0.75, legend=None, label='', ax=ax_5v5_xG); except: pass try: xGD_5v5_marker = team_5v5_df.plot(x='xGD', y='RANK', marker='|', markersize=11, markeredgewidth=1, markerfacecolor='None', markeredgecolor='white', linewidth=0, alpha=1, legend=None, label='', ax=ax_5v5_xG); except: pass if team_PP_toi != 0: try: xGF_PP_plot = team_PP_df.plot.barh(x='PLAYER', y='xGF', color=team_color, edgecolor='None', width=0.75, legend=None, label='', ax=ax_PP_xG); except: pass try: xGA_PP_plot = team_PP_df.plot.barh(x='PLAYER', y='xGA', color=opponent_color, edgecolor='None', width=0.75, legend=None, label='', ax=ax_PP_xG); except: pass try: xGD_PP_marker = team_PP_df.plot(x='xGD', y='RANK', marker='|', markersize=11, markeredgewidth=1, markerfacecolor='None', markeredgecolor='white', linewidth=0, alpha=1, legend=None, label='', ax=ax_PP_xG); except: pass if team_SH_toi != 0: try: xGF_SH_plot = team_SH_df.plot.barh(x='PLAYER', y='xGF', color=team_color, edgecolor='None', width=0.75, legend=None, label='', ax=ax_SH_xG); except: pass try: xGA_SH_plot = team_SH_df.plot.barh(x='PLAYER', y='xGA', color=opponent_color, edgecolor='None', width=0.75, legend=None, label='', ax=ax_SH_xG); except: pass try: xGD_SH_marker = team_SH_df.plot(x='xGD', y='RANK', marker='|', markersize=11, markeredgewidth=1, markerfacecolor='None', markeredgecolor='white', linewidth=0, alpha=1, legend=None, label='', ax=ax_SH_xG); except: pass # for each state, plot the bars for time on ice try: toi_5v5_plot = team_5v5_df.plot.barh(x='PLAYER', y='TOI', color='white', edgecolor=team_color, width=0.75, legend=None, label='', ax=ax_5v5_toi); except: pass if team_PP_toi != 0: try: toi_PP_plot = team_PP_df.plot.barh(x='PLAYER', y='TOI', color='white', edgecolor=team_color, width=0.75, legend=None, label='', ax=ax_PP_toi); except: pass if team_SH_toi != 0: try: toi_SH_plot = team_SH_df.plot.barh(x='PLAYER', y='TOI', color='white', edgecolor=team_color, width=0.75, legend=None, label='', ax=ax_SH_toi); except: pass # set / remove the y-labels for the subplots ax_5v5_xG.set_xlabel('') ax_5v5_xG.set_ylabel('', fontsize=10) ax_5v5_toi.set_xlabel('') ax_5v5_toi.set_ylabel('') ax_PP_xG.set_xlabel('') ax_PP_xG.set_ylabel('', fontsize=10) ax_PP_toi.set_xlabel('') ax_PP_toi.set_ylabel('') ax_SH_xG.set_xlabel('') ax_SH_xG.set_ylabel('', fontsize=10) ax_SH_toi.set_xlabel('') ax_SH_toi.set_ylabel('') # set vertical indicators for zero shots ax_5v5_xG.axvspan(0, 0, ymin=0, ymax=1, alpha=.25, linestyle=':', color='black') ax_PP_xG.axvspan(0, 0, ymin=0, ymax=1, alpha=.25, linestyle=':', color='black') ax_SH_xG.axvspan(0, 0, ymin=0, ymax=1, alpha=.25, linestyle=':', color='black') # change the tick parameters for each axes ax_5v5_xG.tick_params( axis='both', # changes apply to the x-axis which='both', # both major and minor ticks are affected bottom=False, # ticks along the bottom edge are off top=False, # ticks along the top edge are off left=False, # ticks along the left edge are off labelbottom=True) # labels along the bottom edge are on ax_5v5_toi.tick_params( axis='both', # changes apply to the x-axis which='both', # both major and minor ticks are affected bottom=False, # ticks along the bottom edge are off top=False, # ticks along the top edge are off left=False, # ticks along the left edge are off labelleft=False, # labels along the left edge are off labelbottom=True) # labels along the bottom edge are on ax_PP_xG.tick_params( axis='both', # changes apply to the x-axis which='both', # both major and minor ticks are affected bottom=False, # ticks along the bottom edge are off top=False, # ticks along the top edge are off left=False, # ticks along the left edge are off labelbottom=True) # labels along the bottom edge are on ax_PP_toi.tick_params( axis='both', # changes apply to the x-axis which='both', # both major and minor ticks are affected bottom=False, # ticks along the bottom edge are off top=False, # ticks along the top edge are off left=False, # ticks along the left edge are off labelleft=False, # labels along the left edge are off labelbottom=True) # labels along the bottom edge are on ax_SH_xG.tick_params( axis='both', # changes apply to the x-axis which='both', # both major and minor ticks are affected bottom=False, # ticks along the bottom edge are off top=False, # ticks along the top edge are off left=False, # ticks along the left edge are off labelbottom=True) # labels along the bottom edge are on ax_SH_toi.tick_params( axis='both', # changes apply to the x-axis which='both', # both major and minor ticks are affected bottom=False, # ticks along the bottom edge are off top=False, # ticks along the top edge are off left=False, # ticks along the left edge are off labelleft=False, # labels along the left edge are off labelbottom=True) # labels along the bottom edge are on # create a list of x-axis tick values contingent on the max values for shots team_5v5_df2 = team_5v5_df.copy() team_PP_df2 = team_PP_df.copy() team_SH_df2 = team_SH_df.copy() team_5v5_df2['xGA'] *= -1 team_PP_df2['xGA'] *= -1 team_SH_df2['xGA'] *= -1 xGF_5v5_max = team_5v5_df2['xGF'] xGF_5v5_max = xGF_5v5_max.max() xGA_5v5_max = team_5v5_df2['xGA'] xGA_5v5_max = xGA_5v5_max.max() xG_5v5_tickmax = float() if xGF_5v5_max >= xGA_5v5_max: xG_5v5_tickmax = xGF_5v5_max if xGF_5v5_max < xGA_5v5_max: xG_5v5_tickmax = xGA_5v5_max xG_5v5_ticklabels = [] if xG_5v5_tickmax >= 0 and xG_5v5_tickmax <= 0.5: xG_5v5_ticklabels = [-0.50, -0.40, -0.30, -0.20, -0.10, 0.00, 0.10, 0.20, 0.30, 0.40, 0.50] if xG_5v5_tickmax > 0.5 and xG_5v5_tickmax <= 1: xG_5v5_ticklabels = [-1.00, -0.80, -0.60, -0.40, -0.20, 0.00, 0.20, 0.40, 0.60, 0.80, 1.00] if xG_5v5_tickmax > 1 and xG_5v5_tickmax <= 1.5: xG_5v5_ticklabels = [-1.50, -1.20, -0.90, -0.60, -0.30, 0.00, 0.30, 0.60, 0.90, 1.20, 1.50] if xG_5v5_tickmax > 1.5 and xG_5v5_tickmax <= 2: xG_5v5_ticklabels = [-2.00, -1.60, -1.20, -0.80, -0.40, 0.00, 0.40, 0.80, 1.20, 1.60, 2.00] if xG_5v5_tickmax > 2 and xG_5v5_tickmax <= 2.5: xG_5v5_ticklabels = [-2.50, -2.00, -1.50, -1.00, -0.50, 0.00, 0.50, 1.00, 1.50, 2.00, 2.50] if xG_5v5_tickmax > 2.5 and xG_5v5_tickmax <= 3: xG_5v5_ticklabels = [-3.00, -2.40, -1.80, -1.20, -0.60, 0.00, 0.60, 1.20, 1.80, 2.40, 3.00] if xG_5v5_tickmax > 3 and xG_5v5_tickmax <= 3.5: xG_5v5_ticklabels = [-3.50, -2.80, -2.10, -1.40, -0.70, 0.00, 0.70, 1.40, 2.10, 2.80, 3.50] if xG_5v5_tickmax > 3.5 and xG_5v5_tickmax <= 4: xG_5v5_ticklabels = [-4.00, -3.20, -2.40, -1.60, -0.80, 0.00, 0.80, 1.60, 2.40, 3.20, 4.00] toi_5v5_tickmax = max_toi_5v5 toi_5v5_ticklabels = [] if toi_5v5_tickmax <= 10: toi_5v5_ticklabels = [0, 10] if toi_5v5_tickmax > 10 and toi_5v5_tickmax <= 15: toi_5v5_ticklabels = [0, 15] if toi_5v5_tickmax > 15 and toi_5v5_tickmax <= 20: toi_5v5_ticklabels = [0, 20] if toi_5v5_tickmax > 20 and toi_5v5_tickmax <= 25: toi_5v5_ticklabels = [0, 25] if toi_5v5_tickmax > 25 and toi_5v5_tickmax <= 30: toi_5v5_ticklabels = [0, 30] xGF_PP_max = team_PP_df2['xGF'] xGF_PP_max = xGF_PP_max.max() xGA_PP_max = team_PP_df2['xGA'] xGA_PP_max = xGA_PP_max.max() xG_PP_tickmax = float() if xGF_PP_max >= xGA_PP_max: xG_PP_tickmax = xGF_PP_max if xGF_PP_max < xGA_PP_max: xG_PP_tickmax = xGA_PP_max xG_PP_ticklabels = [] if xG_PP_tickmax <= 0.5: xG_PP_ticklabels = [-0.50, 0.00, 0.50] if xG_PP_tickmax > 0.5 and xG_PP_tickmax <= 1: xG_PP_ticklabels = [-1.00, 0.00, 1.00] if xG_PP_tickmax > 1 and xG_PP_tickmax <= 1.5: xG_PP_ticklabels = [-1.50, 0.00, 1.50] if xG_PP_tickmax > 1.5 and xG_PP_tickmax <= 2: xG_PP_ticklabels = [-2.00, 0.00, 2.00] if xG_PP_tickmax > 2 and xG_PP_tickmax <= 2.5: xG_PP_ticklabels = [-2.50, 0.00, 2.50] if xG_PP_tickmax > 2.5 and xG_PP_tickmax <= 3: xG_PP_ticklabels = [-3.00, 0.00, 3.00] if xG_PP_tickmax > 3 and xG_PP_tickmax <= 3.5: xG_PP_ticklabels = [-3.50, 0.00, 3.50] if xG_PP_tickmax > 3 and xG_PP_tickmax <= 4: xG_PP_ticklabels = [-4.00, 0.00, 4.00] xGF_SH_max = team_SH_df2['xGF'] xGF_SH_max = xGF_SH_max.max() xGA_SH_max = team_SH_df2['xGA'] xGA_SH_max = xGA_SH_max.max() xG_SH_tickmax = float() if xGF_SH_max >= xGA_SH_max: xG_SH_tickmax = xGF_SH_max if xGF_SH_max < xGA_SH_max: xG_SH_tickmax = xGA_SH_max xG_SH_ticklabels = [] if xG_SH_tickmax <= 0.5: xG_SH_ticklabels = [-0.50, 0.00, 0.50] if xG_SH_tickmax > 0.5 and xG_SH_tickmax <= 1: xG_SH_ticklabels = [-1.00, 0.00, 1.00] if xG_SH_tickmax > 1 and xG_SH_tickmax <= 1.5: xG_SH_ticklabels = [-1.50, 0.00, 1.50] if xG_SH_tickmax > 1.5 and xG_SH_tickmax <= 2: xG_SH_ticklabels = [-2.00, 0.00, 2.00] if xG_SH_tickmax > 2 and xG_SH_tickmax <= 2.5: xG_SH_ticklabels = [-2.50, 0.00, 2.50] if xG_SH_tickmax > 2.5 and xG_SH_tickmax <= 3: xG_SH_ticklabels = [-3.00, 0.00, 3.00] if xG_SH_tickmax > 3 and xG_SH_tickmax <= 3.5: xG_SH_ticklabels = [-3.50, 0.00, 3.50] if xG_SH_tickmax > 3 and xG_SH_tickmax <= 4: xG_SH_ticklabels = [-4.00, 0.00, 4.00] toi_PP_tickmax = max_toi_PP toi_SH_tickmax = max_toi_SH if toi_PP_tickmax >= toi_SH_tickmax: toi_specialteams_tickmax = toi_PP_tickmax if toi_PP_tickmax < toi_SH_tickmax: toi_specialteams_tickmax = toi_SH_tickmax toi_specialteams_ticklabels = [] if toi_specialteams_tickmax <= 2: toi_specialteams_ticklabels = [0, 2] if toi_specialteams_tickmax > 2 and toi_specialteams_tickmax <= 4: toi_specialteams_ticklabels = [0, 4] if toi_specialteams_tickmax > 4 and toi_specialteams_tickmax <= 6: toi_specialteams_ticklabels = [0, 6] if toi_specialteams_tickmax > 6 and toi_specialteams_tickmax <= 8: toi_specialteams_ticklabels = [0, 8] if toi_specialteams_tickmax > 8 and toi_specialteams_tickmax <= 10: toi_specialteams_ticklabels = [0, 10] if toi_specialteams_tickmax > 10 and toi_specialteams_tickmax <= 12: toi_specialteams_ticklabels = [0, 12] # set vertical indicator for midpoint of time on ice max ax_5v5_toi.axvspan(toi_5v5_ticklabels[1] / 2, toi_5v5_ticklabels[1] / 2, ymin=0, ymax=1, zorder=0, alpha=0.25, linestyle=':', color='black') ax_5v5_toi.axvspan(toi_5v5_ticklabels[1], toi_5v5_ticklabels[1], ymin=0, ymax=1, zorder=0, alpha=0.25, linestyle=':', color='black') ax_PP_toi.axvspan(toi_specialteams_ticklabels[1] / 2, toi_specialteams_ticklabels[1] / 2, ymin=0, ymax=1, zorder=0, alpha=0.25, linestyle=':', color='black') ax_PP_toi.axvspan(toi_specialteams_ticklabels[1], toi_specialteams_ticklabels[1], ymin=0, ymax=1, zorder=0, alpha=0.25, linestyle=':', color='black') ax_SH_toi.axvspan(toi_specialteams_ticklabels[1] / 2, toi_specialteams_ticklabels[1] / 2, ymin=0, ymax=1, zorder=0, alpha=0.25, linestyle=':', color='black') ax_SH_toi.axvspan(toi_specialteams_ticklabels[1], toi_specialteams_ticklabels[1], ymin=0, ymax=1, zorder=0, alpha=0.25, linestyle=':', color='black') # use the newly-minted x-ticklabels to ensure the x-axis labels will always display as integers ax_5v5_xG.set_xticks(xG_5v5_ticklabels, minor=False) ax_5v5_toi.set_xticks(toi_5v5_ticklabels, minor=False) ax_PP_xG.set_xticks(xG_PP_ticklabels, minor=False) ax_PP_toi.set_xticks(toi_specialteams_ticklabels, minor=False) ax_SH_xG.set_xticks(xG_SH_ticklabels, minor=False) ax_SH_toi.set_xticks(toi_specialteams_ticklabels, minor=False) # remove axes ticks for instances where there is no special teams play if team_PP_toi == 0: ax_PP_xG.set_xticks([], minor=False) ax_PP_xG.set_yticks([], minor=False) ax_PP_toi.set_xticks([], minor=False) ax_PP_toi.set_yticks([], minor=False) if team_SH_toi == 0: ax_SH_xG.set_xticks([], minor=False) ax_SH_xG.set_yticks([], minor=False) ax_SH_toi.set_xticks([], minor=False) ax_SH_toi.set_yticks([], minor=False) # remove the borders to each subplot ax_5v5_xG.spines["top"].set_visible(False) ax_5v5_xG.spines["bottom"].set_visible(False) ax_5v5_xG.spines["right"].set_visible(False) ax_5v5_xG.spines["left"].set_visible(False) ax_5v5_toi.spines["top"].set_visible(False) ax_5v5_toi.spines["bottom"].set_visible(False) ax_5v5_toi.spines["right"].set_visible(False) ax_5v5_toi.spines["left"].set_visible(False) ax_PP_xG.spines["top"].set_visible(False) ax_PP_xG.spines["bottom"].set_visible(False) ax_PP_xG.spines["right"].set_visible(False) ax_PP_xG.spines["left"].set_visible(False) ax_PP_toi.spines["top"].set_visible(False) ax_PP_toi.spines["bottom"].set_visible(False) ax_PP_toi.spines["right"].set_visible(False) ax_PP_toi.spines["left"].set_visible(False) ax_SH_xG.spines["top"].set_visible(False) ax_SH_xG.spines["bottom"].set_visible(False) ax_SH_xG.spines["right"].set_visible(False) ax_SH_xG.spines["left"].set_visible(False) ax_SH_toi.spines["top"].set_visible(False) ax_SH_toi.spines["bottom"].set_visible(False) ax_SH_toi.spines["right"].set_visible(False) ax_SH_toi.spines["left"].set_visible(False) # add a legend for the shot type markers from matplotlib.lines import Line2D elements = [Line2D([0], [0], marker='|', markersize=11, markerfacecolor='None', markeredgecolor='black', linewidth=0, alpha=1, label='Differential')] ax_5v5_xG.legend(handles=elements, loc='center', bbox_to_anchor=(.55, -.925), ncol=1).get_frame().set_linewidth(0.0) # add text boxes with team names in white and with the team's color in the background fig.text(.425, 0.936, ' ' + away + ' ', color='white', fontsize='12', bbox=dict(facecolor=away_color, edgecolor='None')) fig.text(.525, 0.936, ' ' + home + ' ', fontsize='12', color='white', bbox=dict(facecolor=home_color, edgecolor='None')) fig.text(.490, 0.936, '@', color='black', fontsize='12', bbox=dict(facecolor='white', edgecolor='None')) ### ### SAVE TO FILE ### if team == away: plt.savefig(charts_players_onice_situation + 'skaters_onice_xG_away_' + situation.lower() + '.png', bbox_inches='tight', pad_inches=0.2) elif team == home: plt.savefig(charts_players_onice_situation + 'skaters_onice_xG_home_' + situation.lower() + '.png', bbox_inches='tight', pad_inches=0.2) # exercise a command-line option to show the current figure if images == 'show': plt.show() ### ### CLOSE ### plt.close(fig) # status update print('Plotting ' + team + ' skaters on-ice xG while ' + situation.lower() + '.') # status update print('Finished plotting the on-ice xG for skaters by situation.')
def parse_ids(season_id, game_id, images): # pull common variables from the parameters file charts_teams_period = parameters.charts_teams_period files_root = parameters.files_root # generate date and team information schedule_csv = files_root + season_id + "_schedule.csv" schedule_df = pd.read_csv(schedule_csv) schedule_date = schedule_df[(schedule_df['GAME_ID'] == int(game_id))] date = schedule_date['DATE'].item() home = schedule_date['HOME'].item() away = schedule_date['AWAY'].item() # create variables that point to the .csv team stats file and play-by-play file stats_teams_file = files_root + 'stats_teams_period.csv' pbp_file = files_root + 'pbp.csv' # create a dataframe object that reads in the team stats file stats_teams_df = pd.read_csv(stats_teams_file) # create a dataframe object that reads in the play-by-file info; invert the X and Y coordinates pbp_df = pd.read_csv(pbp_file) pbp_df = pbp_df[(pbp_df['PERIOD'] <= 4)] pbp_df['X_1'] *= -1 pbp_df['Y_1'] *= -1 pbp_df['X_2'] *= -1 pbp_df['Y_2'] *= -1 # make copies of the pbp file for later generation of team-specific subsets away_df = pbp_df.copy() home_df = pbp_df.copy() # choose colors for each team; set them in a list; generate a custom colormap for each team legend_color = 'black' away_color = dict_team_colors.team_color_1st[away] home_color = dict_team_colors.team_color_1st[home] # change one team's color from its primary option to, depending on the opponent, either a second, third or fourth option try: away_color = mod_switch_colors.switch_team_colors(away, home)[0] home_color = mod_switch_colors.switch_team_colors(away, home)[1] except: pass colors = [away_color, home_color, legend_color] away_cmap = clr.LinearSegmentedColormap.from_list('custom away', [(0, '#ffffff'), (1, away_color)], N=256) home_cmap = clr.LinearSegmentedColormap.from_list('custom home', [(0, '#ffffff'), (1, home_color)], N=256) periods = [1, 2, 3, 4] for period in periods: if period == 1: period_name = '1st' if period == 2: period_name = '2nd' if period == 3: period_name = '3rd' if period == 4: period_name = 'OT' states = ['ALL', '5v5', 'PP', 'SH'] for state in states: # pull the time on ice recorded for the home team from the team stats file if state == 'ALL': try: toi_df = stats_teams_df[(stats_teams_df['TEAM'] == home) & (stats_teams_df['STATE'] == 'ALL') & (stats_teams_df['PERIOD'] == period_name)] toi = toi_df['TOI'].item() except: toi = 0.0 if state == '5v5' and period < 4 or state == '5v5' and int(season_id) != 20192020 and period == 4 and int(game_id) >= 30000 or state == '5v5' and int(season_id) == 20192020 and period == 4 and int(game_id) >= 30021: try: toi_df = stats_teams_df[(stats_teams_df['TEAM'] == home) & (stats_teams_df['STATE'] == '5v5') & (stats_teams_df['PERIOD'] == period_name)] toi = toi_df['TOI'].item() except: toi = 0.0 if state == '5v5' and period == 4 and int(game_id) < 30000 and int(season_id) <= 20142015: try: toi_df = stats_teams_df[(stats_teams_df['TEAM'] == home) & (stats_teams_df['STATE'] == '4v4') & (stats_teams_df['PERIOD'] == period_name)] toi = toi_df['TOI'].item() except: toi = 0.0 if state == '5v5' and period == 4 and int(game_id) < 30000 and int(season_id) >= 20152016 or state == '5v5' and season_id == 20192020 and period == 4 and int(game_id) > 30000 and int(game_id) <= 30020: try: toi_df = stats_teams_df[(stats_teams_df['TEAM'] == home) & (stats_teams_df['STATE'] == '3v3') & (stats_teams_df['PERIOD'] == period_name)] toi = toi_df['TOI'].item() except: toi = 0.0 if state == 'PP': try: toi_df = stats_teams_df[(stats_teams_df['TEAM'] == home) & (stats_teams_df['STATE'] == 'PP') & (stats_teams_df['PERIOD'] == period_name)] toi = toi_df['TOI'].item() except: toi = 0.0 if state == 'SH': try: toi_df = stats_teams_df[(stats_teams_df['TEAM'] == home) & (stats_teams_df['STATE'] == 'SH') & (stats_teams_df['PERIOD'] == period_name)] toi = toi_df['TOI'].item() except: toi = 0.0 # get a count of the number of unblocked shots for each team if state == 'ALL': away_count = str(pbp_df[(pbp_df['TEAM'] == away) & (pbp_df['EVENT'] == 'Shot') & (pbp_df['EVENT_TYPE'] != 'Block') & (pbp_df['PERIOD'] == period)].count()[1]) home_count = str(pbp_df[(pbp_df['TEAM'] == home) & (pbp_df['EVENT'] == 'Shot') & (pbp_df['EVENT_TYPE'] != 'Block') & (pbp_df['PERIOD'] == period)].count()[1]) if state == '5v5' and period < 4: away_count = str(pbp_df[(pbp_df['TEAM'] == away) & (pbp_df['EVENT'] == 'Shot') & (pbp_df['EVENT_TYPE'] != 'Block') & (pbp_df['PERIOD'] == period) & (pbp_df['HOME_STRENGTH'] == '5v5') & (pbp_df['AWAY_STRENGTH'] == '5v5')].count()[1]) home_count = str(pbp_df[(pbp_df['TEAM'] == home) & (pbp_df['EVENT'] == 'Shot') & (pbp_df['EVENT_TYPE'] != 'Block') & (pbp_df['PERIOD'] == period) & (pbp_df['HOME_STRENGTH'] == '5v5') & (pbp_df['AWAY_STRENGTH'] == '5v5')].count()[1]) if state == '5v5' and period == 4 and int(game_id) < 30000 and int(season_id) <= 20142015: away_count = str(pbp_df[(pbp_df['TEAM'] == away) & (pbp_df['EVENT'] == 'Shot') & (pbp_df['EVENT_TYPE'] != 'Block') & (pbp_df['PERIOD'] == period) & (pbp_df['HOME_STRENGTH'] == '4v4') & (pbp_df['AWAY_STRENGTH'] == '4v4')].count()[1]) home_count = str(pbp_df[(pbp_df['TEAM'] == home) & (pbp_df['EVENT'] == 'Shot') & (pbp_df['EVENT_TYPE'] != 'Block') & (pbp_df['PERIOD'] == period) & (pbp_df['HOME_STRENGTH'] == '4v4') & (pbp_df['AWAY_STRENGTH'] == '4v4')].count()[1]) if state == '5v5' and period == 4 and int(game_id) < 30000 and int(season_id) >= 20152016 or state == '5v5' and season_id == 20192020 and period == 4 and int(game_id) > 30000 and int(game_id) <= 30020: away_count = str(pbp_df[(pbp_df['TEAM'] == away) & (pbp_df['EVENT'] == 'Shot') & (pbp_df['EVENT_TYPE'] != 'Block') & (pbp_df['PERIOD'] == period) & (pbp_df['HOME_STRENGTH'] == '3v3') & (pbp_df['AWAY_STRENGTH'] == '3v3')].count()[1]) home_count = str(pbp_df[(pbp_df['TEAM'] == home) & (pbp_df['EVENT'] == 'Shot') & (pbp_df['EVENT_TYPE'] != 'Block') & (pbp_df['PERIOD'] == period) & (pbp_df['HOME_STRENGTH'] == '3v3') & (pbp_df['AWAY_STRENGTH'] == '3v3')].count()[1]) if state == '5v5' and int(season_id) != 20192020 and period == 4 and int(game_id) >= 30000 or state == '5v5' and int(season_id) == 20192020 and period == 4 and int(game_id) >= 30021: away_count = str(pbp_df[(pbp_df['TEAM'] == away) & (pbp_df['EVENT'] == 'Shot') & (pbp_df['EVENT_TYPE'] != 'Block') & (pbp_df['PERIOD'] >= period) & (pbp_df['HOME_STRENGTH'] == '5v5') & (pbp_df['AWAY_STRENGTH'] == '5v5')].count()[1]) home_count = str(pbp_df[(pbp_df['TEAM'] == home) & (pbp_df['EVENT'] == 'Shot') & (pbp_df['EVENT_TYPE'] != 'Block') & (pbp_df['PERIOD'] >= period) & (pbp_df['HOME_STRENGTH'] == '5v5') & (pbp_df['AWAY_STRENGTH'] == '5v5')].count()[1]) if state == 'PP': away_count = str(pbp_df[(pbp_df['TEAM'] == away) & (pbp_df['EVENT'] == 'Shot') & (pbp_df['EVENT_TYPE'] != 'Block') & (pbp_df['PERIOD'] == period) & (pbp_df['HOME_STATE'] == 'PP') & (pbp_df['AWAY_STATE'] == 'SH')].count()[1]) home_count = str(pbp_df[(pbp_df['TEAM'] == home) & (pbp_df['EVENT'] == 'Shot') & (pbp_df['EVENT_TYPE'] != 'Block') & (pbp_df['PERIOD'] == period) & (pbp_df['HOME_STATE'] == 'PP') & (pbp_df['AWAY_STATE'] == 'SH')].count()[1]) if state == 'SH': away_count = str(pbp_df[(pbp_df['TEAM'] == away) & (pbp_df['EVENT'] == 'Shot') & (pbp_df['EVENT_TYPE'] != 'Block') & (pbp_df['PERIOD'] == period) & (pbp_df['HOME_STATE'] == 'SH') & (pbp_df['AWAY_STATE'] == 'PP')].count()[1]) home_count = str(pbp_df[(pbp_df['TEAM'] == home) & (pbp_df['EVENT'] == 'Shot') & (pbp_df['EVENT_TYPE'] != 'Block') & (pbp_df['PERIOD'] == period) & (pbp_df['HOME_STATE'] == 'SH') & (pbp_df['AWAY_STATE'] == 'PP')].count()[1]) # create subsets of the distinct types of unblocked shots for each team from the play-by-play file if state == 'ALL': away_shots = away_df[(away_df['TEAM'] == away) & (away_df['EVENT'] == 'Shot') & (away_df['EVENT_TYPE'] != 'Block') & (away_df['PERIOD'] == period)] away_shots = away_shots.dropna(subset=['X_1', 'Y_1']) away_scored = pbp_df[(pbp_df['TEAM'] == away) & (pbp_df['EVENT'] == 'Shot') & (pbp_df['EVENT_TYPE'] == 'Goal') & (away_df['PERIOD'] == period)] home_shots = home_df[(home_df['TEAM'] == home) & (home_df['EVENT'] == 'Shot') & (home_df['EVENT_TYPE'] != 'Block') & (away_df['PERIOD'] == period)] home_shots = home_shots.dropna(subset=['X_1', 'Y_1']) home_scored = pbp_df[(pbp_df['TEAM'] == home) & (pbp_df['EVENT'] == 'Shot') & (pbp_df['EVENT_TYPE'] == 'Goal') & (away_df['PERIOD'] == period)] if state == '5v5' and period < 4: away_shots = away_df[(away_df['TEAM'] == away) & (away_df['EVENT'] == 'Shot') & (away_df['EVENT_TYPE'] != 'Block') & (away_df['PERIOD'] == period) & (pbp_df['HOME_STRENGTH'] == '5v5') & (pbp_df['AWAY_STRENGTH'] == '5v5')] away_shots = away_shots.dropna(subset=['X_1', 'Y_1']) away_scored = pbp_df[(pbp_df['TEAM'] == away) & (pbp_df['EVENT'] == 'Shot') & (pbp_df['EVENT_TYPE'] == 'Goal') & (away_df['PERIOD'] == period) & (pbp_df['HOME_STRENGTH'] == '5v5') & (pbp_df['AWAY_STRENGTH'] == '5v5')] home_shots = home_df[(home_df['TEAM'] == home) & (home_df['EVENT'] == 'Shot') & (home_df['EVENT_TYPE'] != 'Block') & (away_df['PERIOD'] == period) & (pbp_df['HOME_STRENGTH'] == '5v5') & (pbp_df['AWAY_STRENGTH'] == '5v5')] home_shots = home_shots.dropna(subset=['X_1', 'Y_1']) home_scored = pbp_df[(pbp_df['TEAM'] == home) & (pbp_df['EVENT'] == 'Shot') & (pbp_df['EVENT_TYPE'] == 'Goal') & (away_df['PERIOD'] == period) & (pbp_df['HOME_STRENGTH'] == '5v5') & (pbp_df['AWAY_STRENGTH'] == '5v5')] if state == '5v5' and period == 4 and int(game_id) < 30000 and int(season_id) <= 20142015: away_shots = away_df[(away_df['TEAM'] == away) & (away_df['EVENT'] == 'Shot') & (away_df['EVENT_TYPE'] != 'Block') & (away_df['PERIOD'] == period) & (pbp_df['HOME_STRENGTH'] == '4v4') & (pbp_df['AWAY_STRENGTH'] == '4v4')] away_shots = away_shots.dropna(subset=['X_1', 'Y_1']) away_scored = pbp_df[(pbp_df['TEAM'] == away) & (pbp_df['EVENT'] == 'Shot') & (pbp_df['EVENT_TYPE'] == 'Goal') & (away_df['PERIOD'] == period) & (pbp_df['HOME_STRENGTH'] == '4v4') & (pbp_df['AWAY_STRENGTH'] == '4v4')] home_shots = home_df[(home_df['TEAM'] == home) & (home_df['EVENT'] == 'Shot') & (home_df['EVENT_TYPE'] != 'Block') & (away_df['PERIOD'] == period) & (pbp_df['HOME_STRENGTH'] == '4v4') & (pbp_df['AWAY_STRENGTH'] == '4v4')] home_shots = home_shots.dropna(subset=['X_1', 'Y_1']) home_scored = pbp_df[(pbp_df['TEAM'] == home) & (pbp_df['EVENT'] == 'Shot') & (pbp_df['EVENT_TYPE'] == 'Goal') & (away_df['PERIOD'] == period) & (pbp_df['HOME_STRENGTH'] == '4v4') & (pbp_df['AWAY_STRENGTH'] == '4v4')] if state == '5v5' and period == 4 and int(game_id) < 30000 and int(season_id) >= 20152016 or state == '5v5' and season_id == 20192020 and period == 4 and int(game_id) > 30000 and int(game_id) <= 30020: away_shots = away_df[(away_df['TEAM'] == away) & (away_df['EVENT'] == 'Shot') & (away_df['EVENT_TYPE'] != 'Block') & (away_df['PERIOD'] == period) & (pbp_df['HOME_STRENGTH'] == '3v3') & (pbp_df['AWAY_STRENGTH'] == '3v3')] away_shots = away_shots.dropna(subset=['X_1', 'Y_1']) away_scored = pbp_df[(pbp_df['TEAM'] == away) & (pbp_df['EVENT'] == 'Shot') & (pbp_df['EVENT_TYPE'] == 'Goal') & (away_df['PERIOD'] == period) & (pbp_df['HOME_STRENGTH'] == '3v3') & (pbp_df['AWAY_STRENGTH'] == '3v3')] home_shots = home_df[(home_df['TEAM'] == home) & (home_df['EVENT'] == 'Shot') & (home_df['EVENT_TYPE'] != 'Block') & (away_df['PERIOD'] == period) & (pbp_df['HOME_STRENGTH'] == '3v3') & (pbp_df['AWAY_STRENGTH'] == '3v3')] home_shots = home_shots.dropna(subset=['X_1', 'Y_1']) home_scored = pbp_df[(pbp_df['TEAM'] == home) & (pbp_df['EVENT'] == 'Shot') & (pbp_df['EVENT_TYPE'] == 'Goal') & (away_df['PERIOD'] == period) & (pbp_df['HOME_STRENGTH'] == '3v3') & (pbp_df['AWAY_STRENGTH'] == '3v3')] if state == '5v5' and int(season_id) != 20192020 and period == 4 and int(game_id) >= 30000 or state == '5v5' and int(season_id) == 20192020 and period == 4 and int(game_id) >= 30021: away_shots = away_df[(away_df['TEAM'] == away) & (away_df['EVENT'] == 'Shot') & (away_df['EVENT_TYPE'] != 'Block') & (away_df['PERIOD'] >= period) & (pbp_df['HOME_STRENGTH'] == '5v5') & (pbp_df['AWAY_STRENGTH'] == '5v5')] away_shots = away_shots.dropna(subset=['X_1', 'Y_1']) away_scored = pbp_df[(pbp_df['TEAM'] == away) & (pbp_df['EVENT'] == 'Shot') & (pbp_df['EVENT_TYPE'] == 'Goal') & (away_df['PERIOD'] >= period) & (pbp_df['HOME_STRENGTH'] == '5v5') & (pbp_df['AWAY_STRENGTH'] == '5v5')] home_shots = home_df[(home_df['TEAM'] == home) & (home_df['EVENT'] == 'Shot') & (home_df['EVENT_TYPE'] != 'Block') & (away_df['PERIOD'] >= period) & (pbp_df['HOME_STRENGTH'] == '5v5') & (pbp_df['AWAY_STRENGTH'] == '5v5')] home_shots = home_shots.dropna(subset=['X_1', 'Y_1']) home_scored = pbp_df[(pbp_df['TEAM'] == home) & (pbp_df['EVENT'] == 'Shot') & (pbp_df['EVENT_TYPE'] == 'Goal') & (away_df['PERIOD'] >= period) & (pbp_df['HOME_STRENGTH'] == '5v5') & (pbp_df['AWAY_STRENGTH'] == '5v5')] if state == 'PP': away_shots = away_df[(away_df['TEAM'] == away) & (away_df['EVENT'] == 'Shot') & (away_df['EVENT_TYPE'] != 'Block') & (away_df['PERIOD'] == period) & (pbp_df['HOME_STATE'] == 'PP') & (pbp_df['AWAY_STATE'] == 'SH')] away_shots = away_shots.dropna(subset=['X_1', 'Y_1']) away_scored = pbp_df[(pbp_df['TEAM'] == away) & (pbp_df['EVENT'] == 'Shot') & (pbp_df['EVENT_TYPE'] == 'Goal') & (away_df['PERIOD'] == period) & (pbp_df['HOME_STATE'] == 'PP') & (pbp_df['AWAY_STATE'] == 'SH')] home_shots = home_df[(home_df['TEAM'] == home) & (home_df['EVENT'] == 'Shot') & (home_df['EVENT_TYPE'] != 'Block') & (away_df['PERIOD'] == period) & (pbp_df['HOME_STATE'] == 'PP') & (pbp_df['AWAY_STATE'] == 'SH')] home_shots = home_shots.dropna(subset=['X_1', 'Y_1']) home_scored = pbp_df[(pbp_df['TEAM'] == home) & (pbp_df['EVENT'] == 'Shot') & (pbp_df['EVENT_TYPE'] == 'Goal') & (away_df['PERIOD'] == period) & (pbp_df['HOME_STATE'] == 'PP') & (pbp_df['AWAY_STATE'] == 'SH')] if state == 'SH': away_shots = away_df[(away_df['TEAM'] == away) & (away_df['EVENT'] == 'Shot') & (away_df['EVENT_TYPE'] != 'Block') & (away_df['PERIOD'] == period) & (pbp_df['HOME_STATE'] == 'SH') & (pbp_df['AWAY_STATE'] == 'PP')] away_shots = away_shots.dropna(subset=['X_1', 'Y_1']) away_scored = pbp_df[(pbp_df['TEAM'] == away) & (pbp_df['EVENT'] == 'Shot') & (pbp_df['EVENT_TYPE'] == 'Goal') & (away_df['PERIOD'] == period) & (pbp_df['HOME_STATE'] == 'SH') & (pbp_df['AWAY_STATE'] == 'PP')] home_shots = home_df[(home_df['TEAM'] == home) & (home_df['EVENT'] == 'Shot') & (home_df['EVENT_TYPE'] != 'Block') & (away_df['PERIOD'] == period) & (pbp_df['HOME_STATE'] == 'SH') & (pbp_df['AWAY_STATE'] == 'PP')] home_shots = home_shots.dropna(subset=['X_1', 'Y_1']) home_scored = pbp_df[(pbp_df['TEAM'] == home) & (pbp_df['EVENT'] == 'Shot') & (pbp_df['EVENT_TYPE'] == 'Goal') & (away_df['PERIOD'] == period) & (pbp_df['HOME_STATE'] == 'SH') & (pbp_df['AWAY_STATE'] == 'PP')] # create a figure to plot fig, ax = plt.subplots(figsize=(8,6)) # style the plot using seaborn sns.set_style("white") # make 2D density plots for each team with their unblocked shots try: away_plot = sns.kdeplot(away_shots.X_1, away_shots.Y_1, shade=True, bw=5, clip=((-88,0),(-42,42)), shade_lowest=False, alpha=0.5, cmap=away_cmap, ax=ax) except: pass try: home_plot = sns.kdeplot(home_shots.X_1, home_shots.Y_1, shade=True, bw=5, clip=((0,88),(-42,42)), shade_lowest=False, alpha=0.5, cmap=home_cmap, ax=ax) except: pass # create the marker that will be used for the legend (note the zorder) teams_df_scored = pd.concat([away_scored, home_scored]) try: scored_marker = teams_df_scored.plot.scatter(x='X_1', y='Y_1', zorder=0, marker=u'$\u2609$', s=120, c=colors[2], edgecolors=colors[2], linewidth='1', alpha=1, label='Scored', ax=ax); except: pass # plot the goals for each team try: away_scored_plot = away_scored.plot.scatter(x='X_1', y='Y_1', zorder=3, marker=u'$\u2609$', s=100, c=colors[2], edgecolors=colors[0], linewidth='1', alpha=1, ax=ax); except: pass try: home_scored_plot = home_scored.plot.scatter(x='X_1', y='Y_1', zorder=3, marker=u'$\u2609$', s=100, c=colors[2], edgecolors=colors[1], linewidth='1', alpha=1, ax=ax); except: pass # set the background image of what will be the plot to the 'rink_image.png' file rink_img = plt.imread("rink_image.png") plt.imshow(rink_img, extent=[-100,100,-42.5,42.5], zorder=0) # eliminate the axis labels plt.axis('off') # add text boxes to indicate home and away sides plt.text(58, 45, home_count + ' USF', color=colors[1], fontsize=12, ha='center') plt.text(-58, 45, away_count + ' USF', color=colors[0], fontsize=12, ha='center') # add text boxes with team names in white and with the team's color in the background fig.text(.435, 0.744, ' ' + away + ' ', fontsize='12', color='white', bbox=dict(facecolor=away_color, edgecolor='None')) fig.text(.535, 0.744, ' ' + home + ' ', fontsize='12', color='white', bbox=dict(facecolor=home_color, edgecolor='None')) fig.text(.500, 0.744, '@', fontsize='12', color='black', bbox=dict(facecolor='white', edgecolor='None')) # set the plot title if state == 'ALL': plt.title(date + ' ' + period_name + ' Period Unblocked Shots\n' + str(toi) + ' Minutes\n\n') if state == '5v5' and period < 4: plt.title(date + ' ' + period_name + ' Period Unblocked Shots\n' + str(toi) + ' 5v5 Minutes\n\n') if state == '5v5' and period == 4 and int(game_id) < 30000 and int(season_id) <= 20142015: plt.title(date + ' ' + period_name + ' Period Unblocked Shots\n' + str(toi) + ' 4v4 Minutes\n\n') if state == '5v5' and period == 4 and int(game_id) < 30000 and int(season_id) >= 20152016 or state == '5v5' and season_id == 20192020 and period == 4 and int(game_id) > 30000 and int(game_id) <= 30020: plt.title(date + ' ' + period_name + ' Period Unblocked Shots\n' + str(toi) + ' 3v3 Minutes\n\n') if state == '5v5' and int(season_id) != 20192020 and period == 4 and int(game_id) >= 30000 or state == '5v5' and int(season_id) == 20192020 and period == 4 and int(game_id) >= 30021: plt.title(date + ' ' + period_name + ' Period Unblocked Shots\n' + str(toi) + ' 5v5 Minutes\n\n') if state == 'PP': plt.title(date + ' ' + period_name + ' Period Unblocked Shots\n' + str(toi) + ' Home PP Minutes\n\n') if state == 'SH': plt.title(date + ' ' + period_name + ' Period Unblocked Shots\n' + str(toi) + ' Away PP Minutes\n\n') # set the location of the plot legend plt.legend(loc='upper center', bbox_to_anchor=(0.5, -0.00), scatterpoints=1, ncol=3).get_frame().set_linewidth(0.0) # set plot axis limits plt.xlim(-100,100) plt.ylim(-42.5,42.5) # eliminate unnecessary whitespace away_plot.axes.get_xaxis().set_visible(False) away_plot.get_yaxis().set_visible(False) ### ### SAVE TO FILE ### if state == 'ALL': plt.savefig(charts_teams_period + 'shots_density_' + period_name + '.png', bbox_inches='tight', pad_inches=0.2) if state == '5v5' and period < 4 or state == '5v5' and int(season_id) != 20192020 and period == 4 and int(game_id) >= 30000 or state == '5v5' and int(season_id) == 20192020 and period == 4 and int(game_id) >= 30021: plt.savefig(charts_teams_period + 'shots_density_5v5_' + period_name + '.png', bbox_inches='tight', pad_inches=0.2) if state == '5v5' and period == 4 and int(game_id) < 30000 and int(season_id) <= 20142015: plt.savefig(charts_teams_period + 'shots_density_4v4_' + period_name + '.png', bbox_inches='tight', pad_inches=0.2) if state == '5v5' and period == 4 and int(game_id) < 30000 and int(season_id) >= 20152016 or state == '5v5' and season_id == 20192020 and period == 4 and int(game_id) > 30000 and int(game_id) <= 30020: plt.savefig(charts_teams_period + 'shots_density_3v3_' + period_name + '.png', bbox_inches='tight', pad_inches=0.2) if state == 'PP': plt.savefig(charts_teams_period + 'shots_density_pp_home_' + period_name + '.png', bbox_inches='tight', pad_inches=0.2) if state == 'SH': plt.savefig(charts_teams_period + 'shots_density_pp_away_' + period_name + '.png', bbox_inches='tight', pad_inches=0.2) # exercise a command-line option to show the current figure if images == 'show': plt.show() ### ### CLOSE ### plt.close(fig) # status update if state == 'ALL': print('Finished density plot for ' + period_name + ' period unblocked shots.') if state == '5v5' and period < 4 or state == '5v5' and int(season_id) != 20192020 and period == 4 and int(game_id) >= 30000 or state == '5v5' and int(season_id) == 20192020 and period == 4 and int(game_id) >= 30021: print('Finished density plot for ' + period_name + ' period unblocked 5v5 shots.') if state == '5v5' and period == 4 and int(game_id) < 30000 and int(season_id) <= 20142015: print('Finished density plot for ' + period_name + ' period unblocked 4v4 shots.') if state == '5v5' and period == 4 and int(game_id) < 30000 and int(season_id) >= 20152016 or state == '5v5' and season_id == 20192020 and period == 4 and int(game_id) > 30000 and int(game_id) <= 30020: print('Finished density plot for ' + period_name + ' period unblocked 3v3 shots.') if state == 'PP': print('Finished density plot for ' + period_name + ' period unblocked shots during a home PP.') if state == 'SH': print('Finished density plot for ' + period_name + ' period unblocked shots during an away PP.')
def parse_ids(season_id, game_id, images): # pull common variables from the parameters file charts_units_pairings_matchups = parameters.charts_units_pairings_matchups files_root = parameters.files_root # generate date and team information schedule_csv = files_root + season_id + "_schedule.csv" schedule_df = pd.read_csv(schedule_csv) schedule_date = schedule_df[(schedule_df['GAME_ID'] == int(game_id))] date = schedule_date['DATE'].item() home = schedule_date['HOME'].item() away = schedule_date['AWAY'].item() teams = [away, home] # create variables that point to the .csv processed stats file for lines pairings_file = files_root + 'stats_units_pairings_onice.csv' pairings_matchups_lines_file = files_root + 'stats_units_pairings_onice_matchups_lines.csv' # create dataframe objects that read in info from the .csv files pairings_df = pd.read_csv(pairings_file) pairings_matchups_lines_df = pd.read_csv(pairings_matchups_lines_file) max_toi = pairings_matchups_lines_df['TOI'].max() # choose colors for each team; set them in a list; generate a custom colormap for each team away_color = dict_team_colors.team_color_1st[away] home_color = dict_team_colors.team_color_1st[home] # change one team's color from its primary option to, depending on the opponent, either a second, third or fourth option try: away_color = mod_switch_colors.switch_team_colors(away, home)[0] home_color = mod_switch_colors.switch_team_colors(away, home)[1] except: pass team_colors = [away_color, home_color] away_cmap = clr.LinearSegmentedColormap.from_list('custom away', [(0, '#ffffff'), (1, away_color)], N=256) home_cmap = clr.LinearSegmentedColormap.from_list('custom home', [(0, '#ffffff'), (1, home_color)], N=256) ### ### 5v5 ### # loop through each team for team in teams: if team == away: team_color = team_colors[0] opponent_color = team_colors[1] team_color_map = plt.cm.get_cmap(away_cmap) opponent_color_map = plt.cm.get_cmap(home_cmap) if team == home: team_color = team_colors[1] opponent_color = team_colors[0] team_color_map = plt.cm.get_cmap(home_cmap) opponent_color_map = plt.cm.get_cmap(away_cmap) # create a lines dataframe; filter for team; sort by time on ice; keep the lines with the 4 highest totals; rank and then invert the rankings team_pairings_df = pairings_df.copy() team_pairings_df = team_pairings_df[(team_pairings_df['TEAM'] == team)] team_pairings_df = team_pairings_df.sort_values(by=['TOI'], ascending=True) team_pairings_df = team_pairings_df.iloc[-3:] team_pairings_df['RANK'] = team_pairings_df['TOI'].rank(method='first') team_pairings_df = team_pairings_df.sort_values(by=['RANK'], ascending=True) team_pairings_df['RANK'] -= 1 team_pairings_list = team_pairings_df.PAIRING.unique() # create a lines dataframe; filter for team team_pairings_matchups_lines_df = pairings_matchups_lines_df.copy() team_pairings_matchups_lines_df = team_pairings_matchups_lines_df[( team_pairings_matchups_lines_df['TEAM'] == team)] max_pairings_toi = team_pairings_matchups_lines_df['TOI'].max() # remove zeros from the differential column team_pairings_matchups_lines_df[ 'xGD'] = team_pairings_matchups_lines_df['xGD'].replace(0, np.NaN) # make expected goals against negative values team_pairings_matchups_lines_df['xGA'] *= -1 # create dataframes for specific lines; sort by time on ice; rank and then invert the rankings team_pairing1_matchups_lines_df = team_pairings_matchups_lines_df.copy( ) team_pairing1_matchups_lines_df = team_pairing1_matchups_lines_df[( team_pairing1_matchups_lines_df['PAIRING'] == team_pairings_list[2] )] team_pairing1_matchups_lines_df.sort_values(by=['TOI'], inplace=True) team_pairing1_matchups_lines_df[ 'RANK'] = team_pairing1_matchups_lines_df['TOI'].rank( method='first') team_pairing1_matchups_lines_df['RANK'] -= 1 team_pairing2_matchups_lines_df = team_pairings_matchups_lines_df.copy( ) team_pairing2_matchups_lines_df = team_pairing2_matchups_lines_df[( team_pairing2_matchups_lines_df['PAIRING'] == team_pairings_list[1] )] team_pairing2_matchups_lines_df.sort_values(by=['TOI'], inplace=True) team_pairing2_matchups_lines_df[ 'RANK'] = team_pairing2_matchups_lines_df['TOI'].rank( method='first') team_pairing2_matchups_lines_df['RANK'] -= 1 team_pairing3_matchups_lines_df = team_pairings_matchups_lines_df.copy( ) team_pairing3_matchups_lines_df = team_pairing3_matchups_lines_df[( team_pairing3_matchups_lines_df['PAIRING'] == team_pairings_list[0] )] team_pairing3_matchups_lines_df.sort_values(by=['TOI'], inplace=True) team_pairing3_matchups_lines_df[ 'RANK'] = team_pairing3_matchups_lines_df['TOI'].rank( method='first') team_pairing3_matchups_lines_df['RANK'] -= 1 # create lists for use in determining the differential marker size team_pairing1_matchups_lines_list = team_pairing1_matchups_lines_df.MATCHUP.unique( ) team_pairing2_matchups_lines_list = team_pairing2_matchups_lines_df.MATCHUP.unique( ) team_pairing3_matchups_lines_list = team_pairing3_matchups_lines_df.MATCHUP.unique( ) if len(team_pairing1_matchups_lines_list) >= 7: pairing1_width = .8 elif len(team_pairing1_matchups_lines_list) == 6: pairing1_width = .7 elif len(team_pairing1_matchups_lines_list) == 5: pairing1_width = .6 elif len(team_pairing1_matchups_lines_list) == 4: pairing1_width = .5 elif len(team_pairing1_matchups_lines_list) == 3: pairing1_width = .4 elif len(team_pairing1_matchups_lines_list) == 2: pairing1_width = .3 elif len(team_pairing1_matchups_lines_list) == 1: pairing1_width = .2 if len(team_pairing2_matchups_lines_list) >= 7: pairing2_width = .8 elif len(team_pairing2_matchups_lines_list) == 6: pairing2_width = .7 elif len(team_pairing2_matchups_lines_list) == 5: pairing2_width = .6 elif len(team_pairing2_matchups_lines_list) == 4: pairing2_width = .5 elif len(team_pairing2_matchups_lines_list) == 3: pairing2_width = .4 elif len(team_pairing2_matchups_lines_list) == 2: pairing2_width = .3 elif len(team_pairing2_matchups_lines_list) == 1: pairing2_width = .2 if len(team_pairing3_matchups_lines_list) >= 7: pairing3_width = .8 elif len(team_pairing3_matchups_lines_list) == 6: pairing3_width = .7 elif len(team_pairing3_matchups_lines_list) == 5: pairing3_width = .6 elif len(team_pairing3_matchups_lines_list) == 4: pairing3_width = .5 elif len(team_pairing3_matchups_lines_list) == 3: pairing3_width = .4 elif len(team_pairing3_matchups_lines_list) == 2: pairing3_width = .3 elif len(team_pairing3_matchups_lines_list) == 1: pairing3_width = .2 # create more pairings dataframes with just the time on ice column; set a max value; scale each line's time on ice relative to the max try: pairing1_matchups_lines_toi = team_pairing1_matchups_lines_df[ 'TOI'] max_pairing1_matchups_lines_toi = pairing1_matchups_lines_toi.max() pairing1_matchups_lines_toi_color = pairing1_matchups_lines_toi / float( max_pairing1_matchups_lines_toi) except: pass try: pairing2_matchups_lines_toi = team_pairing2_matchups_lines_df[ 'TOI'] max_pairing2_matchups_lines_toi = pairing2_matchups_lines_toi.max() pairing2_matchups_lines_toi_color = pairing2_matchups_lines_toi / float( max_pairing2_matchups_lines_toi) except: pass try: pairing3_matchups_lines_toi = team_pairing3_matchups_lines_df[ 'TOI'] max_pairing3_matchups_lines_toi = pairing3_matchups_lines_toi.max() pairing3_matchups_lines_toi_color = pairing3_matchups_lines_toi / float( max_pairing3_matchups_lines_toi) except: pass # connect team and opponent color map colors to each line's scaled time on ice try: pairing1_matchups_lines_toi_color_map_for = team_color_map( pairing1_matchups_lines_toi_color) pairing1_matchups_lines_toi_color_map_against = opponent_color_map( pairing1_matchups_lines_toi_color) except: pass try: pairing2_matchups_lines_toi_color_map_for = team_color_map( pairing2_matchups_lines_toi_color) pairing2_matchups_lines_toi_color_map_against = opponent_color_map( pairing2_matchups_lines_toi_color) except: pass try: pairing3_matchups_lines_toi_color_map_for = team_color_map( pairing3_matchups_lines_toi_color) pairing3_matchups_lines_toi_color_map_against = opponent_color_map( pairing3_matchups_lines_toi_color) except: pass # create a figure with two subplots sharing the y-axis fig = plt.figure(figsize=(8, 8)) grid = plt.GridSpec(4, 8, hspace=.40, wspace=0.50) ax_pairing1_xG = fig.add_subplot(grid[0, 0:-2]) ax_pairing1_toi = fig.add_subplot(grid[0, -1]) ax_pairing2_xG = fig.add_subplot(grid[1, 0:-2]) ax_pairing2_toi = fig.add_subplot(grid[1, -1]) ax_pairing3_xG = fig.add_subplot(grid[2, 0:-2]) ax_pairing3_toi = fig.add_subplot(grid[2, -1]) # set the plot title fig.suptitle(date + ' Pairings vs. Lines On-Ice Expected Goals\n\n') fig.text(.396, 0.910, '5v5 S', color='black', fontsize='10', bbox=dict(facecolor='None', edgecolor='None')) # set the axes titles ax_pairing1_xG.set_title(team_pairings_list[2], fontsize=10, color=team_color) ax_pairing1_toi.set_title('5v5 TOI\n', fontsize=10) ax_pairing2_xG.set_title(team_pairings_list[1], fontsize=10, color=team_color) ax_pairing2_toi.set_title('', fontsize=10) ax_pairing3_xG.set_title(team_pairings_list[0], fontsize=10, color=team_color) ax_pairing3_toi.set_title('', fontsize=10) # create bars for expected goals for and against as well as line markers (to note the expected goals differential) for each line try: pairing1_xGF_plot = team_pairing1_matchups_lines_df.plot.barh( x='MATCHUP', y='xGF', stacked=True, color=pairing1_matchups_lines_toi_color_map_for, width=pairing1_width, legend=None, label='', ax=ax_pairing1_xG) except: pass try: pairing1_xGA_plot = team_pairing1_matchups_lines_df.plot.barh( x='MATCHUP', y='xGA', stacked=True, color=pairing1_matchups_lines_toi_color_map_against, width=pairing1_width, legend=None, label='', ax=ax_pairing1_xG) except: pass try: pairing1_xGD_plot = team_pairing1_matchups_lines_df.plot( x='xGD', y='RANK', marker='|', markersize=15, markerfacecolor='None', markeredgecolor='white', linewidth=0, alpha=1, legend=None, label='', ax=ax_pairing1_xG) except: pass try: pairing2_xGF_plot = team_pairing2_matchups_lines_df.plot.barh( x='MATCHUP', y='xGF', stacked=True, color=pairing2_matchups_lines_toi_color_map_for, width=pairing2_width, legend=None, label='', ax=ax_pairing2_xG) except: pass try: pairing2_xGA_plot = team_pairing2_matchups_lines_df.plot.barh( x='MATCHUP', y='xGA', stacked=True, color=pairing2_matchups_lines_toi_color_map_against, width=pairing2_width, legend=None, label='', ax=ax_pairing2_xG) except: pass try: pairing2_xGD_plot = team_pairing2_matchups_lines_df.plot( x='xGD', y='RANK', marker='|', markersize=15, markerfacecolor='None', markeredgecolor='white', linewidth=0, alpha=1, legend=None, label='', ax=ax_pairing2_xG) except: pass try: pairing3_xGF_plot = team_pairing3_matchups_lines_df.plot.barh( x='MATCHUP', y='xGF', stacked=True, color=pairing3_matchups_lines_toi_color_map_for, width=pairing3_width, legend=None, label='', ax=ax_pairing3_xG) except: pass try: pairing3_xGA_plot = team_pairing3_matchups_lines_df.plot.barh( x='MATCHUP', y='xGA', stacked=True, color=pairing3_matchups_lines_toi_color_map_against, width=pairing3_width, legend=None, label='', ax=ax_pairing3_xG) except: pass try: pairing3_xGD_plot = team_pairing3_matchups_lines_df.plot( x='xGD', y='RANK', marker='|', markersize=15, markerfacecolor='None', markeredgecolor='white', linewidth=0, alpha=1, legend=None, label='', ax=ax_pairing3_xG) except: pass # plot the bars for time on ice try: toi_pairing1 = team_pairing1_matchups_lines_df.plot.barh( x='MATCHUP', y='TOI', color='white', edgecolor=team_color, width=pairing1_width, legend=None, label='', ax=ax_pairing1_toi) except: pass try: toi_pairing2 = team_pairing2_matchups_lines_df.plot.barh( x='MATCHUP', y='TOI', color='white', edgecolor=team_color, width=pairing2_width, legend=None, label='', ax=ax_pairing2_toi) except: pass try: toi_pairing3 = team_pairing3_matchups_lines_df.plot.barh( x='MATCHUP', y='TOI', color='white', edgecolor=team_color, width=pairing3_width, legend=None, label='', ax=ax_pairing3_toi) except: pass # remove the labels for each subplot ax_pairing1_xG.set_xlabel('') ax_pairing1_xG.set_ylabel('') ax_pairing1_toi.set_xlabel('') ax_pairing1_toi.set_ylabel('') ax_pairing2_xG.set_xlabel('') ax_pairing2_xG.set_ylabel('') ax_pairing2_toi.set_xlabel('') ax_pairing2_toi.set_ylabel('') ax_pairing3_xG.set_xlabel('') ax_pairing3_xG.set_ylabel('') ax_pairing3_toi.set_xlabel('') ax_pairing3_toi.set_ylabel('') # set vertical indicators for break-even expected goals differential ax_pairing1_xG.axvspan(0, 0, ymin=0, ymax=1, alpha=.25, linestyle=':', color='black') ax_pairing2_xG.axvspan(0, 0, ymin=0, ymax=1, alpha=.25, linestyle=':', color='black') ax_pairing3_xG.axvspan(0, 0, ymin=0, ymax=1, alpha=.25, linestyle=':', color='black') # change the tick parameters ax_pairing1_xG.tick_params( axis='both', which='both', bottom=False, top=False, left=False, labelleft=True, # labels along the left edge are on labelbottom=False) ax_pairing1_toi.tick_params( axis='both', which='both', bottom=False, top=False, left=False, labelleft=False, # labels along the left edge are off labelbottom=False) ax_pairing2_xG.tick_params( axis='both', which='both', bottom=False, top=False, left=False, labelleft=True, # labels along the left edge are on labelbottom=False) ax_pairing2_toi.tick_params( axis='both', which='both', bottom=False, top=False, left=False, labelleft=False, # labels along the left edge are off labelbottom=False) ax_pairing3_xG.tick_params( axis='both', which='both', bottom=False, top=False, left=False, labelleft=True, # labels along the left edge are on labelbottom=True) ax_pairing3_toi.tick_params( axis='both', which='both', bottom=False, top=False, left=False, labelleft=False, # labels along the left edge are off labelbottom=True) # change the y-axis label colors ax_pairing1_xG.tick_params(axis='y', which='both', labelcolor=opponent_color) ax_pairing2_xG.tick_params(axis='y', which='both', labelcolor=opponent_color) ax_pairing3_xG.tick_params(axis='y', which='both', labelcolor=opponent_color) # create a list of x-axis tick values contingent on the max values for expected goals for and against xGF_max = pairings_matchups_lines_df['xGF'] xGF_max = xGF_max.max() xGA_max = pairings_matchups_lines_df['xGA'] xGA_max = xGA_max.max() xG_tickmax = int() if xGF_max >= xGA_max: xG_tickmax = xGF_max elif xGF_max < xGA_max: xG_tickmax = xGA_max xG_ticklabels = [] if xG_tickmax > 0 and xG_tickmax <= 0.5: xG_ticklabels = [ -0.5, -0.4, -0.3, -0.2, -0.1, 0.0, 0.1, 0.2, 0.3, 0.4, 0.5 ] if xG_tickmax > 0.5 and xG_tickmax <= 1: xG_ticklabels = [ -1.0, -0.8, -0.6, -0.4, -0.2, 0.0, 0.2, 0.4, 0.6, 0.8, 1.0 ] if xG_tickmax > 1 and xG_tickmax <= 1.5: xG_ticklabels = [ -1.5, -1.2, -0.9, -0.6, -0.3, 0.0, 0.3, 0.6, 0.9, 1.2, 1.5 ] if xG_tickmax > 1.5 and xG_tickmax <= 2: xG_ticklabels = [ -2.0, -1.6, -1.2, -0.8, -0.4, 0.0, 0.4, 0.8, 1.2, 1.6, 2.0 ] if xG_tickmax > 2 and xG_tickmax <= 2.5: xG_ticklabels = [ -2.5, -2.0, -1.5, -1.0, -0.5, 0.0, 0.5, 1.0, 1.5, 2.0, 2.5 ] if xG_tickmax > 2.5 and xG_tickmax <= 3: xG_ticklabels = [ -3.0, -2.4, -1.8, -1.2, -0.6, 0.0, 0.6, 1.2, 1.8, 2.4, 3.0 ] if xG_tickmax > 3 and xG_tickmax <= 3.5: xG_ticklabels = [ -3.5, -2.8, -2.1, -1.4, -0.7, 0.0, 0.7, 1.4, 2.1, 2.8, 3.5 ] if xG_tickmax > 3.5 and xG_tickmax <= 4: xG_ticklabels = [ -4.0, -3.2, -2.4, -1.6, -0.8, 0.0, 0.8, 1.6, 2.4, 3.2, 4.0 ] toi_tickmax = max_toi toi_ticklabels = [] if toi_tickmax <= 2: toi_ticklabels = [0, 2] if toi_tickmax > 2 and toi_tickmax <= 4: toi_ticklabels = [0, 4] if toi_tickmax > 4 and toi_tickmax <= 6: toi_ticklabels = [0, 6] if toi_tickmax > 6 and toi_tickmax <= 8: toi_ticklabels = [0, 8] if toi_tickmax > 8 and toi_tickmax <= 10: toi_ticklabels = [0, 10] if toi_tickmax > 10 and toi_tickmax <= 12: toi_ticklabels = [0, 12] if toi_tickmax > 12 and toi_tickmax <= 14: toi_ticklabels = [0, 14] if toi_tickmax > 14 and toi_tickmax <= 16: toi_ticklabels = [0, 16] if toi_tickmax > 16 and toi_tickmax <= 18: toi_ticklabels = [0, 18] if toi_tickmax > 18 and toi_tickmax <= 20: toi_ticklabels = [0, 20] # set vertical indicator for midpoint of time on ice max ax_pairing1_toi.axvspan(toi_ticklabels[1] / 2, toi_ticklabels[1] / 2, ymin=0, ymax=1, zorder=0, alpha=0.25, linestyle=':', color='black') ax_pairing1_toi.axvspan(toi_ticklabels[1], toi_ticklabels[1], ymin=0, ymax=1, zorder=0, alpha=0.25, linestyle=':', color='black') ax_pairing2_toi.axvspan(toi_ticklabels[1] / 2, toi_ticklabels[1] / 2, ymin=0, ymax=1, zorder=0, alpha=0.25, linestyle=':', color='black') ax_pairing2_toi.axvspan(toi_ticklabels[1], toi_ticklabels[1], ymin=0, ymax=1, zorder=0, alpha=0.25, linestyle=':', color='black') ax_pairing3_toi.axvspan(toi_ticklabels[1] / 2, toi_ticklabels[1] / 2, ymin=0, ymax=1, zorder=0, alpha=0.25, linestyle=':', color='black') ax_pairing3_toi.axvspan(toi_ticklabels[1], toi_ticklabels[1], ymin=0, ymax=1, zorder=0, alpha=0.25, linestyle=':', color='black') # use the newly-minted x-ticklabels to ensure the x-axis labels will always display as integers ax_pairing1_xG.set_xticks(xG_ticklabels, minor=False) ax_pairing1_toi.set_xticks(toi_ticklabels, minor=False) ax_pairing2_xG.set_xticks(xG_ticklabels, minor=False) ax_pairing2_toi.set_xticks(toi_ticklabels, minor=False) ax_pairing3_xG.set_xticks(xG_ticklabels, minor=False) ax_pairing3_toi.set_xticks(toi_ticklabels, minor=False) # remove the borders to each subplot ax_pairing1_xG.spines["top"].set_visible(False) ax_pairing1_xG.spines["bottom"].set_visible(False) ax_pairing1_xG.spines["right"].set_visible(False) ax_pairing1_xG.spines["left"].set_visible(False) ax_pairing1_toi.spines["top"].set_visible(False) ax_pairing1_toi.spines["bottom"].set_visible(False) ax_pairing1_toi.spines["right"].set_visible(False) ax_pairing1_toi.spines["left"].set_visible(False) ax_pairing2_xG.spines["top"].set_visible(False) ax_pairing2_xG.spines["bottom"].set_visible(False) ax_pairing2_xG.spines["right"].set_visible(False) ax_pairing2_xG.spines["left"].set_visible(False) ax_pairing2_toi.spines["top"].set_visible(False) ax_pairing2_toi.spines["bottom"].set_visible(False) ax_pairing2_toi.spines["right"].set_visible(False) ax_pairing2_toi.spines["left"].set_visible(False) ax_pairing3_xG.spines["top"].set_visible(False) ax_pairing3_xG.spines["bottom"].set_visible(False) ax_pairing3_xG.spines["right"].set_visible(False) ax_pairing3_xG.spines["left"].set_visible(False) ax_pairing3_toi.spines["top"].set_visible(False) ax_pairing3_toi.spines["bottom"].set_visible(False) ax_pairing3_toi.spines["right"].set_visible(False) ax_pairing3_toi.spines["left"].set_visible(False) # add a legend for the shot type markers from matplotlib.lines import Line2D elements = [ Line2D([0], [0], marker='|', markersize=13, markerfacecolor='None', markeredgecolor='black', linewidth=0, alpha=1, label='Differential') ] ax_pairing3_xG.legend(handles=elements, loc='center', bbox_to_anchor=(.5, -.50), ncol=2).get_frame().set_linewidth(0.0) # add text boxes with team names in white and with the team's color in the background fig.text(.425, 0.936, ' ' + away + ' ', color='white', fontsize='12', bbox=dict(facecolor=away_color, edgecolor='None')) fig.text(.525, 0.936, ' ' + home + ' ', fontsize='12', color='white', bbox=dict(facecolor=home_color, edgecolor='None')) fig.text(.490, 0.936, '@', color='black', fontsize='12', bbox=dict(facecolor='white', edgecolor='None')) ### ### SAVE TO FILE ### if team == away: plt.savefig(charts_units_pairings_matchups + 'onice_xg_away_pairings_matchups_lines.png', bbox_inches='tight', pad_inches=0.2) elif team == home: plt.savefig(charts_units_pairings_matchups + 'onice_xg_home_pairings_matchups_lines.png', bbox_inches='tight', pad_inches=0.2) # exercise a command-line option to show the current figure if images == 'show': plt.show() ### ### CLOSE ### plt.close(fig) # status update print('Plotting ' + team + ' pairings vs. lines 5v5 on-ice xG.') # status update print('Finished plotting the 5v5 on-ice xG for pairings vs. lines.')
def parse_ids(season_id, game_id, images): # pull common variables from the parameters file charts_teams = parameters.charts_teams files_root = parameters.files_root # generate date and team information schedule_csv = files_root + season_id + "_schedule.csv" schedule_df = pd.read_csv(schedule_csv) schedule_date = schedule_df[(schedule_df['GAME_ID'] == int(game_id))] date = schedule_date['DATE'].item() home = schedule_date['HOME'].item() away = schedule_date['AWAY'].item() # create variables that point to the .csv livefeed, play-by-play and time-on-ice files livefeed_file = files_root + 'livefeed.json' pbp_file = files_root + 'pbp.csv' toi_file = files_root + 'TOI_matrix.csv' # opens the game's livefeed (JSON) file to create a few shared variables with open(livefeed_file) as livefeed_json: livefeed_data = json.load(livefeed_json) livefeed_parsed = livefeed_data try: game_status = livefeed_parsed["liveData"]["linescore"][ "currentPeriodTimeRemaining"] currentperiod = livefeed_parsed["liveData"]["linescore"][ "currentPeriod"] if game_status != 'Final' and currentperiod < 4: game_type = 'Regulation' elif game_status != 'Final' and currentperiod > 3: game_type = 'Overtime' elif game_status == 'Final' and currentperiod < 4: game_type = 'Regulation' elif game_status == 'Final' and currentperiod > 3: game_type = 'Overtime' except: game_type = '' # create a dataframe object that reads in the play-by-play file pbp_df = pd.read_csv(pbp_file) # create a dataframe object that reads in the time on ice file; filter a copy for seconds of special teams play (for later generation of shaded bars) toi_df = pd.read_csv(toi_file) pp_toi = toi_df.copy() pp_toi_df = pp_toi[(pp_toi['HOME_STATE'] == 'PP') | (pp_toi['AWAY_STATE'] == 'PP')] home_pp = pp_toi_df[(pp_toi_df['HOME_STATE'] == 'PP')] away_pp = pp_toi_df[(pp_toi_df['AWAY_STATE'] == 'PP')] # choose colors for each team and the legend; set them in a list legend_color = 'black' away_color = dict_team_colors.team_color_1st[away] home_color = dict_team_colors.team_color_1st[home] # change one team's color from its primary option to, depending on the opponent, either a second, third or fourth option try: away_color = mod_switch_colors.switch_team_colors(away, home)[0] home_color = mod_switch_colors.switch_team_colors(away, home)[1] except: pass colors = [away_color, home_color, legend_color] ### ### ALL ### # create a copy of the play-by-play dataframe; filter for shots; remove extraneous columns gameflow = pbp_df.copy() gameflow_df = gameflow[(gameflow['EVENT'] == 'Shot') & (gameflow['EVENT_TYPE'] != 'Block')] gameflow_df = gameflow_df.drop(columns=[ 'HOME_RESULT', 'AWAY_RESULT', 'HOME_GOALS', 'AWAY_GOALS', 'HOME_SCOREDIFF', 'AWAY_SCOREDIFF', 'EVENT_DETAIL', 'HOME_ZONE', 'AWAY_ZONE', 'PLAYER_A', 'PLAYER_B', 'PLAYER_C', 'X_1', 'Y_1', 'X_2', 'Y_2', 'HOMEON_1', 'HOMEON_2', 'HOMEON_3', 'HOMEON_4', 'HOMEON_5', 'HOMEON_6', 'AWAYON_1', 'AWAYON_2', 'AWAYON_3', 'AWAYON_4', 'AWAYON_5', 'AWAYON_6' ]) # get the xG value for each instance; add a dataframe column with the cumulative number home_event_xG = (np.where( (gameflow_df['TEAM'] == home) & (gameflow_df['EVENT_TYPE'] != 'Block'), gameflow_df['xG'], 0)) gameflow_df['HOME_xG'] = home_event_xG.cumsum() away_event_xG = (np.where( (gameflow_df['TEAM'] == away) & (gameflow_df['EVENT_TYPE'] != 'Block'), gameflow_df['xG'], 0)) gameflow_df['AWAY_xG'] = away_event_xG.cumsum() # for each instance of an unblocked shot, find the difference in xG for each team up to that point; add a dataframe column with the cumulative differential home_xG_diff = home_event_xG - away_event_xG gameflow_df['HOME_xG_DIFF'] = home_xG_diff.cumsum() away_xG_diff = away_event_xG - home_event_xG gameflow_df['AWAY_xG_DIFF'] = away_xG_diff.cumsum() # duplicate the xG differential columns; set negative values for each team to zero (in order to prettify the step plots) gameflow_df['HOME_xG_DIFF_COPY_1'] = gameflow_df['HOME_xG_DIFF'] gameflow_df.loc[(gameflow_df.HOME_xG_DIFF < 0), ['HOME_xG_DIFF_COPY_1']] = 0 gameflow_df gameflow_df['HOME_xG_DIFF_COPY_2'] = gameflow_df['HOME_xG_DIFF'] gameflow_df.loc[(gameflow_df.HOME_xG_DIFF > 0), ['HOME_xG_DIFF_COPY_2']] = 0 gameflow_df # copy the gameflow dataframe; filter for goals goals = gameflow_df.copy() goals_df = goals[(goals['EVENT_TYPE'] == 'Goal')] home_goals = goals_df[(goals_df['TEAM'] == home)] away_goals = goals_df[(goals_df['TEAM'] == away)] # create a figure to plot fig, ax = plt.subplots(figsize=(8, 6)) # create a subset for each team, contingent on the home team's cumulative xG differential, of the amended gameflow dataframe try: home_advantage = gameflow_df[(gameflow_df['HOME_xG_DIFF_COPY_1'] >= 0)] except: pass try: away_advantage = gameflow_df[(gameflow_df['HOME_xG_DIFF_COPY_2'] <= 0)] except: pass # plot each team's cumulative xG differential; make these lines transparent as they are only needed to create the y-axis scale try: home_xG_diff_plot = gameflow_df.plot(x='SECONDS_GONE', y='HOME_xG_DIFF', color=colors[1], linewidth=2, alpha=0, legend=False, label='', ax=ax) except: pass try: away_xG_diff_plot = gameflow_df.plot(x='SECONDS_GONE', y='AWAY_xG_DIFF', color=colors[0], linewidth=2, alpha=0, legend=False, label='', ax=ax) except: pass # plot stepped lines for each team's subset try: home_advantage_plot_step = plt.step( x=home_advantage['SECONDS_GONE'], y=home_advantage['HOME_xG_DIFF_COPY_1'], linewidth=1, alpha=1, color=colors[1], label='') except: pass try: away_advantage_plot_step = plt.step( x=away_advantage['SECONDS_GONE'], y=away_advantage['HOME_xG_DIFF_COPY_2'], linewidth=1, alpha=1, color=colors[0], label='') except: pass # plot goal events in such a way that they will render exclusively as markers overlaying the stepped line plots try: home_goals_plot = home_goals.plot(x='SECONDS_GONE', y='HOME_xG_DIFF', color=colors[1], linewidth=0, alpha=1, legend=False, label='', marker=u'$\u2609$', markersize=12, ax=ax) except: pass try: away_goals_plot = away_goals.plot(x='SECONDS_GONE', y='HOME_xG_DIFF', color=colors[0], linewidth=0, alpha=1, legend=False, label='', marker=u'$\u2609$', markersize=12, ax=ax) except: pass # create a contingency for situations in which one team has yet to or, if the game is final, did not score if home_goals.empty == False: goals_label = home_goals.plot(x='SECONDS_GONE', y='HOME_xG_DIFF', zorder=0, color=colors[2], linewidth=0, alpha=1, marker=u'$\u2609$', markersize=12, label='Goal', ax=ax) elif home_goals.empty == True and away_goals.empty == False: goals_label = away_goals.plot(x='SECONDS_GONE', y='HOME_xG_DIFF', zorder=0, color=colors[2], linewidth=0, alpha=1, marker=u'$\u2609$', markersize=12, label='Goal', ax=ax) # set the break-even line if game_type == 'Regulation': breakeven_x, breakeven_y = [-0, 3600], [0, 0] elif game_type == 'Overtime': breakeven_x, breakeven_y = [-0, 3900], [0, 0] clear_breakeven = plt.plot(breakeven_x, breakeven_y, linewidth=1, color='white', alpha=1) breakeven = plt.plot(breakeven_x, breakeven_y, linewidth=1, color=colors[2], alpha=0.15) # set vertical indicators for the end of each period ax.axvspan(1200, 1201, ymin=0, ymax=1, alpha=1, color=colors[2], linewidth=0, label='Power Play') ax.axvspan(1200, 1201, ymin=0, ymax=1, alpha=0.15, color=colors[2]) ax.axvspan(2400, 2401, ymin=0, ymax=1, alpha=0.15, color=colors[2]) ax.axvspan(3600, 3601, ymin=0, ymax=1, alpha=0.15, color=colors[2]) if game_type == 'Overtime': ax.axvspan(3900, 3901, ymin=0, ymax=1, alpha=0.15, color=colors[2]) # set vertical shaded areas indcating power play situations for second in home_pp['SECONDS_GONE']: ax.axvspan(second, second + 1, ymin=0, ymax=1, alpha=0.025, color=colors[1]) for second in away_pp['SECONDS_GONE']: ax.axvspan(second, second + 1, ymin=0, ymax=1, alpha=0.025, color=colors[0]) # eliminate unnecessary whitespace on the first axes ax.axes.get_xaxis().set_visible(False) ax.axes.get_yaxis().set_visible(True) # adjust the visibility of the first axes spines ax.spines["top"].set_visible(False) ax.spines["bottom"].set_visible(False) ax.spines["right"].set_visible(False) ax.spines["left"].set_visible(False) # remove ticks belonging to the first axes ax.tick_params(axis='y', which="both", left=False, right=False, length=0) # create a second axes that shares the same x-axis ax2 = ax.twinx() # plot each team's cumulative xG differential; make these lines transparent as they are only needed to create the second y-axis scale home_xG_diff_plot = gameflow_df.plot(x='SECONDS_GONE', y='HOME_xG_DIFF', color=colors[1], linewidth=2, alpha=0, legend=False, ax=ax2) away_xG_diff_plot = gameflow_df.plot(x='SECONDS_GONE', y='AWAY_xG_DIFF', color=colors[0], linewidth=2, alpha=0, legend=False, ax=ax2) # eliminate unnecessary whitespace on the second axes ax2.axes.get_xaxis().set_visible(False) ax2.axes.get_yaxis().set_visible(True) # adjust the visibility of the second axes spines ax2.spines["top"].set_visible(False) ax2.spines["bottom"].set_visible(False) ax2.spines["right"].set_visible(False) ax2.spines["left"].set_visible(False) # get the maximum and minimum values in the xG differential column in order to set the y-values for the period labels max_home_xG_diff = gameflow_df['HOME_xG_DIFF'].max() min_home_xG_diff = gameflow_df['HOME_xG_DIFF'].min() max_away_xG_diff = gameflow_df['AWAY_xG_DIFF'].max() min_away_xG_diff = gameflow_df['AWAY_xG_DIFF'].min() # remove ticks to the second axes ax2.tick_params(axis='y', which="both", left=False, right=False, length=0) # invert the second y-axis ax2.invert_yaxis() # set the team label if max_home_xG_diff > max_away_xG_diff and game_type == 'Regulation': plt.text(-660, min_away_xG_diff, home, fontsize=12, color=colors[1], alpha=1) plt.text(4060, max_home_xG_diff, away, fontsize=12, color=colors[0], alpha=1) elif max_home_xG_diff < max_away_xG_diff and game_type == 'Regulation': plt.text(-660, min_home_xG_diff, home, fontsize=12, color=colors[1], alpha=1) plt.text(4060, max_away_xG_diff, away, fontsize=12, color=colors[0], alpha=1) if max_home_xG_diff > max_away_xG_diff and game_type == 'Overtime': plt.text(-660, min_away_xG_diff, home, fontsize=12, color=colors[1], alpha=1) plt.text(4350, max_home_xG_diff, away, fontsize=12, color=colors[0], alpha=1) elif max_home_xG_diff < max_away_xG_diff and game_type == 'Overtime': plt.text(-660, min_home_xG_diff, home, fontsize=12, color=colors[1], alpha=1) plt.text(4350, max_away_xG_diff, away, fontsize=12, color=colors[0], alpha=1) # set the period names as labels if game_type == 'Regulation': plt.text(0.33, -0.05, '1st', fontsize=12, color=colors[2], alpha=1, transform=ax.transAxes) plt.text(0.63, -0.05, '2nd', fontsize=12, color=colors[2], alpha=1, transform=ax.transAxes) plt.text(0.93, -0.05, '3rd', fontsize=12, color=colors[2], alpha=1, transform=ax.transAxes) if game_type == 'Overtime': plt.text(0.31, -0.05, '1st', fontsize=12, color=colors[2], alpha=1, transform=ax.transAxes) plt.text(0.58, -0.05, '2nd', fontsize=12, color=colors[2], alpha=1, transform=ax.transAxes) plt.text(0.86, -0.05, '3rd', fontsize=12, color=colors[2], alpha=1, transform=ax.transAxes) plt.text(0.94, -0.05, 'OT', fontsize=12, color=colors[2], alpha=1, transform=ax.transAxes) # set the plot title plt.title(date + ' Gameflow: Expected Goals\n\n') # set the location of the plot legend ax.legend(loc='center', bbox_to_anchor=(.5, -0.10), ncol=2).get_frame().set_linewidth(0.0) # add text boxes with team names in white and with the team's color in the background fig.text(.435, 0.916, ' ' + away + ' ', fontsize='12', color='white', bbox=dict(facecolor=away_color, edgecolor='None')) fig.text(.535, 0.916, ' ' + home + ' ', fontsize='12', color='white', bbox=dict(facecolor=home_color, edgecolor='None')) fig.text(.501, 0.916, '@', fontsize='12', color='black', bbox=dict(facecolor='white', edgecolor='None')) ### ### SAVE TO FILE ### plt.savefig(charts_teams + 'shots_gameflow_xg.png', bbox_inches='tight', pad_inches=0.2) # exercise a command-line option to show the current figure if images == 'show': plt.show() ### ### CLOSE ### plt.close(fig) # status update print( 'Finished plotting the xG differential game flow for all situations.') ### ### 5v5 ### # create a copy of the play-by-play dataframe; filter for shots and game state; remove extraneous columns gameflow = pbp_df.copy() gameflow_df = gameflow[(gameflow['EVENT'] == 'Shot') & (gameflow['EVENT_TYPE'] != 'Block') & (gameflow['HOME_STRENGTH'] == '5v5')] gameflow_df = gameflow_df.drop(columns=[ 'HOME_RESULT', 'AWAY_RESULT', 'HOME_GOALS', 'AWAY_GOALS', 'HOME_SCOREDIFF', 'AWAY_SCOREDIFF', 'EVENT_DETAIL', 'HOME_ZONE', 'AWAY_ZONE', 'PLAYER_A', 'PLAYER_B', 'PLAYER_C', 'X_1', 'Y_1', 'X_2', 'Y_2', 'HOMEON_1', 'HOMEON_2', 'HOMEON_3', 'HOMEON_4', 'HOMEON_5', 'HOMEON_6', 'AWAYON_1', 'AWAYON_2', 'AWAYON_3', 'AWAYON_4', 'AWAYON_5', 'AWAYON_6' ]) # get the xG value for each instance; add a dataframe column with the cumulative number home_event_xG = (np.where( (gameflow_df['TEAM'] == home) & (gameflow_df['EVENT_TYPE'] != 'Block'), gameflow_df['xG'], 0)) gameflow_df['HOME_xG'] = home_event_xG.cumsum() away_event_xG = (np.where( (gameflow_df['TEAM'] == away) & (gameflow_df['EVENT_TYPE'] != 'Block'), gameflow_df['xG'], 0)) gameflow_df['AWAY_xG'] = away_event_xG.cumsum() # for each instance of an unblocked shot, find the difference in xG for each team up to that point; add a dataframe column with the cumulative differential home_xG_diff = home_event_xG - away_event_xG gameflow_df['HOME_xG_DIFF'] = home_xG_diff.cumsum() away_xG_diff = away_event_xG - home_event_xG gameflow_df['AWAY_xG_DIFF'] = away_xG_diff.cumsum() # duplicate the xG differential columns; set negative values for each team to zero (in order to prettify the step plots) gameflow_df['HOME_xG_DIFF_COPY_1'] = gameflow_df['HOME_xG_DIFF'] gameflow_df.loc[(gameflow_df.HOME_xG_DIFF < 0), ['HOME_xG_DIFF_COPY_1']] = 0 gameflow_df gameflow_df['HOME_xG_DIFF_COPY_2'] = gameflow_df['HOME_xG_DIFF'] gameflow_df.loc[(gameflow_df.HOME_xG_DIFF > 0), ['HOME_xG_DIFF_COPY_2']] = 0 gameflow_df # copy the gameflow dataframe; filter for goals goals = gameflow_df.copy() goals_df = goals[(goals['EVENT_TYPE'] == 'Goal')] home_goals = goals_df[(goals_df['TEAM'] == home)] away_goals = goals_df[(goals_df['TEAM'] == away)] # create a figure to plot fig, ax = plt.subplots(figsize=(8, 6)) # create a subset for each team, contingent on the home team's cumulative xG differential, of the amended gameflow dataframe try: home_advantage = gameflow_df[(gameflow_df['HOME_xG_DIFF_COPY_1'] >= 0)] except: pass try: away_advantage = gameflow_df[(gameflow_df['HOME_xG_DIFF_COPY_2'] <= 0)] except: pass # plot each team's cumulative xG differential; make these lines transparent as they are only needed to create the y-axis scale try: home_xG_diff_plot = gameflow_df.plot(x='SECONDS_GONE', y='HOME_xG_DIFF', color=colors[1], linewidth=2, alpha=0, legend=False, label='', ax=ax) except: pass try: away_xG_diff_plot = gameflow_df.plot(x='SECONDS_GONE', y='AWAY_xG_DIFF', color=colors[0], linewidth=2, alpha=0, legend=False, label='', ax=ax) except: pass # plot stepped lines for each team's subset try: home_advantage_plot_step = plt.step( x=home_advantage['SECONDS_GONE'], y=home_advantage['HOME_xG_DIFF_COPY_1'], linewidth=1, alpha=1, color=colors[1], label='') except: pass try: away_advantage_plot_step = plt.step( x=away_advantage['SECONDS_GONE'], y=away_advantage['HOME_xG_DIFF_COPY_2'], linewidth=1, alpha=1, color=colors[0], label='') except: pass # plot goal events in such a way that they will render exclusively as markers overlaying the stepped line plots try: home_goals_plot = home_goals.plot(x='SECONDS_GONE', y='HOME_xG_DIFF', color=colors[1], linewidth=0, alpha=1, legend=False, label='', marker=u'$\u2609$', markersize=12, ax=ax) except: pass try: away_goals_plot = away_goals.plot(x='SECONDS_GONE', y='HOME_xG_DIFF', color=colors[0], linewidth=0, alpha=1, legend=False, label='', marker=u'$\u2609$', markersize=12, ax=ax) except: pass # create a contingency for situations in which one team has yet to or, if the game is final, did not score if home_goals.empty == False: goals_label = home_goals.plot(x='SECONDS_GONE', y='HOME_xG_DIFF', zorder=0, color=colors[2], linewidth=0, alpha=1, marker=u'$\u2609$', markersize=12, label='Goal', ax=ax) elif home_goals.empty == True and away_goals.empty == False: goals_label = away_goals.plot(x='SECONDS_GONE', y='HOME_xG_DIFF', zorder=0, color=colors[2], linewidth=0, alpha=1, marker=u'$\u2609$', markersize=12, label='Goal', ax=ax) # set the break-even line breakeven_x, breakeven_y = [-0, 3600], [0, 0] clear_breakeven = plt.plot(breakeven_x, breakeven_y, linewidth=1, color='white', alpha=1) breakeven = plt.plot(breakeven_x, breakeven_y, linewidth=1, color=colors[2], alpha=0.15) # set vertical indicators for the end of each period ax.axvspan(1200, 1201, ymin=0, ymax=1, alpha=1, color=colors[2], linewidth=0, label='Power Play') ax.axvspan(1200, 1201, ymin=0, ymax=1, alpha=0.15, color=colors[2]) ax.axvspan(2400, 2401, ymin=0, ymax=1, alpha=0.15, color=colors[2]) ax.axvspan(3600, 3601, ymin=0, ymax=1, alpha=0.15, color=colors[2]) # set vertical shaded areas indcating power play and empty-net situations for second in home_pp['SECONDS_GONE']: ax.axvspan(second, second + 1, ymin=0, ymax=1, alpha=0.025, color=colors[1]) for second in away_pp['SECONDS_GONE']: ax.axvspan(second, second + 1, ymin=0, ymax=1, alpha=0.025, color=colors[0]) # eliminate unnecessary whitespace on the first axes ax.axes.get_xaxis().set_visible(False) ax.axes.get_yaxis().set_visible(True) # adjust the visibility of the first axes spines ax.spines["top"].set_visible(False) ax.spines["bottom"].set_visible(False) ax.spines["right"].set_visible(False) ax.spines["left"].set_visible(False) # remove ticks to the first axes ax.tick_params(axis='y', which="both", left=False, right=False, length=0) # create a second axes that shares the same x-axis ax2 = ax.twinx() # plot each team's cumulative shot differential; make these lines transparent as they are only needed to create the second y-axis scale try: home_xG_diff_plot = gameflow_df.plot(x='SECONDS_GONE', y='HOME_xG_DIFF', color=colors[1], linewidth=2, alpha=0, legend=False, ax=ax2) except: pass try: away_xG_diff_plot = gameflow_df.plot(x='SECONDS_GONE', y='AWAY_xG_DIFF', color=colors[0], linewidth=2, alpha=0, legend=False, ax=ax2) except: pass # eliminate unnecessary whitespace on the second axes ax2.axes.get_xaxis().set_visible(False) ax2.axes.get_yaxis().set_visible(True) # adjust the visibility of the second axes spines ax2.spines["top"].set_visible(False) ax2.spines["bottom"].set_visible(False) ax2.spines["right"].set_visible(False) ax2.spines["left"].set_visible(False) # get the maximum and minimum values in the xG differential column in order to set the y-values for the period labels max_home_xG_diff = gameflow_df['HOME_xG_DIFF'].max() min_home_xG_diff = gameflow_df['HOME_xG_DIFF'].min() max_away_xG_diff = gameflow_df['AWAY_xG_DIFF'].max() min_away_xG_diff = gameflow_df['AWAY_xG_DIFF'].min() # remove ticks to the second axes ax2.tick_params(axis='y', which="both", left=False, right=False, length=0) # invert the second y-axis ax2.invert_yaxis() # set the team labels if max_home_xG_diff > max_away_xG_diff: plt.text(-660, min_away_xG_diff, home, fontsize=12, color=colors[1], alpha=1) plt.text(4060, max_home_xG_diff, away, fontsize=12, color=colors[0], alpha=1) elif max_home_xG_diff < max_away_xG_diff: plt.text(-660, min_home_xG_diff, home, fontsize=12, color=colors[1], alpha=1) plt.text(4060, max_away_xG_diff, away, fontsize=12, color=colors[0], alpha=1) # set the period names as labels plt.text(0.33, -0.05, '1st', fontsize=12, color=colors[2], alpha=1, transform=ax.transAxes) plt.text(0.63, -0.05, '2nd', fontsize=12, color=colors[2], alpha=1, transform=ax.transAxes) plt.text(0.93, -0.05, '3rd', fontsize=12, color=colors[2], alpha=1, transform=ax.transAxes) # set the plot title plt.title(date + ' 5v5 Gameflow: Expected Goals\n\n') # set the location of the plot legend ax.legend(loc='center', bbox_to_anchor=(.5, -0.10), ncol=2).get_frame().set_linewidth(0.0) # add text boxes with team names in white and with the team's color in the background fig.text(.435, 0.916, ' ' + away + ' ', fontsize='12', color='white', bbox=dict(facecolor=away_color, edgecolor='None')) fig.text(.535, 0.916, ' ' + home + ' ', fontsize='12', color='white', bbox=dict(facecolor=home_color, edgecolor='None')) fig.text(.501, 0.916, '@', fontsize='12', color='black', bbox=dict(facecolor='white', edgecolor='None')) ### ### SAVE TO FILE ### plt.savefig(charts_teams + 'shots_gameflow_xg_5v5.png', bbox_inches='tight', pad_inches=0.2) # exercise a command-line option to show the current figure if images == 'show': plt.show() ### ### CLOSE ### plt.close(fig) # status update print('Finished plotting the 5v5 xG differential game flow.')
def parse_ids(season_id, game_id, images): # pull common variables from the parameters file charts_teams = parameters.charts_teams files_root = parameters.files_root # generate date and team information schedule_csv = files_root + season_id + "_schedule.csv" schedule_df = pd.read_csv(schedule_csv) schedule_date = schedule_df[(schedule_df['GAME_ID'] == int(game_id))] date = schedule_date['DATE'].item() home = schedule_date['HOME'].item() away = schedule_date['AWAY'].item() # create variables that point to the .csv processed teams stats file and play-by-play file stats_teams_file = files_root + 'stats_teams.csv' pbp_file = files_root + 'pbp.csv' # create a dataframe object that reads in the team stats info stats_teams_df = pd.read_csv(stats_teams_file) # create a dataframe object that reads in the shots with expected goals info pbp_df = pd.read_csv(pbp_file) pbp_df['xG'] = round(pbp_df.xG.astype(float) * 100, 2) if int(season_id) >= 20102011: pbp_df['X_1'] *= -1 pbp_df['Y_1'] *= -1 # choose colors for each team and the legend; set them in a list legend_color = 'black' away_color = dict_team_colors.team_color_1st[away] home_color = dict_team_colors.team_color_1st[home] # change one team's color from its primary option to, depending on the opponent, either a second, third or fourth option try: away_color = mod_switch_colors.switch_team_colors(away, home)[0] home_color = mod_switch_colors.switch_team_colors(away, home)[1] except: pass colors = [away_color, home_color, legend_color] states = ['ALL', '5v5', 'PP', 'SH'] for state in states: # pull the time on ice recorded for the home team from the team stats file if state == 'ALL': try: toi_df = stats_teams_df[(stats_teams_df['TEAM'] == home) & (stats_teams_df['STATE'] == 'ALL')] toi = toi_df['TOI'].item() except: toi = 0.0 if state == '5v5': try: toi_df = stats_teams_df[(stats_teams_df['TEAM'] == home) & (stats_teams_df['STATE'] == '5v5')] toi = toi_df['TOI'].item() except: toi = 0.0 if state == 'PP': try: toi_df = stats_teams_df[(stats_teams_df['TEAM'] == home) & (stats_teams_df['STATE'] == 'PP')] toi = toi_df['TOI'].item() except: toi = 0.0 if state == 'SH': try: toi_df = stats_teams_df[(stats_teams_df['TEAM'] == home) & (stats_teams_df['STATE'] == 'SH')] toi = toi_df['TOI'].item() except: toi = 0.0 # get a count of the number of unblocked shots for each team if state == 'ALL': away_count = str(pbp_df[(pbp_df['TEAM'] == away) & (pbp_df['EVENT'] == 'Shot') & (pbp_df['EVENT_TYPE'] != 'Block')].count()[1]) home_count = str(pbp_df[(pbp_df['TEAM'] == home) & (pbp_df['EVENT'] == 'Shot') & (pbp_df['EVENT_TYPE'] != 'Block')].count()[1]) if state == '5v5': away_count = str(pbp_df[(pbp_df['TEAM'] == away) & (pbp_df['EVENT'] == 'Shot') & (pbp_df['EVENT_TYPE'] != 'Block') & (pbp_df['HOME_STRENGTH'] == '5v5') & (pbp_df['AWAY_STRENGTH'] == '5v5')].count()[1]) home_count = str(pbp_df[(pbp_df['TEAM'] == home) & (pbp_df['EVENT'] == 'Shot') & (pbp_df['EVENT_TYPE'] != 'Block') & (pbp_df['HOME_STRENGTH'] == '5v5') & (pbp_df['AWAY_STRENGTH'] == '5v5')].count()[1]) if state == 'PP': away_count = str(pbp_df[(pbp_df['TEAM'] == away) & (pbp_df['EVENT'] == 'Shot') & (pbp_df['EVENT_TYPE'] != 'Block') & (pbp_df['HOME_STATE'] == 'PP') & (pbp_df['AWAY_STATE'] == 'SH')].count()[1]) home_count = str(pbp_df[(pbp_df['TEAM'] == home) & (pbp_df['EVENT'] == 'Shot') & (pbp_df['EVENT_TYPE'] != 'Block') & (pbp_df['HOME_STATE'] == 'PP') & (pbp_df['AWAY_STATE'] == 'SH')].count()[1]) if state == 'SH': away_count = str(pbp_df[(pbp_df['TEAM'] == away) & (pbp_df['EVENT'] == 'Shot') & (pbp_df['EVENT_TYPE'] != 'Block') & (pbp_df['HOME_STATE'] == 'SH') & (pbp_df['AWAY_STATE'] == 'PP')].count()[1]) home_count = str(pbp_df[(pbp_df['TEAM'] == home) & (pbp_df['EVENT'] == 'Shot') & (pbp_df['EVENT_TYPE'] != 'Block') & (pbp_df['HOME_STATE'] == 'SH') & (pbp_df['AWAY_STATE'] == 'PP')].count()[1]) # get the sum xG value of unblocked shots for each team if state == 'ALL': away_xG = str(round((np.where((pbp_df['TEAM'] == away) & (pbp_df['EVENT'] == 'Shot') & (pbp_df['EVENT_TYPE'] != 'Block'), pbp_df['xG'], 0).sum(), 1)[0] / 100, 2)) home_xG = str(round((np.where((pbp_df['TEAM'] == home) & (pbp_df['EVENT'] == 'Shot') & (pbp_df['EVENT_TYPE'] != 'Block'), pbp_df['xG'], 0).sum(), 1)[0] / 100, 2)) if state == '5v5': away_xG = str(round((np.where((pbp_df['TEAM'] == away) & (pbp_df['EVENT'] == 'Shot') & (pbp_df['EVENT_TYPE'] != 'Block') & (pbp_df['HOME_STRENGTH'] == '5v5') & (pbp_df['AWAY_STRENGTH'] == '5v5'), pbp_df['xG'], 0).sum(), 1)[0] / 100, 2)) home_xG = str(round((np.where((pbp_df['TEAM'] == home) & (pbp_df['EVENT'] == 'Shot') & (pbp_df['EVENT_TYPE'] != 'Block') & (pbp_df['HOME_STRENGTH'] == '5v5') & (pbp_df['AWAY_STRENGTH'] == '5v5'), pbp_df['xG'], 0).sum(), 1)[0] / 100, 2)) if state == 'PP': away_xG = str(round((np.where((pbp_df['TEAM'] == away) & (pbp_df['EVENT'] == 'Shot') & (pbp_df['EVENT_TYPE'] != 'Block') & (pbp_df['HOME_STATE'] == 'PP') & (pbp_df['AWAY_STATE'] == 'SH'), pbp_df['xG'], 0).sum(), 1)[0] / 100, 2)) home_xG = str(round((np.where((pbp_df['TEAM'] == home) & (pbp_df['EVENT'] == 'Shot') & (pbp_df['EVENT_TYPE'] != 'Block') & (pbp_df['HOME_STATE'] == 'PP') & (pbp_df['AWAY_STATE'] == 'SH'), pbp_df['xG'], 0).sum(), 1)[0] / 100, 2)) if state == 'SH': away_xG = str(round((np.where((pbp_df['TEAM'] == away) & (pbp_df['EVENT'] == 'Shot') & (pbp_df['EVENT_TYPE'] != 'Block') & (pbp_df['HOME_STATE'] == 'SH') & (pbp_df['AWAY_STATE'] == 'PP'), pbp_df['xG'], 0).sum(), 1)[0] / 100, 2)) home_xG = str(round((np.where((pbp_df['TEAM'] == home) & (pbp_df['EVENT'] == 'Shot') & (pbp_df['EVENT_TYPE'] != 'Block') & (pbp_df['HOME_STATE'] == 'SH') & (pbp_df['AWAY_STATE'] == 'PP'), pbp_df['xG'], 0).sum(), 1)[0] / 100, 2)) # get a count of the number of unblocked shots for each team if state == 'ALL': away_G_count = str(pbp_df[(pbp_df['TEAM'] == away) & (pbp_df['EVENT'] == 'Shot') & (pbp_df['EVENT_TYPE'] == 'Goal')].count()[1]) home_G_count = str(pbp_df[(pbp_df['TEAM'] == home) & (pbp_df['EVENT'] == 'Shot') & (pbp_df['EVENT_TYPE'] == 'Goal')].count()[1]) if state == '5v5': away_G_count = str(pbp_df[(pbp_df['TEAM'] == away) & (pbp_df['EVENT'] == 'Shot') & (pbp_df['EVENT_TYPE'] == 'Goal') & (pbp_df['HOME_STRENGTH'] == '5v5') & (pbp_df['AWAY_STRENGTH'] == '5v5')].count()[1]) home_G_count = str(pbp_df[(pbp_df['TEAM'] == home) & (pbp_df['EVENT'] == 'Shot') & (pbp_df['EVENT_TYPE'] == 'Goal') & (pbp_df['HOME_STRENGTH'] == '5v5') & (pbp_df['AWAY_STRENGTH'] == '5v5')].count()[1]) if state == 'PP': away_G_count = str(pbp_df[(pbp_df['TEAM'] == away) & (pbp_df['EVENT'] == 'Shot') & (pbp_df['EVENT_TYPE'] == 'Goal') & (pbp_df['HOME_STATE'] == 'PP') & (pbp_df['AWAY_STATE'] == 'SH')].count()[1]) home_G_count = str(pbp_df[(pbp_df['TEAM'] == home) & (pbp_df['EVENT'] == 'Shot') & (pbp_df['EVENT_TYPE'] == 'Goal') & (pbp_df['HOME_STATE'] == 'PP') & (pbp_df['AWAY_STATE'] == 'SH')].count()[1]) if state == 'SH': away_G_count = str(pbp_df[(pbp_df['TEAM'] == away) & (pbp_df['EVENT'] == 'Shot') & (pbp_df['EVENT_TYPE'] == 'Goal') & (pbp_df['HOME_STATE'] == 'SH') & (pbp_df['AWAY_STATE'] == 'PP')].count()[1]) home_G_count = str(pbp_df[(pbp_df['TEAM'] == home) & (pbp_df['EVENT'] == 'Shot') & (pbp_df['EVENT_TYPE'] == 'Goal') & (pbp_df['HOME_STATE'] == 'SH') & (pbp_df['AWAY_STATE'] == 'PP')].count()[1]) # create subsets of the distinct types of unblocked shots for each teeam from the play-by-play file if state == 'ALL': away_df_scored = pbp_df[(pbp_df['TEAM'] == away) & (pbp_df['EVENT'] == 'Shot') & (pbp_df['EVENT_TYPE'] == 'Goal')] away_df_saved = pbp_df[(pbp_df['TEAM'] == away) & (pbp_df['EVENT'] == 'Shot') & (pbp_df['EVENT_TYPE'] == 'Save')] away_df_missed = pbp_df[(pbp_df['TEAM'] == away) & (pbp_df['EVENT'] == 'Shot') & (pbp_df['EVENT_TYPE'] == 'Miss')] home_df_scored = pbp_df[(pbp_df['TEAM'] == home) & (pbp_df['EVENT'] == 'Shot') & (pbp_df['EVENT_TYPE'] == 'Goal')] home_df_saved = pbp_df[(pbp_df['TEAM'] == home) & (pbp_df['EVENT'] == 'Shot') & (pbp_df['EVENT_TYPE'] == 'Save')] home_df_missed = pbp_df[(pbp_df['TEAM'] == home) & (pbp_df['EVENT'] == 'Shot') & (pbp_df['EVENT_TYPE'] == 'Miss')] if state == '5v5': away_df_scored = pbp_df[(pbp_df['TEAM'] == away) & (pbp_df['EVENT'] == 'Shot') & (pbp_df['EVENT_TYPE'] == 'Goal') & (pbp_df['HOME_STRENGTH'] == '5v5') & (pbp_df['AWAY_STRENGTH'] == '5v5')] away_df_saved = pbp_df[(pbp_df['TEAM'] == away) & (pbp_df['EVENT'] == 'Shot') & (pbp_df['EVENT_TYPE'] == 'Save') & (pbp_df['HOME_STRENGTH'] == '5v5') & (pbp_df['AWAY_STRENGTH'] == '5v5')] away_df_missed = pbp_df[(pbp_df['TEAM'] == away) & (pbp_df['EVENT'] == 'Shot') & (pbp_df['EVENT_TYPE'] == 'Miss') & (pbp_df['HOME_STRENGTH'] == '5v5') & (pbp_df['AWAY_STRENGTH'] == '5v5')] home_df_scored = pbp_df[(pbp_df['TEAM'] == home) & (pbp_df['EVENT'] == 'Shot') & (pbp_df['EVENT_TYPE'] == 'Goal') & (pbp_df['HOME_STRENGTH'] == '5v5') & (pbp_df['AWAY_STRENGTH'] == '5v5')] home_df_saved = pbp_df[(pbp_df['TEAM'] == home) & (pbp_df['EVENT'] == 'Shot') & (pbp_df['EVENT_TYPE'] == 'Save') & (pbp_df['HOME_STRENGTH'] == '5v5') & (pbp_df['AWAY_STRENGTH'] == '5v5')] home_df_missed = pbp_df[(pbp_df['TEAM'] == home) & (pbp_df['EVENT'] == 'Shot') & (pbp_df['EVENT_TYPE'] == 'Miss') & (pbp_df['HOME_STRENGTH'] == '5v5') & (pbp_df['AWAY_STRENGTH'] == '5v5')] if state == 'PP': away_df_scored = pbp_df[(pbp_df['TEAM'] == away) & (pbp_df['EVENT'] == 'Shot') & (pbp_df['EVENT_TYPE'] == 'Goal') & (pbp_df['HOME_STATE'] == 'PP') & (pbp_df['AWAY_STATE'] == 'SH')] away_df_saved = pbp_df[(pbp_df['TEAM'] == away) & (pbp_df['EVENT'] == 'Shot') & (pbp_df['EVENT_TYPE'] == 'Save') & (pbp_df['HOME_STATE'] == 'PP') & (pbp_df['AWAY_STATE'] == 'SH')] away_df_missed = pbp_df[(pbp_df['TEAM'] == away) & (pbp_df['EVENT'] == 'Shot') & (pbp_df['EVENT_TYPE'] == 'Miss') & (pbp_df['HOME_STATE'] == 'PP') & (pbp_df['AWAY_STATE'] == 'SH')] home_df_scored = pbp_df[(pbp_df['TEAM'] == home) & (pbp_df['EVENT'] == 'Shot') & (pbp_df['EVENT_TYPE'] == 'Goal') & (pbp_df['HOME_STATE'] == 'PP') & (pbp_df['AWAY_STATE'] == 'SH')] home_df_saved = pbp_df[(pbp_df['TEAM'] == home) & (pbp_df['EVENT'] == 'Shot') & (pbp_df['EVENT_TYPE'] == 'Save') & (pbp_df['HOME_STATE'] == 'PP') & (pbp_df['AWAY_STATE'] == 'SH')] home_df_missed = pbp_df[(pbp_df['TEAM'] == home) & (pbp_df['EVENT'] == 'Shot') & (pbp_df['EVENT_TYPE'] == 'Miss') & (pbp_df['HOME_STATE'] == 'PP') & (pbp_df['AWAY_STATE'] == 'SH')] if state == 'SH': away_df_scored = pbp_df[(pbp_df['TEAM'] == away) & (pbp_df['EVENT'] == 'Shot') & (pbp_df['EVENT_TYPE'] == 'Goal') & (pbp_df['HOME_STATE'] == 'SH') & (pbp_df['AWAY_STATE'] == 'PP')] away_df_saved = pbp_df[(pbp_df['TEAM'] == away) & (pbp_df['EVENT'] == 'Shot') & (pbp_df['EVENT_TYPE'] == 'Save') & (pbp_df['HOME_STATE'] == 'SH') & (pbp_df['AWAY_STATE'] == 'PP')] away_df_missed = pbp_df[(pbp_df['TEAM'] == away) & (pbp_df['EVENT'] == 'Shot') & (pbp_df['EVENT_TYPE'] == 'Miss') & (pbp_df['HOME_STATE'] == 'SH') & (pbp_df['AWAY_STATE'] == 'PP')] home_df_scored = pbp_df[(pbp_df['TEAM'] == home) & (pbp_df['EVENT'] == 'Shot') & (pbp_df['EVENT_TYPE'] == 'Goal') & (pbp_df['HOME_STATE'] == 'SH') & (pbp_df['AWAY_STATE'] == 'PP')] home_df_saved = pbp_df[(pbp_df['TEAM'] == home) & (pbp_df['EVENT'] == 'Shot') & (pbp_df['EVENT_TYPE'] == 'Save') & (pbp_df['HOME_STATE'] == 'SH') & (pbp_df['AWAY_STATE'] == 'PP')] home_df_missed = pbp_df[(pbp_df['TEAM'] == home) & (pbp_df['EVENT'] == 'Shot') & (pbp_df['EVENT_TYPE'] == 'Miss') & (pbp_df['HOME_STATE'] == 'SH') & (pbp_df['AWAY_STATE'] == 'PP')] # create lists of the expected goals values for each type of unblocked shot away_scored_list = away_df_scored['xG'].tolist() away_saved_list = away_df_saved['xG'].tolist() away_missed_list = away_df_missed['xG'].tolist() home_scored_list = home_df_scored['xG'].tolist() home_saved_list = home_df_saved['xG'].tolist() home_missed_list = home_df_missed['xG'].tolist() # create a figure to plot fig, ax = plt.subplots(figsize=(8,6)) # plot the distinct types of unblocked shot events for each team in order to create labels teams_df_scored = pd.concat([away_df_scored, home_df_scored]) teams_df_saved = pd.concat([away_df_saved, home_df_saved]) teams_df_missed = pd.concat([away_df_missed, home_df_missed]) try: scored_marker = teams_df_scored.plot.scatter(x='X_1', y='Y_1', zorder=0, marker='D', s=60, c='None', edgecolors='black', linewidth=2, alpha=1, label='Scored', ax=ax); except: pass try: saved_marker = teams_df_saved.plot.scatter(x='X_1', y='Y_1', zorder=0, marker='o', s=40, c='None', edgecolors='black', linewidth=1, alpha=1, label='Saved', ax=ax); except: pass try: missed_marker = teams_df_missed.plot.scatter(x='X_1', y='Y_1', zorder=0, marker='x', s=40, c='black', edgecolors='None', alpha=1, label='Missed', ax=ax); except: pass # plot the distinct types of unblocked shot events for each team try: away_scored_plot = away_df_scored.plot.scatter(x='X_1', y='Y_1', zorder=3, marker='D', s=[5*i for i in away_scored_list], c='None', edgecolors=colors[0], linewidth=2, alpha=1, ax=ax); except: pass try: away_saved_plot = away_df_saved.plot.scatter(x='X_1', y='Y_1', zorder=2, marker='o', s=[5*i for i in away_saved_list], c='None', edgecolors=colors[0], linewidth=1, alpha=0.5, ax=ax); except: pass try: away_missed_plot = away_df_missed.plot.scatter(x='X_1', y='Y_1', zorder=2, marker='x', s=[5*i for i in away_missed_list], c=colors[0], edgecolors='None', alpha=0.5, ax=ax); except: pass try: home_scored_plot = home_df_scored.plot.scatter(x='X_1', y='Y_1', zorder=3, marker='D', s=[5*i for i in home_scored_list], c='None', edgecolors=colors[1], linewidth=2, alpha=1, ax=ax); except: pass try: home_saved_plot = home_df_saved.plot.scatter(x='X_1', y='Y_1', zorder=2, marker='o', s=[5*i for i in home_saved_list], c='None', edgecolors=colors[1], linewidth=1, alpha=0.5, ax=ax); except: pass try: home_missed_plot = home_df_missed.plot.scatter(x='X_1', y='Y_1', zorder=2, marker='x', s=[5*i for i in home_missed_list], c=colors[1], edgecolors='none', alpha=0.5, ax=ax); except: pass # set the background image of what will be the plot to the 'rink_image.png' file rink_img = plt.imread("rink_image.png") plt.imshow(rink_img, extent=[-100,100,-42.5,42.5], zorder=0) # eliminate the axis labels plt.axis('off') # add text boxes to indicate home and away sides plt.text(58, 45, home_count + ' USF\n' + home_xG + ' xGF, ' + home_G_count + ' GF', color=colors[1], fontsize=12, ha='center') plt.text(-58, 45, away_count + ' USF\n' + away_xG + ' xGF, ' + away_G_count + ' GF', color=colors[0], fontsize=12, ha='center') # set the plot title if state == 'ALL': plt.title(date + ' Unblocked Shots\n' + str(toi) + ' Minutes\n\n') if state == '5v5': plt.title(date + ' Unblocked Shots\n' + str(toi) + ' 5v5 Minutes\n\n') if state == 'PP': plt.title(date + ' Unblocked Shots\n' + str(toi) + ' Home PP Minutes\n\n') if state == 'SH': plt.title(date + ' Unblocked Shots\n' + str(toi) + ' Away PP Minutes\n\n') # set the location of the plot legend plt.legend(loc='upper center', bbox_to_anchor=(0.5, -0.00), scatterpoints=1, ncol=3).get_frame().set_linewidth(0.0) # add text boxes with team names in white and with the team's color in the background fig.text(.435, 0.744, ' ' + away + ' ', fontsize='12', color='white', bbox=dict(facecolor=away_color, edgecolor='None')) fig.text(.535, 0.744, ' ' + home + ' ', fontsize='12', color='white', bbox=dict(facecolor=home_color, edgecolor='None')) fig.text(.501, 0.744, '@', fontsize='12', color='black', bbox=dict(facecolor='white', edgecolor='None')) # eliminate unnecessary whitespace ax.axes.get_xaxis().set_visible(False) ax.axes.get_yaxis().set_visible(False) ### ### SAVE TO FILE ### if state == 'ALL': plt.savefig(charts_teams + 'shots_scatter.png', bbox_inches='tight', pad_inches=0.2) if state == '5v5': plt.savefig(charts_teams + 'shots_scatter_5v5.png', bbox_inches='tight', pad_inches=0.2) if state == 'PP': plt.savefig(charts_teams + 'shots_scatter_pp_home.png', bbox_inches='tight', pad_inches=0.2) if state == 'SH': plt.savefig(charts_teams + 'shots_scatter_pp_away.png', bbox_inches='tight', pad_inches=0.2) # exercise a command-line option to show the current figure if images == 'show': plt.show() ### ### CLOSE ### plt.close(fig) # status update if state == 'ALL': print('Finished scatter plot for all unblocked shots sized by xG.') if state == '5v5': print('Finished scatter plot for unblocked 5v5 shots sized by xG.') if state == 'PP': print('Finished scatter plot for unblocked shots sized by xG during a home PP.') if state == 'SH': print('Finished scatter plot for unblocked shots sized by xG during an away PP.')
def parse_ids(season_id, game_id, images): # pull common variables from the parameters file charts_units = parameters.charts_units files_root = parameters.files_root # generate date and team information schedule_csv = files_root + season_id + "_schedule.csv" schedule_df = pd.read_csv(schedule_csv) schedule_date = schedule_df[(schedule_df['GAME_ID'] == int(game_id))] date = schedule_date['DATE'].item() home = schedule_date['HOME'].item() away = schedule_date['AWAY'].item() teams = [away, home] # create variables that point to the .csv processed stats files for the team and players lines_file = files_root + 'stats_units_lines_onice.csv' pairings_file = files_root + 'stats_units_pairings_onice.csv' pk_file = files_root + 'stats_units_pk_onice.csv' pp_file = files_root + 'stats_units_pp_onice.csv' # create a dataframe object that reads in info from the .csv files lines_df = pd.read_csv(lines_file) pairings_df = pd.read_csv(pairings_file) PP_df = pd.read_csv(pp_file) PK_df = pd.read_csv(pk_file) max_lines_toi = lines_df['TOI'].max() max_pairings_toi = pairings_df['TOI'].max() max_PP_toi = PP_df['TOI'].max() max_PK_toi = PK_df['TOI'].max() # choose colors for each team; set them in a list; generate a custom colormap for each team away_color = dict_team_colors.team_color_1st[away] home_color = dict_team_colors.team_color_1st[home] # change one team's color from its primary option to, depending on the opponent, either a second, third or fourth option try: away_color = mod_switch_colors.switch_team_colors(away, home)[0] home_color = mod_switch_colors.switch_team_colors(away, home)[1] except: pass team_colors = [away_color, home_color] ### ### 5v5, PP, PK ### # loop through each team for team in teams: if team == away: team_color = team_colors[0] opponent_color = team_colors[1] if team == home: team_color = team_colors[1] opponent_color = team_colors[0] # create a dataframe; filter for team; sort by team, game state and position; rank by time on ice and then invert the rankings team_lines_df = lines_df.copy() team_lines_df = team_lines_df[(team_lines_df['TEAM'] == team)] team_lines_df = team_lines_df.sort_values(by=['TOI'], ascending = True) team_lines_df = team_lines_df.iloc[-4:] team_lines_df['RANK'] = team_lines_df['TOI'].rank(method='first') team_lines_df = team_lines_df.sort_values(by=['RANK'], ascending = True) team_lines_df['RANK'] -= 1 # remove zeros from the goals for and against columns team_lines_df['GF'] = team_lines_df['GF'].replace(0, np.NaN) team_lines_df['GA'] = team_lines_df['GA'].replace(0, np.NaN) # remove zeros from the differential column team_lines_df['SD'] = team_lines_df['SD'].replace(0, np.NaN) # make goals against and shots against negative values team_lines_df['GA'] *= -1 team_lines_df['SA'] *= -1 # find the max toi value team_max_lines_toi = team_lines_df['TOI'].max() # create a pairings dataframe; filter for team; sort by time on ice; keep the pairs with the 3 highest totals; rank and then invert the rankings team_pairings_df = pairings_df.copy() team_pairings_df = team_pairings_df[(team_pairings_df['TEAM'] == team)] team_pairings_df = team_pairings_df.sort_values(by=['TOI'], ascending = True) team_pairings_df = team_pairings_df.iloc[-3:] team_pairings_df['RANK'] = team_pairings_df['TOI'].rank(method='first') team_pairings_df['RANK'] -= 1 # remove zeros from the goals for and against columns team_pairings_df['GF'] = team_pairings_df['GF'].replace(0, np.NaN) team_pairings_df['GA'] = team_pairings_df['GA'].replace(0, np.NaN) # remove zeros from the differential column team_pairings_df['SD'] = team_pairings_df['SD'].replace(0, np.NaN) # make goals against and shots against negative values team_pairings_df['GA'] *= -1 team_pairings_df['SA'] *= -1 # find the max toi value team_max_pairings_toi = team_pairings_df['TOI'].max() # create a power play units dataframe; filter for team; sort by time on ice; keep the units with the 4 highest totals; rank and then invert the rankings team_PP_df = PP_df.copy() team_PP_df = team_PP_df[(team_PP_df['TEAM'] == team)] team_PP_df = team_PP_df.sort_values(by=['TOI'], ascending = True) team_PP_df = team_PP_df.iloc[-4:] team_PP_df['RANK'] = team_PP_df['TOI'].rank(method='first') team_PP_df['RANK'] -= 1 # remove zeros from the goals for and against columns team_PP_df['GF'] = team_PP_df['GF'].replace(0, np.NaN) team_PP_df['GA'] = team_PP_df['GA'].replace(0, np.NaN) # remove zeros from the differential column team_PP_df['SD'] = team_PP_df['SD'].replace(0, np.NaN) # make goals against and shots against negative values team_PP_df['GA'] *= -1 team_PP_df['SA'] *= -1 # find the max toi value team_max_PP_toi = team_PP_df['TOI'].max() # create a penalty kill units dataframe; filter for team; sort by time on ice; keep the units with the 4 highest totals; rank and then invert the rankings team_PK_df = PK_df.copy() team_PK_df = team_PK_df[(team_PK_df['TEAM'] == team)] team_PK_df = team_PK_df.sort_values(by=['TOI'], ascending = True) team_PK_df = team_PK_df.iloc[-4:] team_PK_df['RANK'] = team_PK_df['TOI'].rank(method='first') team_PK_df['RANK'] -= 1 # remove zeros from the goals for and against columns team_PK_df['GF'] = team_PK_df['GF'].replace(0, np.NaN) team_PK_df['GA'] = team_PK_df['GA'].replace(0, np.NaN) # remove zeros from the differential column team_PK_df['SD'] = team_PK_df['SD'].replace(0, np.NaN) # make goals against and shots against negative values team_PK_df['GA'] *= -1 team_PK_df['SA'] *= -1 # find the max toi value team_max_PK_toi = team_PK_df['TOI'].max() # create a figure with six subplots arrangled complexly using a grid structure fig = plt.figure(figsize=(8,8)) grid = plt.GridSpec(4, 8, hspace=0.75, wspace=0.50) ax_5v5_lines_shots = fig.add_subplot(grid[0, 0:-2]) ax_5v5_lines_toi = fig.add_subplot(grid[0, -1]) ax_5v5_pairings_shots = fig.add_subplot(grid[1, 0:-2]) ax_5v5_pairings_toi = fig.add_subplot(grid[1, -1]) ax_PP_shots = fig.add_subplot(grid[2, 0:-2]) ax_PP_toi = fig.add_subplot(grid[2, -1]) ax_PK_shots = fig.add_subplot(grid[3, 0:-2]) ax_PK_toi = fig.add_subplot(grid[3, -1]) # set the plot title fig.suptitle(date + ' Unit On-Ice Shots\n\n') # set the axes titles ax_5v5_lines_shots.set_title('5v5 S', fontsize=10) ax_5v5_lines_toi.set_title('5v5 TOI', fontsize=10) ax_PP_shots.set_title('PP S', fontsize=10) ax_PP_toi.set_title('PP TOI', fontsize=10) ax_PK_shots.set_title('SH S', fontsize=10) ax_PK_toi.set_title('SH TOI', fontsize=10) # for each state, plot the bars for total shots and markers for saved, missed and blocked shots markers try: SF_5v5_lines_plot = team_lines_df.plot.barh(x='LINE', y='SF', color=team_color, edgecolor='None', width=0.75, legend=None, label='', ax=ax_5v5_lines_shots); except: pass try: SA_5v5_lines_plot = team_lines_df.plot.barh(x='LINE', y='SA', color=opponent_color, edgecolor='None', width=0.75, legend=None, label='', ax=ax_5v5_lines_shots); except: pass try: GF_5v5_lines_marker = team_lines_df.plot(x='GF', y='RANK', marker='D', markersize=5, markerfacecolor='None', markeredgecolor='white', linewidth=0, alpha=1, legend='', label='', ax=ax_5v5_lines_shots); except: pass try: GA_5v5_lines_marker = team_lines_df.plot(x='GA', y='RANK', marker='D', markersize=5, markerfacecolor='None', markeredgecolor='white', linewidth=0, alpha=1, legend='', label='', ax=ax_5v5_lines_shots); except: pass try: SD_5v5_lines_plot = team_lines_df.plot(x='SD', y='RANK', marker='|', markersize=13, markeredgewidth=1, markerfacecolor='None', markeredgecolor='white', linewidth=0, alpha=1, legend='', label='', ax=ax_5v5_lines_shots); except: pass try: SF_5v5_pairings_plot = team_pairings_df.plot.barh(x='PAIRING', y='SF', color=team_color, edgecolor='None', width=0.55, legend=None, label='', ax=ax_5v5_pairings_shots); except: pass try: SA_5v5_pairings_plot = team_pairings_df.plot.barh(x='PAIRING', y='SA', color=opponent_color, edgecolor='None', width=0.55, legend=None, label='', ax=ax_5v5_pairings_shots); except: pass try: GF_5v5_pairings_marker = team_lines_df.plot(x='GF', y='RANK', marker='D', markersize=5, markerfacecolor='None', markeredgecolor='white', linewidth=0, alpha=1, legend='', label='', ax=ax_5v5_pairings_shots); except: pass try: GA_5v5_pairings_marker = team_lines_df.plot(x='GA', y='RANK', marker='D', markersize=5, markerfacecolor='None', markeredgecolor='white', linewidth=0, alpha=1, legend='', label='', ax=ax_5v5_pairings_shots); except: pass try: SD_5v5_pairings_plot = team_pairings_df.plot(x='SD', y='RANK', marker='|', markersize=13, markeredgewidth=1, markerfacecolor='None', markeredgecolor='white', linewidth=0, alpha=1, legend='', label='', ax=ax_5v5_pairings_shots); except: pass try: SF_PP_plot = team_PP_df.plot.barh(x='UNIT', y='SF', color=team_color, edgecolor='None', width=0.75, legend=None, label='', ax=ax_PP_shots); except: pass try: SA_PP_plot = team_PP_df.plot.barh(x='UNIT', y='SA', color=opponent_color, edgecolor='None', width=0.75, legend=None, label='', ax=ax_PP_shots); except: pass try: SD_PP_marker = team_PP_df.plot(x='SD', y='RANK', marker='|', markersize=13, markeredgewidth=1, markerfacecolor='None', markeredgecolor='white', linewidth=0, alpha=1, legend='', label='', ax=ax_PP_shots); except: pass try: SF_PK_plot = team_PK_df.plot.barh(x='UNIT', y='SF', color=team_color, edgecolor='None', width=0.75, legend=None, label='', ax=ax_PK_shots); except: pass try: SA_PK_plot = team_PK_df.plot.barh(x='UNIT', y='SA', color=opponent_color, edgecolor='None', width=0.75, legend=None, label='', ax=ax_PK_shots); except: pass try: SD_PK_marker = team_PK_df.plot(x='SD', y='RANK', marker='|', markersize=13, markeredgewidth=1, markerfacecolor='None', markeredgecolor='white', linewidth=0, alpha=1, legend='', label='', ax=ax_PK_shots); except: pass # for each state, plot the bars for time on ice try: toi_5v5_lines_plot = team_lines_df.plot.barh(x='LINE', y='TOI', color='white', edgecolor=team_color, width=0.75, legend=None, label='', ax=ax_5v5_lines_toi); except: pass try: toi_5v5_pairings_plot = team_pairings_df.plot.barh(x='PAIRING', y='TOI', color='white', edgecolor=team_color, width=0.55, legend=None, label='', ax=ax_5v5_pairings_toi); except: pass try: toi_PP_plot = team_PP_df.plot.barh(x='UNIT', y='TOI', color='white', edgecolor=team_color, width=0.75, legend=None, label='', ax=ax_PP_toi); except: pass try: toi_PK_plot = team_PK_df.plot.barh(x='UNIT', y='TOI', color='white', edgecolor=team_color, width=0.75, legend=None, label='', ax=ax_PK_toi); except: pass # set / remove the y-labels for the subplots ax_5v5_lines_shots.set_xlabel('') ax_5v5_lines_shots.set_ylabel('') ax_5v5_lines_toi.set_xlabel('') ax_5v5_lines_toi.set_ylabel('') ax_5v5_pairings_shots.set_xlabel('') ax_5v5_pairings_shots.set_ylabel('') ax_5v5_pairings_toi.set_xlabel('') ax_5v5_pairings_toi.set_ylabel('') ax_PP_shots.set_xlabel('') ax_PP_shots.set_ylabel('') ax_PP_toi.set_xlabel('') ax_PP_toi.set_ylabel('') ax_PK_shots.set_xlabel('') ax_PK_shots.set_ylabel('') ax_PK_toi.set_xlabel('') ax_PK_toi.set_ylabel('') # set vertical indicators for zero shots ax_5v5_lines_shots.axvspan(0, 0, ymin=0, ymax=1, alpha=0.25, linestyle=':', color='black') ax_5v5_pairings_shots.axvspan(0, 0, ymin=0, ymax=1, alpha=0.25, linestyle=':', color='black') ax_PP_shots.axvspan(0, 0, ymin=0, ymax=1, alpha=0.25, linestyle=':', color='black') ax_PK_shots.axvspan(0, 0, ymin=0, ymax=1, alpha=0.25, linestyle=':', color='black') # change the tick parameters for each axes ax_5v5_lines_shots.tick_params( axis='both', # changes apply to the x-axis which='both', # both major and minor ticks are affected bottom=False, # ticks along the bottom edge are off top=False, # ticks along the top edge are off left=False, # ticks along the left edge are off labelbottom=True) # labels along the bottom edge are on ax_5v5_lines_toi.tick_params( axis='both', # changes apply to the x-axis which='both', # both major and minor ticks are affected bottom=False, # ticks along the bottom edge are off top=False, # ticks along the top edge are off left=False, # ticks along the left edge are off labelleft=False, # labels along the left edge are off labelbottom=True) # labels along the bottom edge are on ax_5v5_pairings_shots.tick_params( axis='both', # changes apply to the x-axis which='both', # both major and minor ticks are affected bottom=False, # ticks along the bottom edge are off top=False, # ticks along the top edge are off left=False, # ticks along the left edge are off labelbottom=True) # labels along the bottom edge are on ax_5v5_pairings_toi.tick_params( axis='both', # changes apply to the x-axis which='both', # both major and minor ticks are affected bottom=False, # ticks along the bottom edge are off top=False, # ticks along the top edge are off left=False, # ticks along the left edge are off labelleft=False, # labels along the left edge are off labelbottom=True) # labels along the bottom edge are on ax_PP_shots.tick_params( axis='both', # changes apply to the x-axis which='both', # both major and minor ticks are affected bottom=False, # ticks along the bottom edge are off top=False, # ticks along the top edge are off left=False, # ticks along the left edge are off labelbottom=True) # labels along the bottom edge are on ax_PP_toi.tick_params( axis='both', # changes apply to the x-axis which='both', # both major and minor ticks are affected bottom=False, # ticks along the bottom edge are off top=False, # ticks along the top edge are off left=False, # ticks along the left edge are off labelleft=False, # labels along the left edge are off labelbottom=True) # labels along the bottom edge are on ax_PK_shots.tick_params( axis='both', # changes apply to the x-axis which='both', # both major and minor ticks are affected bottom=False, # ticks along the bottom edge are off top=False, # ticks along the top edge are off left=False, # ticks along the left edge are off labelbottom=True) # labels along the bottom edge are on ax_PK_toi.tick_params( axis='both', # changes apply to the x-axis which='both', # both major and minor ticks are affected bottom=False, # ticks along the bottom edge are off top=False, # ticks along the top edge are off left=False, # ticks along the left edge are off labelleft=False, # labels along the left edge are off labelbottom=True) # labels along the bottom edge are on # change the y-axis label colors ax_5v5_lines_shots.tick_params( axis='y', which='both', labelcolor=team_color) ax_5v5_pairings_shots.tick_params( axis='y', which='both', labelcolor=team_color) ax_PP_shots.tick_params( axis='y', which='both', labelcolor=team_color) ax_PP_shots.tick_params( axis='y', which='both', labelcolor=team_color) ax_PK_shots.tick_params( axis='y', which='both', labelcolor=team_color) ax_PK_shots.tick_params( axis='y', which='both', labelcolor=team_color) # create a list of x-axis tick values contingent on the max values for shots team_5v5_lines_df2 = team_lines_df.copy() team_5v5_pairings_df2 = team_pairings_df.copy() team_PP_df2 = team_PP_df.copy() team_PK_df2 = team_PK_df.copy() team_5v5_lines_df2['SA'] *= -1 team_5v5_pairings_df2['SA'] *= -1 team_PP_df2['SA'] *= -1 team_PK_df2['SA'] *= -1 SF_5v5_lines_max = team_5v5_lines_df2['SF'] SF_5v5_lines_max = SF_5v5_lines_max.max() SA_5v5_lines_max = team_5v5_lines_df2['SA'] SA_5v5_lines_max = SA_5v5_lines_max.max() S_5v5_lines_max = int() if SF_5v5_lines_max >= SA_5v5_lines_max: S_5v5_lines_max = SF_5v5_lines_max if SF_5v5_lines_max < SA_5v5_lines_max: S_5v5_lines_max = SA_5v5_lines_max SF_5v5_pairings_max = team_5v5_pairings_df2['SF'] SF_5v5_pairings_max = SF_5v5_pairings_max.max() SA_5v5_pairings_max = team_5v5_pairings_df2['SA'] SA_5v5_pairings_max = SA_5v5_pairings_max.max() S_5v5_pairings_max = int() if SF_5v5_pairings_max >= SA_5v5_pairings_max: S_5v5_pairings_max = SF_5v5_pairings_max if SF_5v5_pairings_max < SA_5v5_pairings_max: S_5v5_pairings_max = SA_5v5_pairings_max S_5v5_tickmax = int() if S_5v5_lines_max >= S_5v5_pairings_max: S_5v5_tickmax = S_5v5_lines_max if S_5v5_lines_max < S_5v5_pairings_max: S_5v5_tickmax = S_5v5_pairings_max S_5v5_ticklabels = [] if S_5v5_tickmax <= 10: S_5v5_ticklabels = [-10, -8, -6, -4, -2, 0, 2, 4, 6, 8, 10] if S_5v5_tickmax > 10 and S_5v5_tickmax <= 20: S_5v5_ticklabels = [-20, -16, -12, -8, -4, 0, 4, 8, 12, 16, 20] if S_5v5_tickmax > 20 and S_5v5_tickmax <= 30: S_5v5_ticklabels = [-30, -24, -18, -12, -6, 0, 6, 12, 18, 24, 30] if S_5v5_tickmax > 30 and S_5v5_tickmax <= 40: S_5v5_ticklabels = [-40, -32, -24, -16, -8, 0, 8, 16, 24, 32, 40] toi_5v5_lines_tickmax = max_lines_toi toi_5v5_pairings_tickmax = max_pairings_toi toi_5v5_tickmax = int() if toi_5v5_lines_tickmax >= toi_5v5_pairings_tickmax: toi_5v5_tickmax = toi_5v5_lines_tickmax if toi_5v5_lines_tickmax < toi_5v5_pairings_tickmax: toi_5v5_tickmax = toi_5v5_pairings_tickmax toi_5v5_ticklabels = [] if toi_5v5_tickmax <= 2: toi_5v5_ticklabels = [0, 2] if toi_5v5_tickmax > 2 and toi_5v5_tickmax <= 4: toi_5v5_ticklabels = [0, 4] if toi_5v5_tickmax > 4 and toi_5v5_tickmax <= 6: toi_5v5_ticklabels = [0, 6] if toi_5v5_tickmax > 6 and toi_5v5_tickmax <= 8: toi_5v5_ticklabels = [0, 8] if toi_5v5_tickmax > 8 and toi_5v5_tickmax <= 10: toi_5v5_ticklabels = [0, 10] if toi_5v5_tickmax > 10 and toi_5v5_tickmax <= 12: toi_5v5_ticklabels = [0, 12] if toi_5v5_tickmax > 12 and toi_5v5_tickmax <= 14: toi_5v5_ticklabels = [0, 14] if toi_5v5_tickmax > 14 and toi_5v5_tickmax <= 16: toi_5v5_ticklabels = [0, 16] if toi_5v5_tickmax > 16 and toi_5v5_tickmax <= 18: toi_5v5_ticklabels = [0, 18] if toi_5v5_tickmax > 18 and toi_5v5_tickmax <= 20: toi_5v5_ticklabels = [0, 20] SF_PP_max = team_PP_df2['SF'] SF_PP_max = SF_PP_max.max() SA_PP_max = team_PP_df2['SA'] SA_PP_max = SA_PP_max.max() S_PP_tickmax = int() if SF_PP_max >= SA_PP_max: S_PP_tickmax = SF_PP_max if SF_PP_max < SA_PP_max: S_PP_tickmax = SA_PP_max SF_PK_max = team_PK_df2['SF'] SF_PK_max = SF_PK_max.max() SA_PK_max = team_PK_df2['SA'] SA_PK_max = SA_PK_max.max() S_PK_tickmax = int() if SF_PK_max >= SA_PK_max: S_PK_tickmax = SF_PK_max if SF_PK_max < SA_PK_max: S_PK_tickmax = SA_PK_max if S_PP_tickmax >= S_PK_tickmax: S_specialteams_tickmax = S_PP_tickmax if S_PP_tickmax < S_PK_tickmax: S_specialteams_tickmax = S_PK_tickmax S_specialteams_ticklabels = [] if S_specialteams_tickmax <= 4: S_specialteams_ticklabels = [-4, -2, 0, 2, 4] if S_specialteams_tickmax > 4 and S_specialteams_tickmax <= 6: S_specialteams_ticklabels = [-6, -3, 0, 3, 6] if S_specialteams_tickmax > 6 and S_specialteams_tickmax <= 8: S_specialteams_ticklabels = [-8, -4, 0, 4, 8] if S_specialteams_tickmax > 8 and S_specialteams_tickmax <= 10: S_specialteams_ticklabels = [-10, -5, 0, 5, 10] if S_specialteams_tickmax > 10 and S_specialteams_tickmax <= 12: S_specialteams_ticklabels = [-12, -6, 0, 6, 12] if S_specialteams_tickmax > 12 and S_specialteams_tickmax <= 14: S_specialteams_ticklabels = [-14, -7, 0, 7, 14] if S_specialteams_tickmax > 14 and S_specialteams_tickmax <= 16: S_specialteams_ticklabels = [-16, -8, 0, 8, 16] if S_specialteams_tickmax > 16 and S_specialteams_tickmax <= 18: S_specialteams_ticklabels = [-18, -9, 0, 9, 18] if S_specialteams_tickmax > 18 and S_specialteams_tickmax <= 20: S_specialteams_ticklabels = [-20, -10, 0, 10, 20] toi_PP_tickmax = max_PP_toi toi_SH_tickmax = max_PK_toi toi_specialteams_tickmax = int() if toi_PP_tickmax >= toi_SH_tickmax: toi_specialteams_tickmax = toi_PP_tickmax if toi_PP_tickmax < toi_SH_tickmax: toi_specialteams_tickmax = toi_SH_tickmax toi_specialteams_ticklabels = [] if toi_specialteams_tickmax <= 2: toi_specialteams_ticklabels = [0, 2] if toi_specialteams_tickmax > 2 and toi_specialteams_tickmax <= 4: toi_specialteams_ticklabels = [0, 4] if toi_specialteams_tickmax > 4 and toi_specialteams_tickmax <= 6: toi_specialteams_ticklabels = [0, 6] if toi_specialteams_tickmax > 6 and toi_specialteams_tickmax <= 8: toi_specialteams_ticklabels = [0, 8] if toi_specialteams_tickmax > 8 and toi_specialteams_tickmax <= 10: toi_specialteams_ticklabels = [0, 10] if toi_specialteams_tickmax > 10 and toi_specialteams_tickmax <= 12: toi_specialteams_ticklabels = [0, 12] # set vertical indicator for the midpoint and max of time on ice max ax_5v5_lines_toi.axvspan(toi_5v5_ticklabels[1] / 2, toi_5v5_ticklabels[1] / 2, ymin=0, ymax=1, zorder=0, alpha=0.25, linestyle=':', color='black') ax_5v5_lines_toi.axvspan(toi_5v5_ticklabels[1], toi_5v5_ticklabels[1], ymin=0, ymax=1, zorder=0, alpha=0.25, linestyle=':', color='black') ax_5v5_pairings_toi.axvspan(toi_5v5_ticklabels[1] / 2, toi_5v5_ticklabels[1] / 2, ymin=0, ymax=1, zorder=0, alpha=0.25, linestyle=':', color='black') ax_5v5_pairings_toi.axvspan(toi_5v5_ticklabels[1], toi_5v5_ticklabels[1], ymin=0, ymax=1, zorder=0, alpha=0.25, linestyle=':', color='black') ax_PP_toi.axvspan(toi_specialteams_ticklabels[1] / 2, toi_specialteams_ticklabels[1] / 2, ymin=0, ymax=1, zorder=0, alpha=0.25, linestyle=':', color='black') ax_PP_toi.axvspan(toi_specialteams_ticklabels[1], toi_specialteams_ticklabels[1], ymin=0, ymax=1, zorder=0, alpha=0.25, linestyle=':', color='black') ax_PK_toi.axvspan(toi_specialteams_ticklabels[1] / 2, toi_specialteams_ticklabels[1] / 2, ymin=0, ymax=1, zorder=0, alpha=0.25, linestyle=':', color='black') ax_PK_toi.axvspan(toi_specialteams_ticklabels[1], toi_specialteams_ticklabels[1], ymin=0, ymax=1, zorder=0, alpha=0.25, linestyle=':', color='black') # use the newly-minted x-ticklabels to ensure the x-axis labels will always display as integers ax_5v5_lines_shots.set_xticks(S_5v5_ticklabels, minor=False) ax_5v5_lines_toi.set_xticks(toi_5v5_ticklabels, minor=False) ax_5v5_pairings_shots.set_xticks(S_5v5_ticklabels, minor=False) ax_5v5_pairings_toi.set_xticks(toi_5v5_ticklabels, minor=False) ax_PP_shots.set_xticks(S_specialteams_ticklabels, minor=False) ax_PP_toi.set_xticks(toi_specialteams_ticklabels, minor=False) ax_PK_shots.set_xticks(S_specialteams_ticklabels, minor=False) ax_PK_toi.set_xticks(toi_specialteams_ticklabels, minor=False) # remove the borders to each subplot ax_5v5_lines_shots.spines["top"].set_visible(False) ax_5v5_lines_shots.spines["bottom"].set_visible(False) ax_5v5_lines_shots.spines["right"].set_visible(False) ax_5v5_lines_shots.spines["left"].set_visible(False) ax_5v5_lines_toi.spines["top"].set_visible(False) ax_5v5_lines_toi.spines["bottom"].set_visible(False) ax_5v5_lines_toi.spines["right"].set_visible(False) ax_5v5_lines_toi.spines["left"].set_visible(False) ax_5v5_pairings_shots.spines["top"].set_visible(False) ax_5v5_pairings_shots.spines["bottom"].set_visible(False) ax_5v5_pairings_shots.spines["right"].set_visible(False) ax_5v5_pairings_shots.spines["left"].set_visible(False) ax_5v5_pairings_toi.spines["top"].set_visible(False) ax_5v5_pairings_toi.spines["bottom"].set_visible(False) ax_5v5_pairings_toi.spines["right"].set_visible(False) ax_5v5_pairings_toi.spines["left"].set_visible(False) ax_PP_shots.spines["top"].set_visible(False) ax_PP_shots.spines["bottom"].set_visible(False) ax_PP_shots.spines["right"].set_visible(False) ax_PP_shots.spines["left"].set_visible(False) ax_PP_toi.spines["top"].set_visible(False) ax_PP_toi.spines["bottom"].set_visible(False) ax_PP_toi.spines["right"].set_visible(False) ax_PP_toi.spines["left"].set_visible(False) ax_PK_shots.spines["top"].set_visible(False) ax_PK_shots.spines["bottom"].set_visible(False) ax_PK_shots.spines["right"].set_visible(False) ax_PK_shots.spines["left"].set_visible(False) ax_PK_toi.spines["top"].set_visible(False) ax_PK_toi.spines["bottom"].set_visible(False) ax_PK_toi.spines["right"].set_visible(False) ax_PK_toi.spines["left"].set_visible(False) # add a legend for the shot type markers from matplotlib.lines import Line2D elements = [Line2D([0], [0], marker='D', markersize=5, markerfacecolor='None', markeredgecolor='black', linewidth=0, alpha=1, label='Scored'), Line2D([0], [0], marker='|', markersize=13, markerfacecolor='None', markeredgecolor='black', linewidth=0, alpha=1, label='Differential')] ax_PK_shots.legend(handles=elements, loc='center', bbox_to_anchor=(.5, -.6), ncol=2).get_frame().set_linewidth(0.0) # add text boxes with team names in white and with the team's color in the background fig.text(.425, 0.936, ' ' + away + ' ', color='white', fontsize='12', bbox=dict(facecolor=away_color, edgecolor='None')) fig.text(.525, 0.936, ' ' + home + ' ', fontsize='12', color='white', bbox=dict(facecolor=home_color, edgecolor='None')) fig.text(.490, 0.936, '@', color='black', fontsize='12', bbox=dict(facecolor='white', edgecolor='None')) # add a text box in the event a team does not have a power play if team_max_PP_toi == 0: fig.text(0.35, 0.375, 'No PP situations', color='black', fontsize='10', bbox=dict(facecolor='None', edgecolor='None')) # add a text box in the event a team's opponent does not have a power play if team_max_PK_toi == 0: fig.text(0.35, 0.175, 'No PK situations', color='black', fontsize='10', bbox=dict(facecolor='None', edgecolor='None')) # for games where one (or both!) teams spend no time on a powerplay or shorthanded, turn all indicators for the respective axes off if team_max_PP_toi == 0: ax_PP_shots.axis('off') ax_PP_toi.axis('off') if team_max_PK_toi == 0: ax_PK_shots.axis('off') ax_PK_toi.axis('off') ### ### SAVE TO FILE ### if team == away: plt.savefig(charts_units + 'onice_shots_away.png', bbox_inches='tight', pad_inches=0.2) elif team == home: plt.savefig(charts_units + 'onice_shots_home.png', bbox_inches='tight', pad_inches=0.2) # exercise a command-line option to show the current figure if images == 'show': plt.show() ### ### CLOSE ### plt.close(fig) # status update print('Plotting ' + team + ' lines, pairings and special teams units on-ice shots.') # status update print('Finished plotting the on-ice shots for lines, pairings and special teams units.')
def parse_ids(season_id, game_id, images): # pull common variables from the parameters file charts_players_individual = parameters.charts_players_individual files_root = parameters.files_root # generate date and team information schedule_csv = files_root + season_id + "_schedule.csv" schedule_df = pd.read_csv(schedule_csv) schedule_date = schedule_df[(schedule_df['GAME_ID'] == int(game_id))] date = schedule_date['DATE'].item() home = schedule_date['HOME'].item() away = schedule_date['AWAY'].item() teams = [away, home] # create variables that point to the .csv processed stats files for the team and players players_file = files_root + 'stats_players_individual.csv' # create a dataframe object that reads in info from the .csv files players_df = pd.read_csv(players_file) skaters_5v5_df = players_df.copy() skaters_5v5_df = skaters_5v5_df[(skaters_5v5_df['STATE'] == '5v5') & (skaters_5v5_df['POS'] != 'G')] max_5v5_toi = skaters_5v5_df['TOI'].max() skaters_PP_df = players_df.copy() skaters_PP_df = skaters_PP_df[(skaters_PP_df['STATE'] == 'PP') & (skaters_PP_df['POS'] != 'G')] max_PP_toi = skaters_PP_df['TOI'].max() skaters_SH_df = players_df.copy() skaters_SH_df = skaters_SH_df[(skaters_SH_df['STATE'] == 'PP') & (skaters_SH_df['POS'] != 'G')] max_SH_toi = skaters_SH_df['TOI'].max() # choose colors for each team; set them in a list; generate a custom colormap for each team away_color = dict_team_colors.team_color_1st[away] home_color = dict_team_colors.team_color_1st[home] # change one team's color from its primary option to, depending on the opponent, either a second, third or fourth option try: away_color = mod_switch_colors.switch_team_colors(away, home)[0] home_color = mod_switch_colors.switch_team_colors(away, home)[1] except: pass team_colors = [away_color, home_color] ### ### 5v5, PP, SH ### # loop through each team for team in teams: if team == away: team_color = team_colors[0] if team == home: team_color = team_colors[1] # create a dataframe; filter for team; sort by team, game state and position; rank by time on ice and then invert the rankings team_df = players_df.copy() team_df = team_df[(team_df['TEAM'] == team) & (team_df['POS'] != 'G')] # create columns for saved, missed and blocked shots; remove zeros from all the columns intended for plotting team_df['SS'] = team_df['ONS'] - team_df['G'] team_df['MS'] = team_df['US'] - team_df['ONS'] team_df['BS'] = team_df['S'] - team_df['US'] team_df['G'] = team_df['G'].replace(0, np.NaN) team_df['SS'] = team_df['SS'].replace(0, np.NaN) team_df['MS'] = team_df['MS'].replace(0, np.NaN) team_df['BS'] = team_df['BS'].replace(0, np.NaN) # create a filtered dataframe for each game state; sort by team, game state and position; rank by time on ice and then invert the rankings team_5v5_df = team_df.copy() team_5v5_df = team_5v5_df[(team_5v5_df['STATE'] == '5v5')] team_5v5_df = team_5v5_df.sort_values(by=['TOI'], ascending=True) team_5v5_df['RANK'] = team_5v5_df['TOI'].rank(method='first') team_5v5_df['RANK'] -= 1 team_PP_df = team_df.copy() team_PP_df = team_PP_df[(team_PP_df['STATE'] == 'PP') & (team_PP_df['TOI'] > 0)] team_PP_df = team_PP_df.sort_values(by=['TOI'], ascending=True) team_PP_df = team_PP_df.iloc[-10:] team_PP_df['RANK'] = team_PP_df['TOI'].rank(method='first') team_PP_df['RANK'] -= 1 team_SH_df = team_df.copy() team_SH_df = team_SH_df[(team_SH_df['STATE'] == 'SH') & (team_SH_df['TOI'] > 0)] team_SH_df = team_SH_df.sort_values(by=['TOI'], ascending=True) team_SH_df = team_SH_df.iloc[-10:] team_SH_df['RANK'] = team_SH_df['TOI'].rank(method='first') team_SH_df['RANK'] -= 1 # for each game state, create a dataframe with just the time on ice column; set a max value; scale each player's time on ice relative to the max toi_5v5 = team_5v5_df['TOI'] max_toi_5v5 = toi_5v5.max() toi_PP = team_PP_df['TOI'] max_toi_PP = toi_PP.max() team_PP_toi = max_toi_PP toi_SH = team_SH_df['TOI'] max_toi_SH = toi_SH.max() team_SH_toi = max_toi_SH # create a figure with six subplots arrangled complexly using a grid structure fig = plt.figure(figsize=(8, 8)) grid = plt.GridSpec(5, 8, hspace=0.75, wspace=0.75) ax_5v5_shots = fig.add_subplot(grid[0:-2, :-1]) ax_5v5_toi = fig.add_subplot(grid[0:-2, 7]) ax_PP_shots = fig.add_subplot(grid[3:, :2]) ax_PP_toi = fig.add_subplot(grid[3:, 2]) ax_SH_shots = fig.add_subplot(grid[3:, 5:-1]) ax_SH_toi = fig.add_subplot(grid[3:, 7]) # set the plot title fig.suptitle(date + ' Skaters Individual Shots\n\n') # set the axes titles ax_5v5_shots.set_title('5v5 S', fontsize=10) ax_5v5_toi.set_title('5v5 TOI', fontsize=10) ax_PP_shots.set_title('PP S', fontsize=10) ax_PP_toi.set_title('PP TOI', fontsize=10) ax_SH_shots.set_title('SH S', fontsize=10) ax_SH_toi.set_title('SH TOI', fontsize=10) # create markers for the plot legend try: G_marker = team_5v5_df.plot(x='G', y='RANK', marker='D', markersize=11, markerfacecolor='None', markeredgecolor='black', linewidth=0, alpha=1, legend='Scored', label='Scored', ax=ax_5v5_shots) except: pass try: SS_marker = team_5v5_df.plot(x='SS', y='RANK', marker='o', markersize=7, markerfacecolor='None', markeredgecolor='black', linewidth=0, alpha=1, legend='Saved', label='Saved', ax=ax_5v5_shots) except: pass try: MS_marker = team_5v5_df.plot(x='MS', y='RANK', marker='x', markersize=7, markeredgewidth=1, color='black', linewidth=0, alpha=1, legend='Missed', label='Missed', ax=ax_5v5_shots) except: pass try: BS_marker = team_5v5_df.plot(x='BS', y='RANK', marker='_', markersize=13, markeredgewidth=1, color='black', linewidth=0, alpha=1, legend='Blocked', label='Blocked', ax=ax_5v5_shots) except: pass # for each state, plot the bars for total shots and markers for saved, missed and blocked shots markers try: S_5v5_plot = team_5v5_df.plot.barh(x='PLAYER', y='S', color=team_color, edgecolor=None, width=0.75, legend=None, label='', ax=ax_5v5_shots) except: pass try: G_5v5_marker = team_5v5_df.plot(x='G', y='RANK', marker='D', markersize=11, markerfacecolor='None', markeredgecolor='white', linewidth=0, alpha=1, legend='', label='', ax=ax_5v5_shots) except: pass try: SS_5v5_marker = team_5v5_df.plot(x='SS', y='RANK', marker='o', markersize=7, markerfacecolor='None', markeredgecolor='white', linewidth=0, alpha=1, legend='', label='', ax=ax_5v5_shots) except: pass try: MS_5v5_marker = team_5v5_df.plot(x='MS', y='RANK', marker='x', markersize=7, markeredgewidth=1, color='white', linewidth=0, alpha=1, legend='', label='', ax=ax_5v5_shots) except: pass try: BS_5v5_marker = team_5v5_df.plot(x='BS', y='RANK', marker='_', markersize=13, markeredgewidth=1, color='white', linewidth=0, alpha=1, legend='', label='', ax=ax_5v5_shots) except: pass if team_PP_toi != 0: try: S_PP_plot = team_PP_df.plot.barh(x='PLAYER', y='S', color=team_color, edgecolor=None, width=0.75, legend=None, label='', ax=ax_PP_shots) except: pass try: G_PP_marker = team_PP_df.plot(x='G', y='RANK', marker='D', markersize=11, markerfacecolor='None', markeredgecolor='white', linewidth=0, alpha=1, legend='', label='', ax=ax_PP_shots) except: pass try: SS_PP_marker = team_PP_df.plot(x='SS', y='RANK', marker='o', markersize=7, markerfacecolor='None', markeredgecolor='white', linewidth=0, alpha=1, legend='', label='', ax=ax_PP_shots) except: pass try: MS_PP_marker = team_PP_df.plot(x='MS', y='RANK', marker='x', markersize=7, markeredgewidth=1, color='white', linewidth=0, alpha=1, legend='', label='', ax=ax_PP_shots) except: pass try: BS_PP_marker = team_PP_df.plot(x='BS', y='RANK', marker='_', markersize=13, markeredgewidth=1, color='white', linewidth=0, alpha=1, legend='', label='', ax=ax_PP_shots) except: pass if team_SH_toi != 0: try: S_SH_plot = team_SH_df.plot.barh(x='PLAYER', y='S', color=team_color, edgecolor=None, width=0.75, legend=None, label='', ax=ax_SH_shots) except: pass try: G_SH_marker = team_SH_df.plot(x='G', y='RANK', marker='D', markersize=11, markerfacecolor='None', markeredgecolor='white', linewidth=0, alpha=1, legend='', label='', ax=ax_SH_shots) except: pass try: SS_SH_marker = team_SH_df.plot(x='SS', y='RANK', marker='o', markersize=7, markerfacecolor='None', markeredgecolor='white', linewidth=0, alpha=1, legend='', label='', ax=ax_SH_shots) except: pass try: MS_SH_marker = team_SH_df.plot(x='MS', y='RANK', marker='x', markersize=7, markeredgewidth=1, color='white', linewidth=0, alpha=1, legend='', label='', ax=ax_SH_shots) except: pass try: BS_SH_marker = team_SH_df.plot(x='BS', y='RANK', marker='_', markersize=11, markeredgewidth=1, color='white', linewidth=0, alpha=1, legend='', label='', ax=ax_SH_shots) except: pass # for each state, plot the bars for time on ice try: toi_5v5_plot = team_5v5_df.plot.barh(x='PLAYER', y='TOI', color='white', edgecolor=team_color, width=0.75, legend=None, label='', ax=ax_5v5_toi) except: pass if team_PP_toi != 0: try: toi_PP_plot = team_PP_df.plot.barh(x='PLAYER', y='TOI', color='white', edgecolor=team_color, width=0.75, legend=None, label='', ax=ax_PP_toi) except: pass if team_SH_toi != 0: try: toi_SH_plot = team_SH_df.plot.barh(x='PLAYER', y='TOI', color='white', edgecolor=team_color, width=0.75, legend=None, label='', ax=ax_SH_toi) except: pass # set / remove the y-labels for the subplots ax_5v5_shots.set_xlabel('') ax_5v5_shots.set_ylabel('', fontsize=10) ax_5v5_toi.set_xlabel('') ax_5v5_toi.set_ylabel('') ax_PP_shots.set_xlabel('') ax_PP_shots.set_ylabel('', fontsize=10) ax_PP_toi.set_xlabel('') ax_PP_toi.set_ylabel('') ax_SH_shots.set_xlabel('') ax_SH_shots.set_ylabel('', fontsize=10) ax_SH_toi.set_xlabel('') ax_SH_toi.set_ylabel('') # change the tick parameters for each axes ax_5v5_shots.tick_params( axis='both', # changes apply to the x-axis which='both', # both major and minor ticks are affected bottom=False, # ticks along the bottom edge are off top=False, # ticks along the top edge are off left=False, # ticks along the left edge are off labelbottom=True) # labels along the bottom edge are on ax_5v5_toi.tick_params( axis='both', # changes apply to the x-axis which='both', # both major and minor ticks are affected bottom=False, # ticks along the bottom edge are off top=False, # ticks along the top edge are off left=False, # ticks along the left edge are off labelleft=False, # labels along the left edge are off labelbottom=True) # labels along the bottom edge are on ax_PP_shots.tick_params( axis='both', # changes apply to the x-axis which='both', # both major and minor ticks are affected bottom=False, # ticks along the bottom edge are off top=False, # ticks along the top edge are off left=False, # ticks along the left edge are off labelbottom=True) # labels along the bottom edge are on ax_PP_toi.tick_params( axis='both', # changes apply to the x-axis which='both', # both major and minor ticks are affected bottom=False, # ticks along the bottom edge are off top=False, # ticks along the top edge are off left=False, # ticks along the left edge are off labelleft=False, # labels along the left edge are off labelbottom=True) # labels along the bottom edge are on ax_SH_shots.tick_params( axis='both', # changes apply to the x-axis which='both', # both major and minor ticks are affected bottom=False, # ticks along the bottom edge are off top=False, # ticks along the top edge are off left=False, # ticks along the left edge are off labelbottom=True) # labels along the bottom edge are on ax_SH_toi.tick_params( axis='both', # changes apply to the x-axis which='both', # both major and minor ticks are affected bottom=False, # ticks along the bottom edge are off top=False, # ticks along the top edge are off left=False, # ticks along the left edge are off labelleft=False, # labels along the left edge are off labelbottom=True) # labels along the bottom edge are on # change the y-axis label colors ax_5v5_shots.tick_params(axis='y', which='both', labelcolor=team_color) ax_PP_shots.tick_params(axis='y', which='both', labelcolor=team_color) ax_SH_shots.tick_params(axis='y', which='both', labelcolor=team_color) # create a list of x-axis tick values contingent on the max values for shots S_5v5_max = team_5v5_df['S'] S_5v5_tickmax = S_5v5_max.max() S_5v5_ticklabels = [] if S_5v5_tickmax <= 10: S_5v5_ticklabels = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10] if S_5v5_tickmax > 10 and S_5v5_tickmax <= 20: S_5v5_ticklabels = [0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20] toi_5v5_tickmax = max_5v5_toi toi_5v5_ticklabels = [] if toi_5v5_tickmax <= 10: toi_5v5_ticklabels = [0, 10] if toi_5v5_tickmax > 10 and toi_5v5_tickmax <= 15: toi_5v5_ticklabels = [0, 15] if toi_5v5_tickmax > 15 and toi_5v5_tickmax <= 20: toi_5v5_ticklabels = [0, 20] if toi_5v5_tickmax > 20 and toi_5v5_tickmax <= 25: toi_5v5_ticklabels = [0, 25] if toi_5v5_tickmax > 25 and toi_5v5_tickmax <= 30: toi_5v5_ticklabels = [0, 30] if toi_5v5_tickmax > 30 and toi_5v5_tickmax <= 35: toi_5v5_ticklabels = [0, 35] if toi_5v5_tickmax > 35 and toi_5v5_tickmax <= 40: toi_5v5_ticklabels = [0, 40] if toi_5v5_tickmax > 40 and toi_5v5_tickmax <= 45: toi_5v5_ticklabels = [0, 45] if toi_5v5_tickmax > 45 and toi_5v5_tickmax <= 50: toi_5v5_ticklabels = [0, 50] if toi_5v5_tickmax > 50 and toi_5v5_tickmax <= 55: toi_5v5_ticklabels = [0, 55] if toi_5v5_tickmax > 55 and toi_5v5_tickmax <= 60: toi_5v5_ticklabels = [0, 60] S_PP_max = team_PP_df['S'] S_PP_tickmax = S_PP_max.max() S_PP_ticklabels = [] if S_PP_tickmax <= 5: S_PP_ticklabels = [0, 1, 2, 3, 4, 5] if S_PP_tickmax > 5 and S_PP_tickmax <= 10: S_PP_ticklabels = [0, 2, 4, 6, 8, 10] if S_PP_tickmax > 10 and S_PP_tickmax <= 15: S_PP_ticklabels = [0, 3, 6, 9, 12, 15] S_SH_max = team_SH_df['S'] S_SH_tickmax = S_SH_max.max() S_SH_ticklabels = [] if S_SH_tickmax <= 5: S_SH_ticklabels = [0, 1, 2, 3, 4, 5] if S_SH_tickmax > 5 and S_SH_tickmax <= 10: S_SH_ticklabels = [0, 2, 4, 6, 8, 10] if S_SH_tickmax > 10 and S_SH_tickmax <= 15: S_SH_ticklabels = [0, 3, 6, 9, 12, 15] toi_PP_tickmax = max_PP_toi toi_SH_tickmax = max_SH_toi toi_specialteams_tickmax = float() if toi_PP_tickmax >= toi_SH_tickmax: toi_specialteams_tickmax = toi_PP_tickmax if toi_PP_tickmax < toi_SH_tickmax: toi_specialteams_tickmax = toi_SH_tickmax toi_specialteams_ticklabels = [] if toi_specialteams_tickmax <= 2: toi_specialteams_ticklabels = [0, 2] if toi_specialteams_tickmax > 2 and toi_specialteams_tickmax <= 4: toi_specialteams_ticklabels = [0, 4] if toi_specialteams_tickmax > 4 and toi_specialteams_tickmax <= 6: toi_specialteams_ticklabels = [0, 6] if toi_specialteams_tickmax > 6 and toi_specialteams_tickmax <= 8: toi_specialteams_ticklabels = [0, 8] if toi_specialteams_tickmax > 8 and toi_specialteams_tickmax <= 10: toi_specialteams_ticklabels = [0, 10] if toi_specialteams_tickmax > 10 and toi_specialteams_tickmax <= 12: toi_specialteams_ticklabels = [0, 12] if toi_specialteams_tickmax > 12 and toi_specialteams_tickmax <= 14: toi_specialteams_ticklabels = [0, 14] if toi_specialteams_tickmax > 14 and toi_specialteams_tickmax <= 16: toi_specialteams_ticklabels = [0, 16] if toi_specialteams_tickmax > 16 and toi_specialteams_tickmax <= 18: toi_specialteams_ticklabels = [0, 18] if toi_specialteams_tickmax > 18 and toi_specialteams_tickmax <= 20: toi_specialteams_ticklabels = [0, 20] # set vertical indicator for midpoint of time on ice max ax_5v5_toi.axvspan(toi_5v5_ticklabels[1] / 2, toi_5v5_ticklabels[1] / 2, ymin=0, ymax=1, zorder=0, alpha=0.25, linestyle=':', color='black') ax_5v5_toi.axvspan(toi_5v5_ticklabels[1], toi_5v5_ticklabels[1], ymin=0, ymax=1, zorder=0, alpha=0.25, linestyle=':', color='black') ax_PP_toi.axvspan(toi_specialteams_ticklabels[1] / 2, toi_specialteams_ticklabels[1] / 2, ymin=0, ymax=1, zorder=0, alpha=0.25, linestyle=':', color='black') ax_PP_toi.axvspan(toi_specialteams_ticklabels[1], toi_specialteams_ticklabels[1], ymin=0, ymax=1, zorder=0, alpha=0.25, linestyle=':', color='black') ax_SH_toi.axvspan(toi_specialteams_ticklabels[1] / 2, toi_specialteams_ticklabels[1] / 2, ymin=0, ymax=1, zorder=0, alpha=0.25, linestyle=':', color='black') ax_SH_toi.axvspan(toi_specialteams_ticklabels[1], toi_specialteams_ticklabels[1], ymin=0, ymax=1, zorder=0, alpha=0.25, linestyle=':', color='black') # use the newly-minted x-ticklabels to ensure the x-axis labels will always display as integers ax_5v5_shots.set_xticks(S_5v5_ticklabels, minor=False) ax_5v5_toi.set_xticks(toi_5v5_ticklabels, minor=False) ax_PP_shots.set_xticks(S_PP_ticklabels, minor=False) ax_PP_toi.set_xticks(toi_specialteams_ticklabels, minor=False) ax_SH_shots.set_xticks(S_SH_ticklabels, minor=False) ax_SH_toi.set_xticks(toi_specialteams_ticklabels, minor=False) # remove axes ticks for instances where there is no special teams play if team_PP_toi == 0: ax_PP_shots.set_xticks([], minor=False) ax_PP_shots.set_yticks([], minor=False) ax_PP_toi.set_xticks([], minor=False) ax_PP_toi.set_yticks([], minor=False) if team_SH_toi == 0: ax_SH_shots.set_xticks([], minor=False) ax_SH_shots.set_yticks([], minor=False) ax_SH_toi.set_xticks([], minor=False) ax_SH_toi.set_yticks([], minor=False) # remove the borders to each subplot ax_5v5_shots.spines["top"].set_visible(False) ax_5v5_shots.spines["bottom"].set_visible(False) ax_5v5_shots.spines["right"].set_visible(False) ax_5v5_shots.spines["left"].set_visible(False) ax_5v5_toi.spines["top"].set_visible(False) ax_5v5_toi.spines["bottom"].set_visible(False) ax_5v5_toi.spines["right"].set_visible(False) ax_5v5_toi.spines["left"].set_visible(False) ax_PP_shots.spines["top"].set_visible(False) ax_PP_shots.spines["bottom"].set_visible(False) ax_PP_shots.spines["right"].set_visible(False) ax_PP_shots.spines["left"].set_visible(False) ax_PP_toi.spines["top"].set_visible(False) ax_PP_toi.spines["bottom"].set_visible(False) ax_PP_toi.spines["right"].set_visible(False) ax_PP_toi.spines["left"].set_visible(False) ax_SH_shots.spines["top"].set_visible(False) ax_SH_shots.spines["bottom"].set_visible(False) ax_SH_shots.spines["right"].set_visible(False) ax_SH_shots.spines["left"].set_visible(False) ax_SH_toi.spines["top"].set_visible(False) ax_SH_toi.spines["bottom"].set_visible(False) ax_SH_toi.spines["right"].set_visible(False) ax_SH_toi.spines["left"].set_visible(False) # add a legend for the shot type markers ax_5v5_shots.legend(loc='center', bbox_to_anchor=(.55, -.9), ncol=4).get_frame().set_linewidth(0.0) # add text boxes with team names in white and with the team's color in the background fig.text(.425, 0.936, ' ' + away + ' ', color='white', fontsize='12', bbox=dict(facecolor=away_color, edgecolor='None')) fig.text(.525, 0.936, ' ' + home + ' ', fontsize='12', color='white', bbox=dict(facecolor=home_color, edgecolor='None')) fig.text(.490, 0.936, '@', color='black', fontsize='12', bbox=dict(facecolor='white', edgecolor='None')) ### ### SAVE TO FILE ### if team == away: plt.savefig(charts_players_individual + 'skaters_individual_shots_away.png', bbox_inches='tight', pad_inches=0.2) elif team == home: plt.savefig(charts_players_individual + 'skaters_individual_shots_home.png', bbox_inches='tight', pad_inches=0.2) # exercise a command-line option to show the current figure if images == 'show': plt.show() ### ### CLOSE ### plt.close(fig) # status update print('Plotting ' + team + ' skaters individual shots.') # status update print('Finished plotting the individual shots for skaters.')
def parse_ids(season_id, game_id, images): # pull common variables from the parameters file charts_players_composite_situation = parameters.charts_players_composite_situation files_root = parameters.files_root # generate date and team information schedule_csv = files_root + season_id + "_schedule.csv" schedule_df = pd.read_csv(schedule_csv) schedule_date = schedule_df[(schedule_df['GAME_ID'] == int(game_id))] date = schedule_date['DATE'].item() home = schedule_date['HOME'].item() away = schedule_date['AWAY'].item() teams = [away, home] # create variables that point to the .csv processed stats files for the team and players team_file = files_root + 'stats_teams_situation.csv' players_individual_file = files_root + 'stats_players_individual_situation.csv' players_onice_file = files_root + 'stats_players_onice_situation.csv' # create dataframe objects that read in info from the .csv files team_stats_df = pd.read_csv(team_file) players_individual_df = pd.read_csv(players_individual_file) players_individual_df = players_individual_df.rename(columns={'GS': 'iGS'}) players_individual_df = players_individual_df[[ 'TEAM', 'PLAYER', 'POS', 'STATE', 'SITUATION', 'TOI', 'iGS' ]] players_onice_df = pd.read_csv(players_onice_file) players_onice_df = players_onice_df.rename(columns={'GS': 'onGS'}) players_onice_df = players_onice_df[[ 'TEAM', 'PLAYER', 'POS', 'STATE', 'SITUATION', 'TOI', 'onGS' ]] players_df = pd.merge( players_individual_df, players_onice_df, on=['TEAM', 'PLAYER', 'POS', 'STATE', 'SITUATION', 'TOI'], how='inner') players_df['GS'] = players_df['iGS'] + players_df['onGS'] # create dataframes filtered for game state, then player type teams_all_df = players_df.copy() teams_all_df = teams_all_df[(teams_all_df['STATE'] == 'ALL')] teams_all_skaters_df = teams_all_df.copy() teams_all_skaters_df = teams_all_skaters_df[(teams_all_skaters_df['POS'] != 'G')] teams_all_goalies_df = teams_all_df.copy() teams_all_goalies_df = teams_all_goalies_df[( teams_all_goalies_df['POS'] == 'G')] teams_5v5_df = players_df.copy() teams_5v5_df = teams_5v5_df[(teams_5v5_df['STATE'] == '5v5')] teams_5v5_skaters_df = teams_5v5_df.copy() teams_5v5_skaters_df = teams_5v5_skaters_df[(teams_5v5_skaters_df['POS'] != 'G')] teams_5v5_goalies_df = teams_5v5_df.copy() teams_5v5_goalies_df = teams_5v5_goalies_df[( teams_5v5_goalies_df['POS'] == 'G')] teams_3v3_df = players_df.copy() teams_3v3_df = teams_3v3_df[(teams_3v3_df['STATE'] == '3v3')] teams_3v3_skaters_df = teams_3v3_df.copy() teams_3v3_skaters_df = teams_3v3_skaters_df[(teams_3v3_skaters_df['POS'] != 'G')] teams_3v3_goalies_df = teams_3v3_df.copy() teams_3v3_goalies_df = teams_3v3_goalies_df[( teams_3v3_goalies_df['POS'] == 'G')] teams_PP_df = players_df.copy() teams_PP_df = teams_PP_df[(teams_PP_df['STATE'] == 'PP')] teams_PP_skaters_df = teams_PP_df.copy() teams_PP_skaters_df = teams_PP_skaters_df[(teams_PP_skaters_df['POS'] != 'G')] teams_PP_goalies_df = teams_PP_df.copy() teams_PP_goalies_df = teams_PP_goalies_df[( teams_PP_goalies_df['POS'] == 'G')] teams_SH_df = players_df.copy() teams_SH_df = teams_SH_df[(teams_SH_df['STATE'] == 'SH')] teams_SH_skaters_df = teams_SH_df.copy() teams_SH_skaters_df = teams_SH_skaters_df[(teams_SH_skaters_df['POS'] != 'G')] teams_SH_goalies_df = teams_SH_df.copy() teams_SH_goalies_df = teams_SH_goalies_df[( teams_SH_goalies_df['POS'] == 'G')] # choose colors for each team; set them in a list; generate a custom colormap for each team away_color = dict_team_colors.team_color_1st[away] home_color = dict_team_colors.team_color_1st[home] # change one team's color from its primary option to, depending on the opponent, either a second, third or fourth option try: away_color = mod_switch_colors.switch_team_colors(away, home)[0] home_color = mod_switch_colors.switch_team_colors(away, home)[1] except: pass team_colors = [away_color, home_color] ### ### 5v5, PP, SH ### situations = ['Leading', 'Tied', 'Trailing'] # loop through each situation for situation in situations: if situation == 'Leading': home_situation = 'Leading' away_situation = 'Trailing' if situation == 'Tied': home_situation = 'Tied' away_situation = 'Tied' if situation == 'Trailing': home_situation = 'Trailing' away_situation = 'Leading' # add a loop for each team for team in teams: if team == away: team_color = team_colors[0] situation = away_situation if team == home: team_color = team_colors[1] situation = home_situation # create a dataframe from the team stats file for generating toi values for the different game states team_toi_df = team_stats_df.copy() team_all_toi = team_toi_df[(team_toi_df['TEAM'] == team) & (team_toi_df['STATE'] == 'ALL') & (team_toi_df['SITUATION'] == situation)] team_all_toi = team_all_toi['TOI'].item() team_5v5_toi = team_toi_df[(team_toi_df['TEAM'] == team) & (team_toi_df['STATE'] == '5v5') & (team_toi_df['SITUATION'] == situation)] team_5v5_toi = team_5v5_toi['TOI'].item() team_PP_toi = team_toi_df[(team_toi_df['TEAM'] == team) & (team_toi_df['STATE'] == 'PP') & (team_toi_df['SITUATION'] == situation)] team_PP_toi = team_PP_toi['TOI'].item() team_SH_toi = team_toi_df[(team_toi_df['TEAM'] == team) & (team_toi_df['STATE'] == 'SH') & (team_toi_df['SITUATION'] == situation)] team_SH_toi = team_SH_toi['TOI'].item() # create a dataframe; filter for team; sort by team, game state and position; rank by time on ice and then invert the rankings team_df = players_df.copy() team_df = team_df[(team_df['TEAM'] == team) & (team_df['SITUATION'] == situation)] # remove zeros from the individual gamescore, onice gamescore and overall gamescore columns team_df['iGS'] = team_df['iGS'].replace(0, np.NaN) team_df['onGS'] = team_df['onGS'].replace(0, np.NaN) team_df['GS'] = team_df['GS'].replace(0, np.NaN) # create a filtered dataframe for each game state; sort by team, game state and position; rank by time on ice and then invert the rankings team_5v5_skaters_df = teams_5v5_skaters_df.copy() team_5v5_skaters_df = team_5v5_skaters_df[ (team_5v5_skaters_df['TEAM'] == team) & (team_5v5_skaters_df['SITUATION'] == situation)] team_5v5_skaters_df = team_5v5_skaters_df.sort_values( by=['TOI'], ascending=True) team_5v5_skaters_df['RANK'] = team_5v5_skaters_df['TOI'].rank( method='first') team_5v5_skaters_df['RANK'] -= 1 team_5v5_goalies_df = teams_5v5_goalies_df.copy() team_5v5_goalies_df = team_5v5_goalies_df[ (team_5v5_goalies_df['TEAM'] == team) & (team_5v5_goalies_df['SITUATION'] == situation)] team_5v5_goalies_df = team_5v5_goalies_df.sort_values( by=['TOI'], ascending=True) team_5v5_goalies_df['RANK'] = team_5v5_goalies_df['TOI'].rank( method='first') team_5v5_goalies_df['RANK'] -= 1 team_PP_skaters_df = teams_PP_skaters_df.copy() team_PP_skaters_df = team_PP_skaters_df[ (team_PP_skaters_df['TEAM'] == team) & (team_PP_skaters_df['SITUATION'] == situation)] team_PP_skaters_df = team_PP_skaters_df[(team_PP_skaters_df['TOI'] > 0)] team_PP_skaters_df = team_PP_skaters_df.sort_values(by=['TOI'], ascending=True) team_PP_skaters_df = team_PP_skaters_df.iloc[-10:] team_PP_skaters_df['RANK'] = team_PP_skaters_df['TOI'].rank( method='first') team_PP_skaters_df['RANK'] -= 1 team_PP_goalies_df = teams_PP_goalies_df.copy() team_PP_goalies_df = team_PP_goalies_df[ (team_PP_goalies_df['TEAM'] == team) & (team_PP_goalies_df['SITUATION'] == situation)] team_PP_goalies_df = team_PP_goalies_df[(team_PP_goalies_df['TOI'] > 0)] team_PP_goalies_df = team_PP_goalies_df.sort_values(by=['TOI'], ascending=True) team_PP_goalies_df['RANK'] = team_PP_goalies_df['TOI'].rank( method='first') team_PP_goalies_df['RANK'] -= 1 team_SH_skaters_df = teams_SH_skaters_df.copy() team_SH_skaters_df = team_SH_skaters_df[ (team_SH_skaters_df['TEAM'] == team) & (team_SH_skaters_df['SITUATION'] == situation)] team_SH_skaters_df = team_SH_skaters_df[(team_SH_skaters_df['TOI'] > 0)] team_SH_skaters_df = team_SH_skaters_df.sort_values(by=['TOI'], ascending=True) team_SH_skaters_df = team_SH_skaters_df.iloc[-10:] team_SH_skaters_df['RANK'] = team_SH_skaters_df['TOI'].rank( method='first') team_SH_skaters_df['RANK'] -= 1 team_SH_goalies_df = teams_SH_goalies_df.copy() team_SH_goalies_df = team_SH_goalies_df[ (team_SH_goalies_df['TEAM'] == team) & (team_SH_goalies_df['SITUATION'] == situation)] team_SH_goalies_df = team_SH_goalies_df[(team_SH_goalies_df['TOI'] > 0)] team_SH_goalies_df = team_SH_goalies_df.sort_values(by=['TOI'], ascending=True) team_SH_goalies_df['RANK'] = team_SH_goalies_df['TOI'].rank( method='first') team_SH_goalies_df['RANK'] -= 1 # for each game state, create a dataframe with just the time on ice column; set a max value; scale each player's time on ice relative to the max toi_5v5_skaters = team_5v5_skaters_df['TOI'] max_toi_5v5_skaters = toi_5v5_skaters.max() toi_5v5_goalies = team_5v5_goalies_df['TOI'] max_toi_5v5_goalies = toi_5v5_goalies.max() toi_PP_skaters = team_PP_skaters_df['TOI'] max_toi_PP_skaters = toi_PP_skaters.max() toi_PP_goalies = team_PP_goalies_df['TOI'] max_toi_PP_goalies = toi_PP_goalies.max() toi_SH_skaters = team_SH_skaters_df['TOI'] max_toi_SH_skaters = toi_SH_skaters.max() toi_SH_goalies = team_SH_goalies_df['TOI'] max_toi_SH_goalies = toi_SH_goalies.max() # create a figure with six subplots arrangled complexly using a grid structure fig = plt.figure(figsize=(9, 9)) grid = plt.GridSpec(11, 8, hspace=0.25, wspace=0.75) ax_5v5_skaters_gamescore = fig.add_subplot(grid[0:5, :-1]) ax_5v5_skaters_toi = fig.add_subplot(grid[0:5, 7]) ax_5v5_goalies_gamescore = fig.add_subplot(grid[5:6, :-1]) ax_5v5_goalies_toi = fig.add_subplot(grid[5:6, 7]) ax_gap = fig.add_subplot(grid[6:7, :]) ax_PP_skaters_gamescore = fig.add_subplot(grid[7:10, :2]) ax_PP_skaters_toi = fig.add_subplot(grid[7:10, 2]) ax_PP_goalies_gamescore = fig.add_subplot(grid[10:, :2]) ax_PP_goalies_toi = fig.add_subplot(grid[10:, 2]) ax_SH_skaters_gamescore = fig.add_subplot(grid[7:10, 5:-1]) ax_SH_skaters_toi = fig.add_subplot(grid[7:10, 7]) ax_SH_goalies_gamescore = fig.add_subplot(grid[10:, 5:-1]) ax_SH_goalies_toi = fig.add_subplot(grid[10:, 7]) # set the plot title if team == away: fig.suptitle(date + ' GameScores (Away ' + situation + ')\n\n') if team == home: fig.suptitle(date + ' GameScores (Home ' + situation + ')\n\n') # set the axes titles ax_5v5_skaters_gamescore.set_title('5v5 GS', fontsize=10) ax_5v5_skaters_toi.set_title('5v5 TOI', fontsize=10) ax_5v5_goalies_gamescore.set_title('', fontsize=10) ax_5v5_goalies_toi.set_title('', fontsize=10) ax_PP_skaters_gamescore.set_title('PP GS', fontsize=10) ax_PP_skaters_toi.set_title('PP TOI', fontsize=10) ax_PP_goalies_gamescore.set_title('', fontsize=10) ax_PP_goalies_toi.set_title('', fontsize=10) ax_SH_skaters_gamescore.set_title('SH GS', fontsize=10) ax_SH_skaters_toi.set_title('SH TOI', fontsize=10) ax_SH_goalies_gamescore.set_title('', fontsize=10) ax_SH_goalies_toi.set_title('', fontsize=10) # ensure the gap axis is transparent ax_gap.set_facecolor('None') # for each state, plot the bars for total gamescore try: GS_5v5_skaters_plot = team_5v5_skaters_df.plot.barh( x='PLAYER', y='GS', color=team_color, edgecolor='None', width=0.75, legend=None, label='', ax=ax_5v5_skaters_gamescore) except: pass try: GS_5v5_goalies_plot = team_5v5_goalies_df.plot.barh( x='PLAYER', y='GS', color=team_color, edgecolor='None', width=0.25, legend=None, label='', ax=ax_5v5_goalies_gamescore) except: pass if team_PP_toi != 0: try: GS_PP_skaters_plot = team_PP_skaters_df.plot.barh( x='PLAYER', y='GS', color=team_color, edgecolor='None', width=0.75, legend=None, label='', ax=ax_PP_skaters_gamescore) except: pass try: GS_PP_goalies_plot = team_PP_goalies_df.plot.barh( x='PLAYER', y='GS', color=team_color, edgecolor='None', width=0.25, legend=None, label='', ax=ax_PP_goalies_gamescore) except: pass if team_SH_toi != 0: try: GS_SH_skaters_plot = team_SH_skaters_df.plot.barh( x='PLAYER', y='GS', color=team_color, edgecolor='None', width=0.75, legend=None, label='', ax=ax_SH_skaters_gamescore) except: pass try: GS_SH_goalies_plot = team_SH_goalies_df.plot.barh( x='PLAYER', y='GS', color=team_color, edgecolor='None', width=0.25, legend=None, label='', ax=ax_SH_goalies_gamescore) except: pass # for each state, plot the bars for time on ice try: toi_5v5_skaters_plot = team_5v5_skaters_df.plot.barh( x='PLAYER', y='TOI', color='white', edgecolor=team_color, width=0.75, legend=None, label='', ax=ax_5v5_skaters_toi) except: pass try: toi_5v5_goalies_plot = team_5v5_goalies_df.plot.barh( x='PLAYER', y='TOI', color='white', edgecolor=team_color, width=0.25, legend=None, label='', ax=ax_5v5_goalies_toi) except: pass if team_PP_toi != 0: try: toi_PP_skaters_plot = team_PP_skaters_df.plot.barh( x='PLAYER', y='TOI', color='white', edgecolor=team_color, width=0.75, legend=None, label='', ax=ax_PP_skaters_toi) except: pass try: toi_PP_goalies_plot = team_PP_goalies_df.plot.barh( x='PLAYER', y='TOI', color='white', edgecolor=team_color, width=0.25, legend=None, label='', ax=ax_PP_goalies_toi) except: pass if team_SH_toi != 0: try: toi_SH_skaters_plot = team_SH_skaters_df.plot.barh( x='PLAYER', y='TOI', color='white', edgecolor=team_color, width=0.75, legend=None, label='', ax=ax_SH_skaters_toi) except: pass try: toi_SH_goalies_plot = team_SH_goalies_df.plot.barh( x='PLAYER', y='TOI', color='white', edgecolor=team_color, width=0.25, legend=None, label='', ax=ax_SH_goalies_toi) except: pass # set / remove the y-labels for the subplots ax_5v5_skaters_gamescore.set_xlabel('') ax_5v5_skaters_gamescore.set_ylabel('', fontsize=10) ax_5v5_skaters_toi.set_xlabel('') ax_5v5_skaters_toi.set_ylabel('') ax_5v5_goalies_gamescore.set_xlabel('') ax_5v5_goalies_gamescore.set_ylabel('', fontsize=10) ax_5v5_goalies_toi.set_xlabel('') ax_5v5_goalies_toi.set_ylabel('') ax_gap.set_xlabel('') ax_gap.set_ylabel('', fontsize=10) ax_PP_skaters_gamescore.set_xlabel('') ax_PP_skaters_gamescore.set_ylabel('', fontsize=10) ax_PP_skaters_toi.set_xlabel('') ax_PP_skaters_toi.set_ylabel('') ax_PP_goalies_gamescore.set_xlabel('') ax_PP_goalies_gamescore.set_ylabel('', fontsize=10) ax_PP_goalies_toi.set_xlabel('') ax_PP_goalies_toi.set_ylabel('') ax_SH_skaters_gamescore.set_xlabel('') ax_SH_skaters_gamescore.set_ylabel('', fontsize=10) ax_SH_skaters_toi.set_xlabel('') ax_SH_skaters_toi.set_ylabel('') ax_SH_goalies_gamescore.set_xlabel('') ax_SH_goalies_gamescore.set_ylabel('', fontsize=10) ax_SH_goalies_toi.set_xlabel('') ax_SH_goalies_toi.set_ylabel('') # set vertical indicators for break-even gamescore ax_5v5_skaters_gamescore.axvspan(0, 0, ymin=0, ymax=1, alpha=.25, zorder=0, linestyle=':', color='black') ax_5v5_goalies_gamescore.axvspan(0, 0, ymin=0, ymax=1, alpha=.25, zorder=0, linestyle=':', color='black') ax_PP_skaters_gamescore.axvspan(0, 0, ymin=0, ymax=1, alpha=.25, zorder=0, linestyle=':', color='black') ax_PP_goalies_gamescore.axvspan(0, 0, ymin=0, ymax=1, alpha=.25, zorder=0, linestyle=':', color='black') ax_SH_skaters_gamescore.axvspan(0, 0, ymin=0, ymax=1, alpha=.25, zorder=0, linestyle=':', color='black') ax_SH_goalies_gamescore.axvspan(0, 0, ymin=0, ymax=1, alpha=.25, zorder=0, linestyle=':', color='black') # change the tick parameters for each axes ax_5v5_skaters_gamescore.tick_params( axis='both', # changes apply to the x-axis which='both', # both major and minor ticks are affected bottom=False, # ticks along the bottom edge are off top=False, # ticks along the top edge are off left=False, # ticks along the left edge are off labelbottom=False) # labels along the bottom edge are off ax_5v5_skaters_toi.tick_params( axis='both', # changes apply to the x-axis which='both', # both major and minor ticks are affected bottom=False, # ticks along the bottom edge are off top=False, # ticks along the top edge are off left=False, # ticks along the left edge are off labelleft=False, # labels along the left edge are off labelbottom=False) # labels along the bottom edge are off ax_5v5_goalies_gamescore.tick_params( axis='both', # changes apply to the x-axis which='both', # both major and minor ticks are affected bottom=False, # ticks along the bottom edge are off top=False, # ticks along the top edge are off left=False, # ticks along the left edge are off labelbottom=True) # labels along the bottom edge are off ax_5v5_goalies_toi.tick_params( axis='both', # changes apply to the x-axis which='both', # both major and minor ticks are affected bottom=False, # ticks along the bottom edge are off top=False, # ticks along the top edge are off left=False, # ticks along the left edge are off labelleft=False, # labels along the left edge are off labelbottom=True) # labels along the bottom edge are off ax_gap.tick_params( axis='both', # changes apply to the x-axis which='both', # both major and minor ticks are affected bottom=False, # ticks along the bottom edge are off top=False, # ticks along the top edge are off left=False, # ticks along the left edge are off labelbottom=False) # labels along the bottom edge are off ax_gap.tick_params( axis='both', # changes apply to the x-axis which='both', # both major and minor ticks are affected bottom=False, # ticks along the bottom edge are off top=False, # ticks along the top edge are off left=False, # ticks along the left edge are off labelleft=False, # labels along the left edge are off labelbottom=False) # labels along the bottom edge are off ax_PP_skaters_gamescore.tick_params( axis='both', # changes apply to the x-axis which='both', # both major and minor ticks are affected bottom=False, # ticks along the bottom edge are off top=False, # ticks along the top edge are off left=False, # ticks along the left edge are off labelbottom=False) # labels along the bottom edge are off ax_PP_skaters_toi.tick_params( axis='both', # changes apply to the x-axis which='both', # both major and minor ticks are affected bottom=False, # ticks along the bottom edge are off top=False, # ticks along the top edge are off left=False, # ticks along the left edge are off labelleft= False, # labels along the left edge are off labelbottom=False) # labels along the bottom edge are off ax_PP_goalies_gamescore.tick_params( axis='both', # changes apply to the x-axis which='both', # both major and minor ticks are affected bottom=False, # ticks along the bottom edge are off top=False, # ticks along the top edge are off left=False, # ticks along the left edge are off labelbottom=True) # labels along the bottom edge are on ax_PP_goalies_toi.tick_params( axis='both', # changes apply to the x-axis which='both', # both major and minor ticks are affected bottom=False, # ticks along the bottom edge are off top=False, # ticks along the top edge are off left=False, # ticks along the left edge are off labelleft= False, # labels along the left edge are off labelbottom=True) # labels along the bottom edge are on ax_SH_skaters_gamescore.tick_params( axis='both', # changes apply to the x-axis which='both', # both major and minor ticks are affected bottom=False, # ticks along the bottom edge are off top=False, # ticks along the top edge are off left=False, # ticks along the left edge are off labelbottom=False) # labels along the bottom edge are off ax_SH_skaters_toi.tick_params( axis='both', # changes apply to the x-axis which='both', # both major and minor ticks are affected bottom=False, # ticks along the bottom edge are off top=False, # ticks along the top edge are off left=False, # ticks along the left edge are off labelleft=False, # labels along the left edge are off labelbottom=False) # labels along the bottom edge are off ax_SH_goalies_gamescore.tick_params( axis='both', # changes apply to the x-axis which='both', # both major and minor ticks are affected bottom=False, # ticks along the bottom edge are off top=False, # ticks along the top edge are off left=False, # ticks along the left edge are off labelbottom=True) # labels along the bottom edge are on ax_SH_goalies_toi.tick_params( axis='both', # changes apply to the x-axis which='both', # both major and minor ticks are affected bottom=False, # ticks along the bottom edge are off top=False, # ticks along the top edge are off left=False, # ticks along the left edge are off labelleft=False, # labels along the left edge are off labelbottom=True) # labels along the bottom edge are on # change the y-axis label colors ax_5v5_skaters_gamescore.tick_params(axis='y', which='both', labelcolor=team_color) ax_5v5_goalies_gamescore.tick_params(axis='y', which='both', labelcolor=team_color) ax_PP_skaters_gamescore.tick_params(axis='y', which='both', labelcolor=team_color) ax_PP_goalies_gamescore.tick_params(axis='y', which='both', labelcolor=team_color) ax_SH_skaters_gamescore.tick_params(axis='y', which='both', labelcolor=team_color) ax_SH_goalies_gamescore.tick_params(axis='y', which='both', labelcolor=team_color) # create a list of x-axis tick values contingent on the max values for gamescore GS_5v5_maxmin = teams_5v5_df['GS'] GS_5v5_max = round(GS_5v5_maxmin.max(), 1) GS_5v5_min = abs(round(GS_5v5_maxmin.min(), 1)) GS_5v5_tickmax = int() GS_5v5_tickmin = int() if GS_5v5_max >= GS_5v5_min: GS_5v5_tickmax = GS_5v5_max GS_5v5_tickmin = GS_5v5_max * -1 if GS_5v5_max < GS_5v5_min: GS_5v5_tickmax = GS_5v5_min GS_5v5_tickmin = GS_5v5_min * -1 GS_5v5_ticklabels = [ GS_5v5_tickmin, round((GS_5v5_tickmin / 2), 1), 0, round((GS_5v5_tickmax / 2), 1), GS_5v5_tickmax ] toi_5v5_tickmax = max_toi_5v5_goalies toi_5v5_ticklabels = [] if toi_5v5_tickmax <= 5: toi_5v5_ticklabels = [0, 5] if toi_5v5_tickmax > 5 and toi_5v5_tickmax <= 10: toi_5v5_ticklabels = [0, 10] if toi_5v5_tickmax > 10 and toi_5v5_tickmax <= 15: toi_5v5_ticklabels = [0, 15] if toi_5v5_tickmax > 15 and toi_5v5_tickmax <= 20: toi_5v5_ticklabels = [0, 20] if toi_5v5_tickmax > 20 and toi_5v5_tickmax <= 25: toi_5v5_ticklabels = [0, 25] if toi_5v5_tickmax > 25 and toi_5v5_tickmax <= 30: toi_5v5_ticklabels = [0, 30] if toi_5v5_tickmax > 30 and toi_5v5_tickmax <= 35: toi_5v5_ticklabels = [0, 35] if toi_5v5_tickmax > 35 and toi_5v5_tickmax <= 40: toi_5v5_ticklabels = [0, 40] if toi_5v5_tickmax > 40 and toi_5v5_tickmax <= 45: toi_5v5_ticklabels = [0, 45] if toi_5v5_tickmax > 45 and toi_5v5_tickmax <= 50: toi_5v5_ticklabels = [0, 50] if toi_5v5_tickmax > 50 and toi_5v5_tickmax <= 55: toi_5v5_ticklabels = [0, 55] if toi_5v5_tickmax > 55 and toi_5v5_tickmax <= 60: toi_5v5_ticklabels = [0, 60] GS_PP_maxmin = teams_PP_df['GS'] GS_PP_max = round(GS_PP_maxmin.max(), 1) GS_PP_min = abs(round(GS_PP_maxmin.min(), 1)) GS_PP_tickmax = int() GS_PP_tickmin = int() if GS_PP_max >= GS_PP_min: GS_PP_tickmax = GS_PP_max GS_PP_tickmin = GS_PP_max * -1 if GS_PP_max < GS_PP_min: GS_PP_tickmax = GS_PP_min GS_PP_tickmin = GS_PP_min * -1 GS_PP_ticklabels = [ GS_PP_tickmin, round((GS_PP_tickmin / 2), 1), 0, round((GS_PP_tickmax / 2), 1), GS_PP_tickmax ] GS_SH_maxmin = teams_SH_df['GS'] GS_SH_max = round(GS_SH_maxmin.max(), 1) GS_SH_min = abs(round(GS_SH_maxmin.min(), 1)) GS_SH_tickmax = int() GS_SH_tickmin = int() if GS_SH_max >= GS_SH_min: GS_SH_tickmax = GS_SH_max GS_SH_tickmin = GS_SH_max * -1 if GS_SH_max < GS_SH_min: GS_SH_tickmax = GS_SH_min GS_SH_tickmin = GS_SH_min * -1 GS_SH_ticklabels = [ GS_SH_tickmin, round((GS_SH_tickmin / 2), 1), 0, round((GS_SH_tickmax / 2), 1), GS_SH_tickmax ] toi_PP_skaters_tickmax = max_toi_PP_goalies toi_SH_skaters_tickmax = max_toi_SH_goalies toi_specialteams_tickmax = int() if toi_PP_skaters_tickmax >= toi_SH_skaters_tickmax: toi_specialteams_tickmax = toi_PP_skaters_tickmax if toi_PP_skaters_tickmax < toi_SH_skaters_tickmax: toi_specialteams_tickmax = toi_SH_skaters_tickmax toi_specialteams_ticklabels = [] if toi_specialteams_tickmax <= 2: toi_specialteams_ticklabels = [0, 2] if toi_specialteams_tickmax > 2 and toi_specialteams_tickmax <= 4: toi_specialteams_ticklabels = [0, 4] if toi_specialteams_tickmax > 4 and toi_specialteams_tickmax <= 6: toi_specialteams_ticklabels = [0, 6] if toi_specialteams_tickmax > 6 and toi_specialteams_tickmax <= 8: toi_specialteams_ticklabels = [0, 8] if toi_specialteams_tickmax > 8 and toi_specialteams_tickmax <= 10: toi_specialteams_ticklabels = [0, 10] if toi_specialteams_tickmax > 10 and toi_specialteams_tickmax <= 12: toi_specialteams_ticklabels = [0, 12] if toi_specialteams_tickmax > 12 and toi_specialteams_tickmax <= 14: toi_specialteams_ticklabels = [0, 14] if toi_specialteams_tickmax > 14 and toi_specialteams_tickmax <= 16: toi_specialteams_ticklabels = [0, 16] if toi_specialteams_tickmax > 16 and toi_specialteams_tickmax <= 18: toi_specialteams_ticklabels = [0, 18] if toi_specialteams_tickmax > 18 and toi_specialteams_tickmax <= 20: toi_specialteams_ticklabels = [0, 20] # set vertical indicator for midpoint of time on ice max ax_5v5_skaters_toi.axvspan(toi_5v5_ticklabels[1] / 2, toi_5v5_ticklabels[1] / 2, ymin=0, ymax=1, zorder=0, alpha=0.25, linestyle=':', color='black') ax_5v5_skaters_toi.axvspan(toi_5v5_ticklabels[1], toi_5v5_ticklabels[1], ymin=0, ymax=1, zorder=0, alpha=0.25, linestyle=':', color='black') ax_5v5_goalies_toi.axvspan(toi_5v5_ticklabels[1] / 2, toi_5v5_ticklabels[1] / 2, ymin=0, ymax=1, zorder=0, alpha=0.25, linestyle=':', color='black') ax_5v5_goalies_toi.axvspan(toi_5v5_ticklabels[1], toi_5v5_ticklabels[1], ymin=0, ymax=1, zorder=0, alpha=0.25, linestyle=':', color='black') ax_PP_skaters_toi.axvspan(toi_specialteams_ticklabels[1] / 2, toi_specialteams_ticklabels[1] / 2, ymin=0, ymax=1, zorder=0, alpha=0.25, linestyle=':', color='black') ax_PP_skaters_toi.axvspan(toi_specialteams_ticklabels[1], toi_specialteams_ticklabels[1], ymin=0, ymax=1, zorder=0, alpha=0.25, linestyle=':', color='black') ax_PP_goalies_toi.axvspan(toi_specialteams_ticklabels[1] / 2, toi_specialteams_ticklabels[1] / 2, ymin=0, ymax=1, zorder=0, alpha=0.25, linestyle=':', color='black') ax_PP_goalies_toi.axvspan(toi_specialteams_ticklabels[1], toi_specialteams_ticklabels[1], ymin=0, ymax=1, zorder=0, alpha=0.25, linestyle=':', color='black') ax_SH_skaters_toi.axvspan(toi_specialteams_ticklabels[1] / 2, toi_specialteams_ticklabels[1] / 2, ymin=0, ymax=1, zorder=0, alpha=0.25, linestyle=':', color='black') ax_SH_skaters_toi.axvspan(toi_specialteams_ticklabels[1], toi_specialteams_ticklabels[1], ymin=0, ymax=1, zorder=0, alpha=0.25, linestyle=':', color='black') ax_SH_goalies_toi.axvspan(toi_specialteams_ticklabels[1] / 2, toi_specialteams_ticklabels[1] / 2, ymin=0, ymax=1, zorder=0, alpha=0.25, linestyle=':', color='black') ax_SH_goalies_toi.axvspan(toi_specialteams_ticklabels[1], toi_specialteams_ticklabels[1], ymin=0, ymax=1, zorder=0, alpha=0.25, linestyle=':', color='black') # use the newly-minted x-ticklabels to ensure the x-axis labels will always display as integers ax_5v5_skaters_gamescore.set_xticks(GS_5v5_ticklabels, minor=False) ax_5v5_skaters_toi.set_xticks(toi_5v5_ticklabels, minor=False) ax_5v5_goalies_gamescore.set_xticks(GS_5v5_ticklabels, minor=False) ax_5v5_goalies_toi.set_xticks(toi_5v5_ticklabels, minor=False) ax_PP_skaters_gamescore.set_xticks(GS_PP_ticklabels, minor=False) ax_PP_skaters_toi.set_xticks(toi_specialteams_ticklabels, minor=False) ax_PP_goalies_gamescore.set_xticks(GS_PP_ticklabels, minor=False) ax_PP_goalies_toi.set_xticks(toi_specialteams_ticklabels, minor=False) ax_SH_skaters_gamescore.set_xticks(GS_SH_ticklabels, minor=False) ax_SH_skaters_toi.set_xticks(toi_specialteams_ticklabels, minor=False) ax_SH_goalies_gamescore.set_xticks(GS_SH_ticklabels, minor=False) ax_SH_goalies_toi.set_xticks(toi_specialteams_ticklabels, minor=False) # remove axes ticks for instances where there is no special teams play if team_PP_toi == 0: ax_PP_skaters_gamescore.set_xticks([], minor=False) ax_PP_skaters_gamescore.set_yticks([], minor=False) ax_PP_skaters_toi.set_xticks([], minor=False) ax_PP_skaters_toi.set_yticks([], minor=False) ax_PP_goalies_gamescore.set_xticks([], minor=False) ax_PP_goalies_gamescore.set_yticks([], minor=False) ax_PP_goalies_toi.set_xticks([], minor=False) ax_PP_goalies_toi.set_yticks([], minor=False) if team_SH_toi == 0: ax_SH_skaters_gamescore.set_xticks([], minor=False) ax_SH_skaters_gamescore.set_yticks([], minor=False) ax_SH_skaters_toi.set_xticks([], minor=False) ax_SH_skaters_toi.set_yticks([], minor=False) ax_SH_goalies_gamescore.set_xticks([], minor=False) ax_SH_goalies_gamescore.set_yticks([], minor=False) ax_SH_goalies_toi.set_xticks([], minor=False) ax_SH_goalies_toi.set_yticks([], minor=False) # remove the borders to each subplot ax_5v5_skaters_gamescore.spines["top"].set_visible(False) ax_5v5_skaters_gamescore.spines["bottom"].set_visible(False) ax_5v5_skaters_gamescore.spines["right"].set_visible(False) ax_5v5_skaters_gamescore.spines["left"].set_visible(False) ax_5v5_skaters_toi.spines["top"].set_visible(False) ax_5v5_skaters_toi.spines["bottom"].set_visible(False) ax_5v5_skaters_toi.spines["right"].set_visible(False) ax_5v5_skaters_toi.spines["left"].set_visible(False) ax_5v5_goalies_gamescore.spines["top"].set_visible(False) ax_5v5_goalies_gamescore.spines["bottom"].set_visible(False) ax_5v5_goalies_gamescore.spines["right"].set_visible(False) ax_5v5_goalies_gamescore.spines["left"].set_visible(False) ax_5v5_goalies_toi.spines["top"].set_visible(False) ax_5v5_goalies_toi.spines["bottom"].set_visible(False) ax_5v5_goalies_toi.spines["right"].set_visible(False) ax_5v5_goalies_toi.spines["left"].set_visible(False) ax_gap.spines["top"].set_visible(False) ax_gap.spines["bottom"].set_visible(False) ax_gap.spines["right"].set_visible(False) ax_gap.spines["left"].set_visible(False) ax_PP_skaters_gamescore.spines["top"].set_visible(False) ax_PP_skaters_gamescore.spines["bottom"].set_visible(False) ax_PP_skaters_gamescore.spines["right"].set_visible(False) ax_PP_skaters_gamescore.spines["left"].set_visible(False) ax_PP_skaters_toi.spines["top"].set_visible(False) ax_PP_skaters_toi.spines["bottom"].set_visible(False) ax_PP_skaters_toi.spines["right"].set_visible(False) ax_PP_skaters_toi.spines["left"].set_visible(False) ax_PP_goalies_gamescore.spines["top"].set_visible(False) ax_PP_goalies_gamescore.spines["bottom"].set_visible(False) ax_PP_goalies_gamescore.spines["right"].set_visible(False) ax_PP_goalies_gamescore.spines["left"].set_visible(False) ax_PP_goalies_toi.spines["top"].set_visible(False) ax_PP_goalies_toi.spines["bottom"].set_visible(False) ax_PP_goalies_toi.spines["right"].set_visible(False) ax_PP_goalies_toi.spines["left"].set_visible(False) ax_SH_skaters_gamescore.spines["top"].set_visible(False) ax_SH_skaters_gamescore.spines["bottom"].set_visible(False) ax_SH_skaters_gamescore.spines["right"].set_visible(False) ax_SH_skaters_gamescore.spines["left"].set_visible(False) ax_SH_skaters_toi.spines["top"].set_visible(False) ax_SH_skaters_toi.spines["bottom"].set_visible(False) ax_SH_skaters_toi.spines["right"].set_visible(False) ax_SH_skaters_toi.spines["left"].set_visible(False) ax_SH_goalies_gamescore.spines["top"].set_visible(False) ax_SH_goalies_gamescore.spines["bottom"].set_visible(False) ax_SH_goalies_gamescore.spines["right"].set_visible(False) ax_SH_goalies_gamescore.spines["left"].set_visible(False) ax_SH_goalies_toi.spines["top"].set_visible(False) ax_SH_goalies_toi.spines["bottom"].set_visible(False) ax_SH_goalies_toi.spines["right"].set_visible(False) ax_SH_goalies_toi.spines["left"].set_visible(False) # add text boxes with team names in white and with the team's color in the background fig.text(.425, 0.936, ' ' + away + ' ', color='white', fontsize='12', bbox=dict(facecolor=away_color, edgecolor='None')) fig.text(.525, 0.936, ' ' + home + ' ', color='white', fontsize='12', bbox=dict(facecolor=home_color, edgecolor='None')) fig.text(.490, 0.936, '@', color='black', fontsize='12', bbox=dict(facecolor='white', edgecolor='None')) ### ### SAVE TO FILE ### if team == away: plt.savefig(charts_players_composite_situation + 'gamescores_away_' + situation.lower() + '.png', bbox_inches='tight', pad_inches=0.2) elif team == home: plt.savefig(charts_players_composite_situation + 'gamescores_home_' + situation.lower() + '.png', bbox_inches='tight', pad_inches=0.2) # exercise a command-line option to show the current figure if images == 'show': plt.show() ### ### CLOSE ### plt.close(fig) # status update print('Plotting ' + team + ' ' + situation.lower() + ' gamescores for players.') # status update print('Finished plotting player gamescores by situation for ' + season_id + ' ' + game_id)
def parse_ids(season_id, game_id, images): # pull common variables from the parameters file charts_players_individual_period = parameters.charts_players_individual_period files_root = parameters.files_root # generate date and team information schedule_csv = files_root + season_id + "_schedule.csv" schedule_df = pd.read_csv(schedule_csv) schedule_date = schedule_df[(schedule_df['GAME_ID'] == int(game_id))] date = schedule_date['DATE'].item() home = schedule_date['HOME'].item() away = schedule_date['AWAY'].item() teams = [away, home] # create variables that point to the .csv processed stats files for the team and players team_file = files_root + 'stats_teams_period.csv' players_file = files_root + 'stats_players_individual_period.csv' # create a dataframe object that reads in info from the .csv files team_stats_df = pd.read_csv(team_file) players_df = pd.read_csv(players_file) # choose colors for each team; set them in a list; generate a custom colormap for each team away_color = dict_team_colors.team_color_1st[away] home_color = dict_team_colors.team_color_1st[home] # change one team's color from its primary option to, depending on the opponent, either a second, third or fourth option try: away_color = mod_switch_colors.switch_team_colors(away, home)[0] home_color = mod_switch_colors.switch_team_colors(away, home)[1] except: pass team_colors = [away_color, home_color] ### ### 5v5, PP, SH ### periods = [1, 2, 3, 4] # loop through each period for period in periods: if period == 1: period_name = '1st' if period == 2: period_name = '2nd' if period == 3: period_name = '3rd' if period == 4: period_name = 'OT' skaters_PP_df = players_df.copy() skaters_PP_df = skaters_PP_df[(skaters_PP_df['STATE'] == 'PP') & (skaters_PP_df['PERIOD'] == period_name) & (skaters_PP_df['POS'] != 'G')] max_PP_toi = skaters_PP_df['TOI'].max() skaters_SH_df = players_df.copy() skaters_SH_df = skaters_SH_df[(skaters_SH_df['STATE'] == 'SH') & (skaters_SH_df['PERIOD'] == period_name) & (skaters_PP_df['POS'] != 'G')] max_SH_toi = skaters_SH_df['TOI'].max() # loop through each team for team in teams: if team == away: team_color = team_colors[0] if team == home: team_color = team_colors[1] # create a dataframe from the team stats file for generating toi values for the different game states team_toi_df = team_stats_df.copy() team_all_toi = team_toi_df[(team_toi_df['TEAM'] == team) & (team_toi_df['STATE'] == 'ALL') & (team_toi_df['PERIOD'] == period_name)] try: team_all_toi = team_all_toi['TOI'].item() except: continue if period < 4 or season_id != 20192020 and period == 4 and int( game_id ) >= 30000 or season_id == 20192020 and period == 4 and int( game_id) >= 30021: team_5v5_toi = team_toi_df[(team_toi_df['TEAM'] == team) & (team_toi_df['STATE'] == '5v5') & (team_toi_df['PERIOD'] == period_name)] team_5v5_toi = team_5v5_toi['TOI'].item() if period == 4 and int(game_id) < 30000 and int( season_id) <= 20142015: team_4v4_toi = team_toi_df[(team_toi_df['TEAM'] == team) & (team_toi_df['STATE'] == '4v4') & (team_toi_df['PERIOD'] == period_name)] team_4v4_toi = team_4v4_toi['TOI'].item() if period == 4 and int(game_id) < 30000 and int( season_id ) >= 20152016 or season_id == 20192020 and period == 4 and int( game_id) > 30000 and int(game_id) <= 30020: team_3v3_toi = team_toi_df[(team_toi_df['TEAM'] == team) & (team_toi_df['STATE'] == '3v3') & (team_toi_df['PERIOD'] == period_name)] team_3v3_toi = team_3v3_toi['TOI'].item() team_PP_toi = team_toi_df[(team_toi_df['TEAM'] == team) & (team_toi_df['STATE'] == 'PP') & (team_toi_df['PERIOD'] == period_name)] team_PP_toi = team_PP_toi['TOI'].item() team_SH_toi = team_toi_df[(team_toi_df['TEAM'] == team) & (team_toi_df['STATE'] == 'SH') & (team_toi_df['PERIOD'] == period_name)] team_SH_toi = team_SH_toi['TOI'].item() # create a dataframe; filter for team; sort by team, game state and position; rank by time on ice and then invert the rankings team_df = players_df.copy() team_df = team_df[(team_df['TEAM'] == team) & (team_df['POS'] != 'G') & (team_df['PERIOD'] == period_name)] # create a filtered dataframe for each game state; sort by team, game state and position; rank by time on ice and then invert the rankings if period < 4 or season_id != 20192020 and period == 4 and int( game_id ) >= 30000 or season_id == 20192020 and period == 4 and int( game_id) >= 30021: team_5v5_df = team_df.copy() team_5v5_df = team_5v5_df[(team_5v5_df['STATE'] == '5v5')] team_5v5_df = team_5v5_df.sort_values(by=['TOI'], ascending=True) team_5v5_df['RANK'] = team_5v5_df['TOI'].rank(method='first') team_5v5_df['RANK'] -= 1 if period == 4 and int(game_id) < 30000 and int( season_id) <= 20142015: team_4v4_df = team_df.copy() team_4v4_df = team_4v4_df[(team_4v4_df['STATE'] == '4v4')] team_4v4_df = team_4v4_df.sort_values(by=['TOI'], ascending=True) team_4v4_df['RANK'] = team_4v4_df['TOI'].rank(method='first') team_4v4_df['RANK'] -= 1 if period == 4 and int(game_id) < 30000 and int( season_id ) >= 20152016 or season_id == 20192020 and period == 4 and int( game_id) > 30000 and int(game_id) <= 30020: team_3v3_df = team_df.copy() team_3v3_df = team_3v3_df[(team_3v3_df['STATE'] == '3v3')] team_3v3_df = team_3v3_df.sort_values(by=['TOI'], ascending=True) team_3v3_df['RANK'] = team_3v3_df['TOI'].rank(method='first') team_3v3_df['RANK'] -= 1 team_PP_df = team_df.copy() team_PP_df = team_PP_df[(team_PP_df['STATE'] == 'PP') & (team_PP_df['TOI'] > 0)] team_PP_df = team_PP_df.sort_values(by=['TOI'], ascending=True) team_PP_df = team_PP_df.iloc[-10:] team_PP_df['RANK'] = team_PP_df['TOI'].rank(method='first') team_PP_df['RANK'] -= 1 team_SH_df = team_df.copy() team_SH_df = team_SH_df[(team_SH_df['STATE'] == 'SH') & (team_SH_df['TOI'] > 0)] team_SH_df = team_SH_df.sort_values(by=['TOI'], ascending=True) team_SH_df = team_SH_df.iloc[-10:] team_SH_df['RANK'] = team_SH_df['TOI'].rank(method='first') team_SH_df['RANK'] -= 1 # for each game state, create a dataframe with just the time on ice column; set a max value; scale each player's time on ice relative to the max if period < 4 or season_id != 20192020 and period == 4 and int( game_id ) >= 30000 or season_id == 20192020 and period == 4 and int( game_id) >= 30021: toi_5v5 = team_5v5_df['TOI'] max_toi_5v5 = toi_5v5.max() if period == 4 and int(game_id) < 30000 and int( season_id) <= 20142015: toi_4v4 = team_4v4_df['TOI'] max_toi_4v4 = toi_4v4.max() if period == 4 and int(game_id) < 30000 and int( season_id ) >= 20152016 or season_id == 20192020 and period == 4 and int( game_id) > 30000 and int(game_id) <= 30020: toi_3v3 = team_3v3_df['TOI'] max_toi_3v3 = toi_3v3.max() toi_PP = team_PP_df['TOI'] max_toi_PP = toi_PP.max() toi_SH = team_SH_df['TOI'] max_toi_SH = toi_SH.max() # create a figure with six subplots arrangled complexly using a grid structure fig = plt.figure(figsize=(8, 8)) grid = plt.GridSpec(5, 8, hspace=0.75, wspace=0.75) if period < 4 or season_id != 20192020 and period == 4 and int( game_id ) >= 30000 or season_id == 20192020 and period == 4 and int( game_id) >= 30021: ax_5v5_xG = fig.add_subplot(grid[0:-2, :-1]) ax_5v5_toi = fig.add_subplot(grid[0:-2, 7]) if period == 4 and int(game_id) < 30000 and int( season_id) <= 20142015: ax_4v4_xG = fig.add_subplot(grid[0:-2, :-1]) ax_4v4_toi = fig.add_subplot(grid[0:-2, 7]) if period == 4 and int(game_id) < 30000 and int( season_id ) >= 20152016 or season_id == 20192020 and period == 4 and int( game_id) > 30000 and int(game_id) <= 30020: ax_3v3_xG = fig.add_subplot(grid[0:-2, :-1]) ax_3v3_toi = fig.add_subplot(grid[0:-2, 7]) ax_PP_xG = fig.add_subplot(grid[3:, :2]) ax_PP_toi = fig.add_subplot(grid[3:, 2]) ax_SH_xG = fig.add_subplot(grid[3:, 5:-1]) ax_SH_toi = fig.add_subplot(grid[3:, 7]) # set the plot title fig.suptitle(date + ' Skaters Individual Expected Goals (' + period_name + ' Period)\n\n') # set the axes titles if period < 4 or season_id != 20192020 and period == 4 and int( game_id ) >= 30000 or season_id == 20192020 and period == 4 and int( game_id) >= 30021: ax_5v5_xG.set_title('5v5 xG', fontsize=10) ax_5v5_toi.set_title('5v5 TOI', fontsize=10) if period == 4 and int(game_id) < 30000 and int( season_id) <= 20142015: ax_4v4_xG.set_title('4v4 xG', fontsize=10) ax_4v4_toi.set_title('4v4 TOI', fontsize=10) if period == 4 and int(game_id) < 30000 and int( season_id ) >= 20152016 or season_id == 20192020 and period == 4 and int( game_id) > 30000 and int(game_id) <= 30020: ax_3v3_xG.set_title('3v3 xG', fontsize=10) ax_3v3_toi.set_title('3v3 TOI', fontsize=10) ax_PP_xG.set_title('PP xG', fontsize=10) ax_PP_toi.set_title('PP TOI', fontsize=10) ax_SH_xG.set_title('SH xG', fontsize=10) ax_SH_toi.set_title('SH TOI', fontsize=10) # for each state, plot the bars for total shots and markers for saved, missed and blocked shots markers if period < 4 or season_id != 20192020 and period == 4 and int( game_id ) >= 30000 or season_id == 20192020 and period == 4 and int( game_id) >= 30021: try: xG_5v5_plot = team_5v5_df.plot.barh(x='PLAYER', y='xG', color=team_color, edgecolor=None, width=0.75, legend=None, label='', ax=ax_5v5_xG) except: pass if period == 4 and int(game_id) < 30000 and int( season_id) <= 20142015: try: xG_4v4_plot = team_4v4_df.plot.barh(x='PLAYER', y='xG', color=team_color, edgecolor=None, width=0.75, legend=None, label='', ax=ax_4v4_xG) except: pass if period == 4 and int(game_id) < 30000 and int( season_id ) >= 20152016 or season_id == 20192020 and period == 4 and int( game_id) > 30000 and int(game_id) <= 30020: try: xG_3v3_plot = team_3v3_df.plot.barh(x='PLAYER', y='xG', color=team_color, edgecolor=None, width=0.75, legend=None, label='', ax=ax_3v3_xG) except: pass if team_PP_toi != 0: try: xG_PP_plot = team_PP_df.plot.barh(x='PLAYER', y='xG', color=team_color, edgecolor=None, width=0.75, legend=None, label='', ax=ax_PP_xG) except: pass if team_SH_toi != 0: try: xG_SH_plot = team_SH_df.plot.barh(x='PLAYER', y='xG', color=team_color, edgecolor=None, width=0.75, legend=None, label='', ax=ax_SH_xG) except: pass # for each state, plot the bars for time on ice if period < 4 or season_id != 20192020 and period == 4 and int( game_id ) >= 30000 or season_id == 20192020 and period == 4 and int( game_id) >= 30021: try: toi_5v5_plot = team_5v5_df.plot.barh(x='PLAYER', y='TOI', color='white', edgecolor=team_color, width=0.75, legend=None, label='', ax=ax_5v5_toi) except: pass if period == 4 and int(game_id) < 30000 and int( season_id) <= 20142015: try: toi_4v4_plot = team_4v4_df.plot.barh(x='PLAYER', y='TOI', color='white', edgecolor=team_color, width=0.75, legend=None, label='', ax=ax_4v4_toi) except: pass if period == 4 and int(game_id) < 30000 and int( season_id ) >= 20152016 or season_id == 20192020 and period == 4 and int( game_id) > 30000 and int(game_id) <= 30020: try: toi_3v3_plot = team_3v3_df.plot.barh(x='PLAYER', y='TOI', color='white', edgecolor=team_color, width=0.75, legend=None, label='', ax=ax_3v3_toi) except: pass if team_PP_toi != 0: try: toi_PP_plot = team_PP_df.plot.barh(x='PLAYER', y='TOI', color='white', edgecolor=team_color, width=0.75, legend=None, label='', ax=ax_PP_toi) except: pass if team_SH_toi != 0: try: toi_SH_plot = team_SH_df.plot.barh(x='PLAYER', y='TOI', color='white', edgecolor=team_color, width=0.75, legend=None, label='', ax=ax_SH_toi) except: pass # set / remove the y-labels for the subplots if period < 4 or season_id != 20192020 and period == 4 and int( game_id ) >= 30000 or season_id == 20192020 and period == 4 and int( game_id) >= 30021: ax_5v5_xG.set_xlabel('') ax_5v5_xG.set_ylabel('', fontsize=10) ax_5v5_toi.set_xlabel('') ax_5v5_toi.set_ylabel('') if period == 4 and int(game_id) < 30000 and int( season_id) <= 20142015: ax_4v4_xG.set_xlabel('') ax_4v4_xG.set_ylabel('', fontsize=10) ax_4v4_toi.set_xlabel('') ax_4v4_toi.set_ylabel('') if period == 4 and int(game_id) < 30000 and int( season_id ) >= 20152016 or season_id == 20192020 and period == 4 and int( game_id) > 30000 and int(game_id) <= 30020: ax_3v3_xG.set_xlabel('') ax_3v3_xG.set_ylabel('', fontsize=10) ax_3v3_toi.set_xlabel('') ax_3v3_toi.set_ylabel('') ax_PP_xG.set_xlabel('') ax_PP_xG.set_ylabel('', fontsize=10) ax_PP_toi.set_xlabel('') ax_PP_toi.set_ylabel('') ax_SH_xG.set_xlabel('') ax_SH_xG.set_ylabel('', fontsize=10) ax_SH_toi.set_xlabel('') ax_SH_toi.set_ylabel('') # change the tick parameters for each axes if period < 4 or season_id != 20192020 and period == 4 and int( game_id ) >= 30000 or season_id == 20192020 and period == 4 and int( game_id) >= 30021: ax_5v5_xG.tick_params( axis='both', # changes apply to the x-axis which='both', # both major and minor ticks are affected bottom=False, # ticks along the bottom edge are off top=False, # ticks along the top edge are off left=False, # ticks along the left edge are off labelbottom=True) # labels along the bottom edge are on ax_5v5_toi.tick_params( axis='both', # changes apply to the x-axis which='both', # both major and minor ticks are affected bottom=False, # ticks along the bottom edge are off top=False, # ticks along the top edge are off left=False, # ticks along the left edge are off labelleft=False, # labels along the left edge are off labelbottom=True) # labels along the bottom edge are on if period == 4 and int(game_id) < 30000 and int( season_id) <= 20142015: ax_4v4_xG.tick_params( axis='both', # changes apply to the x-axis which='both', # both major and minor ticks are affected bottom=False, # ticks along the bottom edge are off top=False, # ticks along the top edge are off left=False, # ticks along the left edge are off labelbottom=True) # labels along the bottom edge are on ax_4v4_toi.tick_params( axis='both', # changes apply to the x-axis which='both', # both major and minor ticks are affected bottom=False, # ticks along the bottom edge are off top=False, # ticks along the top edge are off left=False, # ticks along the left edge are off labelleft=False, # labels along the left edge are off labelbottom=True) # labels along the bottom edge are on if period == 4 and int(game_id) < 30000 and int( season_id ) >= 20152016 or season_id == 20192020 and period == 4 and int( game_id) > 30000 and int(game_id) <= 30020: ax_3v3_xG.tick_params( axis='both', # changes apply to the x-axis which='both', # both major and minor ticks are affected bottom=False, # ticks along the bottom edge are off top=False, # ticks along the top edge are off left=False, # ticks along the left edge are off labelbottom=True) # labels along the bottom edge are on ax_3v3_toi.tick_params( axis='both', # changes apply to the x-axis which='both', # both major and minor ticks are affected bottom=False, # ticks along the bottom edge are off top=False, # ticks along the top edge are off left=False, # ticks along the left edge are off labelleft=False, # labels along the left edge are off labelbottom=True) # labels along the bottom edge are on ax_PP_xG.tick_params( axis='both', # changes apply to the x-axis which='both', # both major and minor ticks are affected bottom=False, # ticks along the bottom edge are off top=False, # ticks along the top edge are off left=False, # ticks along the left edge are off labelbottom=True) # labels along the bottom edge are on ax_PP_toi.tick_params( axis='both', # changes apply to the x-axis which='both', # both major and minor ticks are affected bottom=False, # ticks along the bottom edge are off top=False, # ticks along the top edge are off left=False, # ticks along the left edge are off labelleft= False, # labels along the left edge are off labelbottom=True) # labels along the bottom edge are on ax_SH_xG.tick_params( axis='both', # changes apply to the x-axis which='both', # both major and minor ticks are affected bottom=False, # ticks along the bottom edge are off top=False, # ticks along the top edge are off left=False, # ticks along the left edge are off labelbottom=True) # labels along the bottom edge are on ax_SH_toi.tick_params( axis='both', # changes apply to the x-axis which='both', # both major and minor ticks are affected bottom=False, # ticks along the bottom edge are off top=False, # ticks along the top edge are off left=False, # ticks along the left edge are off labelleft=False, # labels along the left edge are off labelbottom=True) # labels along the bottom edge are on # change the y-axis label colors if period < 4 or season_id != 20192020 and period == 4 and int( game_id ) >= 30000 or season_id == 20192020 and period == 4 and int( game_id) >= 30021: ax_5v5_xG.tick_params(axis='y', which='both', labelcolor=team_color) if period == 4 and int(game_id) < 30000 and int( season_id) <= 20142015: ax_4v4_xG.tick_params(axis='y', which='both', labelcolor=team_color) if period == 4 and int(game_id) < 30000 and int( season_id ) >= 20152016 or season_id == 20192020 and period == 4 and int( game_id) > 30000 and int(game_id) <= 30020: ax_3v3_xG.tick_params(axis='y', which='both', labelcolor=team_color) ax_PP_xG.tick_params(axis='y', which='both', labelcolor=team_color) ax_SH_xG.tick_params(axis='y', which='both', labelcolor=team_color) # create a list of x-axis tick values contingent on the max values for shots if period < 4 or season_id != 20192020 and period == 4 and int( game_id ) >= 30000 or season_id == 20192020 and period == 4 and int( game_id) >= 30021: xG_5v5_max = team_5v5_df['xG'] xG_5v5_tickmax = xG_5v5_max.max() xG_5v5_ticklabels = [] if xG_5v5_tickmax >= 0 and xG_5v5_tickmax <= 0.5: xG_5v5_ticklabels = [0.0, 0.1, 0.2, 0.3, 0.4, 0.5] if xG_5v5_tickmax > 5 and xG_5v5_tickmax <= 1.0: xG_5v5_ticklabels = [0.0, 0.2, 0.4, 0.6, 0.8, 1.0] if xG_5v5_tickmax > 1 and xG_5v5_tickmax <= 1.5: xG_5v5_ticklabels = [0.0, 0.3, 0.6, 0.9, 1.2, 1.5] if xG_5v5_tickmax > 1.5 and xG_5v5_tickmax <= 2: xG_5v5_ticklabels = [0.0, 0.4, 0.8, 1.2, 1.6, 2.0] if xG_5v5_tickmax > 2 and xG_5v5_tickmax <= 2.5: xG_5v5_ticklabels = [0.0, 0.5, 1.0, 1.5, 2.0, 2.5] toi_5v5_ticklabels = [0, 20] if period == 4 and int(game_id) < 30000 and int( season_id) <= 20142015: xG_4v4_max = team_4v4_df['xG'] xG_4v4_tickmax = xG_4v4_max.max() xG_4v4_ticklabels = [] if xG_4v4_tickmax >= 0 and xG_4v4_tickmax <= 0.5: xG_4v4_ticklabels = [0.0, 0.1, 0.2, 0.3, 0.4, 0.5] if xG_4v4_tickmax > 5 and xG_4v4_tickmax <= 1.0: xG_3v3_ticklabels = [0.0, 0.2, 0.4, 0.6, 0.8, 1.0] if xG_4v4_tickmax > 1 and xG_4v4_tickmax <= 1.5: xG_4v4_ticklabels = [0.0, 0.3, 0.6, 0.9, 1.2, 1.5] if xG_4v4_tickmax > 1.5 and xG_4v4_tickmax <= 2: xG_4v4_ticklabels = [0.0, 0.4, 0.8, 1.2, 1.6, 2.0] if xG_4v4_tickmax > 2 and xG_4v4_tickmax <= 2.5: xG_4v4_ticklabels = [0.0, 0.5, 1.0, 1.5, 2.0, 2.5] toi_4v4_ticklabels = [0, 5] if period == 4 and int(game_id) < 30000 and int( season_id ) >= 20152016 or season_id == 20192020 and period == 4 and int( game_id) > 30000 and int(game_id) <= 30020: xG_3v3_max = team_3v3_df['xG'] xG_3v3_tickmax = xG_3v3_max.max() xG_3v3_ticklabels = [] if xG_3v3_tickmax >= 0 and xG_3v3_tickmax <= 0.5: xG_3v3_ticklabels = [0.0, 0.1, 0.2, 0.3, 0.4, 0.5] if xG_3v3_tickmax > 5 and xG_3v3_tickmax <= 1.0: xG_3v3_ticklabels = [0.0, 0.2, 0.4, 0.6, 0.8, 1.0] if xG_3v3_tickmax > 1 and xG_3v3_tickmax <= 1.5: xG_3v3_ticklabels = [0.0, 0.3, 0.6, 0.9, 1.2, 1.5] if xG_3v3_tickmax > 1.5 and xG_3v3_tickmax <= 2: xG_3v3_ticklabels = [0.0, 0.4, 0.8, 1.2, 1.6, 2.0] if xG_3v3_tickmax > 2 and xG_3v3_tickmax <= 2.5: xG_3v3_ticklabels = [0.0, 0.5, 1.0, 1.5, 2.0, 2.5] toi_3v3_ticklabels = [0, 5] xG_PP_max = team_PP_df['xG'] xG_PP_tickmax = xG_PP_max.max() xG_PP_ticklabels = [] if xG_PP_tickmax <= 1: xG_PP_ticklabels = [0.0, 0.5, 1.0] if xG_PP_tickmax > 1 and xG_PP_tickmax <= 2: xG_PP_ticklabels = [0.0, 1.0, 2.0] if xG_PP_tickmax > 2 and xG_PP_tickmax <= 3: xG_PP_ticklabels = [0.0, 1.5, 3.0] if xG_PP_tickmax > 3 and xG_PP_tickmax <= 4: xG_PP_ticklabels = [0.0, 3.0, 4.0] xG_SH_max = team_SH_df['xG'] xG_SH_tickmax = xG_SH_max.max() xG_SH_ticklabels = [] if xG_SH_tickmax <= 1: xG_SH_ticklabels = [0.0, 0.5, 1.0] if xG_SH_tickmax > 1 and xG_SH_tickmax <= 2: xG_SH_ticklabels = [0.0, 1.0, 2.0] if xG_SH_tickmax > 2 and xG_SH_tickmax <= 3: xG_SH_ticklabels = [0.0, 1.5, 3.0] if xG_SH_tickmax > 3 and xG_SH_tickmax <= 4: xG_SH_ticklabels = [0.0, 2.0, 4.0] toi_PP_tickmax = max_PP_toi toi_SH_tickmax = max_SH_toi toi_specialteams_tickmax = float() if toi_PP_tickmax >= toi_SH_tickmax: toi_specialteams_tickmax = toi_PP_tickmax if toi_PP_tickmax < toi_SH_tickmax: toi_specialteams_tickmax = toi_SH_tickmax toi_specialteams_ticklabels = [] if toi_specialteams_tickmax <= 2: toi_specialteams_ticklabels = [0, 2] if toi_specialteams_tickmax > 2 and toi_specialteams_tickmax <= 4: toi_specialteams_ticklabels = [0, 4] if toi_specialteams_tickmax > 4 and toi_specialteams_tickmax <= 6: toi_specialteams_ticklabels = [0, 6] if toi_specialteams_tickmax > 6 and toi_specialteams_tickmax <= 8: toi_specialteams_ticklabels = [0, 8] if toi_specialteams_tickmax > 8 and toi_specialteams_tickmax <= 10: toi_specialteams_ticklabels = [0, 10] if toi_specialteams_tickmax > 10 and toi_specialteams_tickmax <= 12: toi_specialteams_ticklabels = [0, 12] if toi_specialteams_tickmax > 12 and toi_specialteams_tickmax <= 14: toi_specialteams_ticklabels = [0, 14] if toi_specialteams_tickmax > 14 and toi_specialteams_tickmax <= 16: toi_specialteams_ticklabels = [0, 16] if toi_specialteams_tickmax > 16 and toi_specialteams_tickmax <= 18: toi_specialteams_ticklabels = [0, 18] if toi_specialteams_tickmax > 18 and toi_specialteams_tickmax <= 20: toi_specialteams_ticklabels = [0, 20] # set vertical indicator for midpoint of time on ice max if period < 4 or season_id != 20192020 and period == 4 and int( game_id ) >= 30000 or season_id == 20192020 and period == 4 and int( game_id) >= 30021: ax_5v5_toi.axvspan(toi_5v5_ticklabels[1] / 2, toi_5v5_ticklabels[1] / 2, ymin=0, ymax=1, zorder=0, alpha=0.25, linestyle=':', color='black') ax_5v5_toi.axvspan(toi_5v5_ticklabels[1], toi_5v5_ticklabels[1], ymin=0, ymax=1, zorder=0, alpha=0.25, linestyle=':', color='black') if period == 4 and int(game_id) < 30000 and int( season_id) <= 20142015: ax_4v4_toi.axvspan(toi_4v4_ticklabels[1] / 2, toi_4v4_ticklabels[1] / 2, ymin=0, ymax=1, zorder=0, alpha=0.25, linestyle=':', color='black') ax_4v4_toi.axvspan(toi_4v4_ticklabels[1], toi_4v4_ticklabels[1], ymin=0, ymax=1, zorder=0, alpha=0.25, linestyle=':', color='black') if period == 4 and int(game_id) < 30000 and int( season_id ) >= 20152016 or season_id == 20192020 and period == 4 and int( game_id) > 30000 and int(game_id) <= 30020: ax_3v3_toi.axvspan(toi_3v3_ticklabels[1] / 2, toi_3v3_ticklabels[1] / 2, ymin=0, ymax=1, zorder=0, alpha=0.25, linestyle=':', color='black') ax_3v3_toi.axvspan(toi_3v3_ticklabels[1], toi_3v3_ticklabels[1], ymin=0, ymax=1, zorder=0, alpha=0.25, linestyle=':', color='black') ax_PP_toi.axvspan(toi_specialteams_ticklabels[1] / 2, toi_specialteams_ticklabels[1] / 2, ymin=0, ymax=1, zorder=0, alpha=0.25, linestyle=':', color='black') ax_PP_toi.axvspan(toi_specialteams_ticklabels[1], toi_specialteams_ticklabels[1], ymin=0, ymax=1, zorder=0, alpha=0.25, linestyle=':', color='black') ax_SH_toi.axvspan(toi_specialteams_ticklabels[1] / 2, toi_specialteams_ticklabels[1] / 2, ymin=0, ymax=1, zorder=0, alpha=0.25, linestyle=':', color='black') ax_SH_toi.axvspan(toi_specialteams_ticklabels[1], toi_specialteams_ticklabels[1], ymin=0, ymax=1, zorder=0, alpha=0.25, linestyle=':', color='black') # use the newly-minted x-ticklabels to ensure the x-axis labels will always display as integers if period < 4 or season_id != 20192020 and period == 4 and int( game_id ) >= 30000 or season_id == 20192020 and period == 4 and int( game_id) >= 30021: ax_5v5_xG.set_xticks(xG_5v5_ticklabels, minor=False) ax_5v5_toi.set_xticks(toi_5v5_ticklabels, minor=False) if period == 4 and int(game_id) < 30000 and int( season_id) <= 20142015: ax_4v4_xG.set_xticks(xG_4v4_ticklabels, minor=False) ax_4v4_toi.set_xticks(toi_4v4_ticklabels, minor=False) if period == 4 and int(game_id) < 30000 and int( season_id ) >= 20152016 or season_id == 20192020 and period == 4 and int( game_id) > 30000 and int(game_id) <= 30020: ax_3v3_xG.set_xticks(xG_3v3_ticklabels, minor=False) ax_3v3_toi.set_xticks(toi_3v3_ticklabels, minor=False) ax_PP_xG.set_xticks(xG_PP_ticklabels, minor=False) ax_PP_toi.set_xticks(toi_specialteams_ticklabels, minor=False) ax_SH_xG.set_xticks(xG_SH_ticklabels, minor=False) ax_SH_toi.set_xticks(toi_specialteams_ticklabels, minor=False) # remove axes ticks for instances where there is no special teams play if team_PP_toi == 0: ax_PP_xG.set_xticks([], minor=False) ax_PP_xG.set_yticks([], minor=False) ax_PP_toi.set_xticks([], minor=False) ax_PP_toi.set_yticks([], minor=False) if team_SH_toi == 0: ax_SH_xG.set_xticks([], minor=False) ax_SH_xG.set_yticks([], minor=False) ax_SH_toi.set_xticks([], minor=False) ax_SH_toi.set_yticks([], minor=False) # remove the borders to each subplot if period < 4 or season_id != 20192020 and period == 4 and int( game_id ) >= 30000 or season_id == 20192020 and period == 4 and int( game_id) >= 30021: ax_5v5_xG.spines["top"].set_visible(False) ax_5v5_xG.spines["bottom"].set_visible(False) ax_5v5_xG.spines["right"].set_visible(False) ax_5v5_xG.spines["left"].set_visible(False) ax_5v5_toi.spines["top"].set_visible(False) ax_5v5_toi.spines["bottom"].set_visible(False) ax_5v5_toi.spines["right"].set_visible(False) ax_5v5_toi.spines["left"].set_visible(False) if period == 4 and int(game_id) < 30000 and int( season_id) <= 20142015: ax_4v4_xG.spines["top"].set_visible(False) ax_4v4_xG.spines["bottom"].set_visible(False) ax_4v4_xG.spines["right"].set_visible(False) ax_4v4_xG.spines["left"].set_visible(False) ax_4v4_toi.spines["top"].set_visible(False) ax_4v4_toi.spines["bottom"].set_visible(False) ax_4v4_toi.spines["right"].set_visible(False) ax_4v4_toi.spines["left"].set_visible(False) if period == 4 and int(game_id) < 30000 and int( season_id ) >= 20152016 or season_id == 20192020 and period == 4 and int( game_id) > 30000 and int(game_id) <= 30020: ax_3v3_xG.spines["top"].set_visible(False) ax_3v3_xG.spines["bottom"].set_visible(False) ax_3v3_xG.spines["right"].set_visible(False) ax_3v3_xG.spines["left"].set_visible(False) ax_3v3_toi.spines["top"].set_visible(False) ax_3v3_toi.spines["bottom"].set_visible(False) ax_3v3_toi.spines["right"].set_visible(False) ax_3v3_toi.spines["left"].set_visible(False) ax_PP_xG.spines["top"].set_visible(False) ax_PP_xG.spines["bottom"].set_visible(False) ax_PP_xG.spines["right"].set_visible(False) ax_PP_xG.spines["left"].set_visible(False) ax_PP_toi.spines["top"].set_visible(False) ax_PP_toi.spines["bottom"].set_visible(False) ax_PP_toi.spines["right"].set_visible(False) ax_PP_toi.spines["left"].set_visible(False) ax_SH_xG.spines["top"].set_visible(False) ax_SH_xG.spines["bottom"].set_visible(False) ax_SH_xG.spines["right"].set_visible(False) ax_SH_xG.spines["left"].set_visible(False) ax_SH_toi.spines["top"].set_visible(False) ax_SH_toi.spines["bottom"].set_visible(False) ax_SH_toi.spines["right"].set_visible(False) ax_SH_toi.spines["left"].set_visible(False) # add text boxes with team names in white and with the team's color in the background fig.text(.425, 0.936, ' ' + away + ' ', color='white', fontsize='12', bbox=dict(facecolor=away_color, edgecolor='None')) fig.text(.525, 0.936, ' ' + home + ' ', fontsize='12', color='white', bbox=dict(facecolor=home_color, edgecolor='None')) fig.text(.490, 0.936, '@', color='black', fontsize='12', bbox=dict(facecolor='white', edgecolor='None')) ### ### SAVE TO FILE ### if team == away: plt.savefig(charts_players_individual_period + 'skaters_individual_xG_away_' + period_name + '.png', bbox_inches='tight', pad_inches=0.2) elif team == home: plt.savefig(charts_players_individual_period + 'skaters_individual_xG_home_' + period_name + '.png', bbox_inches='tight', pad_inches=0.2) # exercise a command-line option to show the current figure if images == 'show': plt.show() ### ### CLOSE ### plt.close(fig) # status update print('Plotting ' + team + ' skaters individual xG for the ' + period_name + ' period.') # status update print('Finished plotting the individual xG for skaters by period.')