Open In Colab

NHL Data Visualization#

Project: Recreating the Masters#

Dr. N. C. Jacob#

24 April 2022#

Hockey is my favorite spectator sport. I watch hockey most evenings before bed. With the Stanley Cup championship approaching, I wanted to see how my club was fairing (and brag a bit). I found a visualization from the previous season that I felt was worthy of recerating and attempt to do so in this document.

Master?

NHL uses a point system to determine the winners of the regular season. The victor of a match is awarded two points. If the regular time ends in a tie or draw, both teams are awarded a point and then vie in overtime for a third point. This causes some games to be worth a total of three points while other are only worth two. A team will need to average more than one point in each game to have a winning season. Teams represented above the \(x\)-axis here have scored more than one point each game while those falling below are not having a very good season. We can also see in each division which team will make the cut for the playoffs.

Graphical Excellence#

The above grahpic displays many aspects of grahpical excellence:

  • We see that there are five graphics all of which have had the data adjusted for the group it represents. This is much like using the time value of money, where you count for inflation. This is excellent because it displays in time the actual expected points which may vary as the season progresses.

  • The time series line has been drawn in a color representing each team.

  • The grahpic does not require a legend since each team has been represented by their logo.

  • Each division is highlighted as well as the entire league, showing us which teams are likely to make the playoffs in each.

Packages For Project#


import requests
import pandas as pa
from bs4 import BeautifulSoup
import numpy as np
import matplotlib.image as mpimg
import matplotlib.pyplot as plt

Data Gathering#

To be able to do this I am going to need sports data. I think I can find that at pro-hockey reference and images for the teams

The data for this was not readily available so I am going to have to do some work. I can gather each games data here and then I’ll go back and compute the point totals for each team after each game they play. Let’s see if we can get that to work!

r = requests.get('https://www.hockey-reference.com/leagues/NHL_2022_games.html')
html_contents = r.text
html_soup = BeautifulSoup(html_contents,"lxml")


len(html_soup.find_all('table'))
2
tables = html_soup.find_all('table')

df = pa.read_html(str(tables))[0]
df.head(10)
Date Visitor G Home G.1 Unnamed: 5 Att. LOG Notes
0 2021-10-12 Pittsburgh Penguins 6 Tampa Bay Lightning 2 NaN 19092.0 2:33 NaN
1 2021-10-12 Seattle Kraken 3 Vegas Golden Knights 4 NaN 18431.0 2:25 NaN
2 2021-10-13 Winnipeg Jets 1 Anaheim Ducks 4 NaN 16260.0 2:29 NaN
3 2021-10-13 Chicago Blackhawks 2 Colorado Avalanche 4 NaN 18037.0 2:32 NaN
4 2021-10-13 Vancouver Canucks 2 Edmonton Oilers 3 SO 16034.0 2:42 NaN
5 2021-10-13 Montreal Canadiens 1 Toronto Maple Leafs 2 NaN 18493.0 2:33 NaN
6 2021-10-13 New York Rangers 1 Washington Capitals 5 NaN 18573.0 2:29 NaN
7 2021-10-14 Montreal Canadiens 1 Buffalo Sabres 5 NaN 8467.0 2:26 NaN
8 2021-10-14 New York Islanders 3 Carolina Hurricanes 6 NaN 18680.0 2:46 NaN
9 2021-10-14 Arizona Coyotes 2 Columbus Blue Jackets 8 NaN 17813.0 2:30 NaN

Well that part worked as well as excepcted! Let’s get all the teams and start building our season by games. There are 82 games in the season (most have only played around 70 right now when I gathered this!)

teams = [x.replace(" ","").replace(".","").lower() for x in df.Home.unique()]

games = ['game{}'.format(x) for x in range(1,83)]
pointsbygame = pa.DataFrame(np.nan, index = games,columns = teams)
pointsbygame.head()
tampabaylightning vegasgoldenknights anaheimducks coloradoavalanche edmontonoilers torontomapleleafs washingtoncapitals buffalosabres carolinahurricanes columbusbluejackets ... arizonacoyotes calgaryflames chicagoblackhawks minnesotawild winnipegjets dallasstars seattlekraken stlouisblues vancouvercanucks newyorkislanders
game1 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
game2 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
game3 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
game4 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
game5 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN

5 rows × 32 columns

def findwinner(game):
  if game['G']>game['G.1']:
    print('Visitor {}'.format(game['Visitor']) + ' Won')
  else:
    print('Home {}'.format(game['Home']) + ' Won')
findwinner(df.loc[0])
Visitor Pittsburgh Penguins Won

I need to do a little better than that! I’ll need to add 2 points for that game for the winner and 0 points for the loser (1 if it went to OT).

for team in teams:
  globals()[team] = []
def cleanteamname(teamname): #returns the list about the team.
  return globals()[teamname.replace(" ","").replace(".","").lower()]   
def winner(game):
  if (game["G"] > game["G.1"]) & (not(pa.isnull(game['G']))):
    cleanteamname(game.Visitor).append(2)
  elif not(pa.isnull(game['G'])):
    cleanteamname(game.Home).append(2)
  else:
    cleanteamname(game.Home).append(np.nan)
    cleanteamname(game.Visitor).append(np.nan)

def loser(game):
  if pa.isnull(game['Unnamed: 5']): #No overtime
    val = 0
  else:
    val = 1 #gives a point for OT/SO loss
  if (game['G'] > game['G.1']) & (not(pa.isnull(game['G']))): #home team lost
    cleanteamname(game.Home).append(val)
  elif not(pa.isnull(game['G'])):
    cleanteamname(game.Visitor).append(val)
df.loc[1300]
Date                  2022-04-29
Visitor       Colorado Avalanche
G                              1
Home              Minnesota Wild
G.1                            4
Unnamed: 5                   NaN
Att.                     19261.0
LOG                         2:29
Notes                        NaN
Name: 1300, dtype: object
winner(df.loc[1300])

vancouvercanucks
[]
loser(df.loc[1300])

edmontonoilers
[]

Now that I see those working, I’ll clear the values away by resetting all the teams to an empty set

for team in teams:
  globals()[team] = []

Now to run this code for every game

for i in df.index:
  winner(df.loc[i])
  loser(df.loc[i])
stlouisblues
[2,
 2,
 2,
 2,
 2,
 0,
 2,
 1,
 2,
 0,
 2,
 1,
 0,
 0,
 0,
 2,
 0,
 2,
 0,
 1,
 2,
 2,
 0,
 1,
 2,
 2,
 2,
 1,
 2,
 2,
 0,
 2,
 2,
 0,
 2,
 2,
 2,
 0,
 2,
 2,
 2,
 0,
 2,
 0,
 0,
 2,
 2,
 1,
 2,
 2,
 2,
 2,
 0,
 0,
 1,
 0,
 2,
 2,
 1,
 1,
 0,
 2,
 0,
 0,
 2,
 2,
 1,
 2,
 2,
 2,
 2,
 2,
 2,
 2,
 2,
 2,
 1,
 2,
 2,
 2,
 0,
 0]

I think this worked. Now to store it in the dataframe.

len(stlouisblues)
82
pointsbygame['anaheimducks'] = anaheimducks
for team in teams:
  pointsbygame[team] = globals()[team]

pointsbygame
tampabaylightning vegasgoldenknights anaheimducks coloradoavalanche edmontonoilers torontomapleleafs washingtoncapitals buffalosabres carolinahurricanes columbusbluejackets ... arizonacoyotes calgaryflames chicagoblackhawks minnesotawild winnipegjets dallasstars seattlekraken stlouisblues vancouvercanucks newyorkislanders
game1 0 2 2 2 2 2 2 2 2 2 ... 0 0 0 2 0 2 0 2 1 0
game2 2 0 0 0 2 0 1 2 2 2 ... 1 1 1 2 0 0 2 2 2 0
game3 2 0 2 0 2 2 2 2 2 0 ... 0 2 0 2 1 0 1 2 0 2
game4 0 0 0 0 2 1 2 0 2 2 ... 0 2 0 2 2 2 0 2 0 1
game5 1 0 0 2 2 0 1 1 2 0 ... 0 2 0 0 2 2 0 2 2 2
... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...
game78 2 2 0 0 2 0 2 2 2 1 ... 0 2 0 2 0 0 0 2 0 0
game79 2 1 0 0 0 1 1 2 2 2 ... 1 2 0 2 2 2 0 2 0 0
game80 2 1 0 2 2 2 0 2 2 0 ... 2 2 2 0 2 2 0 2 2 2
game81 0 1 2 1 2 2 0 0 2 2 ... 2 1 2 2 2 1 2 0 2 2
game82 2 2 0 0 2 2 0 2 2 0 ... 2 0 1 2 2 2 0 0 1 0

82 rows × 32 columns

totalpointsbygame = pa.DataFrame(np.nan, index = range(0,83),columns = teams)

for team in teams:
  globals()[team + 'total'] = [0]

for team in teams:
  points = 0
  for game in globals()[team]:
    points = points + game
    globals()[team + 'total'].append(points)
stlouisbluestotal
[0,
 2,
 4,
 6,
 8,
 10,
 10,
 12,
 13,
 15,
 15,
 17,
 18,
 18,
 18,
 18,
 20,
 20,
 22,
 22,
 23,
 25,
 27,
 27,
 28,
 30,
 32,
 34,
 35,
 37,
 39,
 39,
 41,
 43,
 43,
 45,
 47,
 49,
 49,
 51,
 53,
 55,
 55,
 57,
 57,
 57,
 59,
 61,
 62,
 64,
 66,
 68,
 70,
 70,
 70,
 71,
 71,
 73,
 75,
 76,
 77,
 77,
 79,
 79,
 79,
 81,
 83,
 84,
 86,
 88,
 90,
 92,
 94,
 96,
 98,
 100,
 102,
 103,
 105,
 107,
 109,
 109,
 109]
for team in teams:
  totalpointsbygame[team] = globals()[team + 'total']
totalpointsbygame
tampabaylightning vegasgoldenknights anaheimducks coloradoavalanche edmontonoilers torontomapleleafs washingtoncapitals buffalosabres carolinahurricanes columbusbluejackets ... arizonacoyotes calgaryflames chicagoblackhawks minnesotawild winnipegjets dallasstars seattlekraken stlouisblues vancouvercanucks newyorkislanders
0 0 0 0 0 0 0 0 0 0 0 ... 0 0 0 0 0 0 0 0 0 0
1 0 2 2 2 2 2 2 2 2 2 ... 0 0 0 2 0 2 0 2 1 0
2 2 2 2 2 4 2 3 4 4 4 ... 1 1 1 4 0 2 2 4 3 0
3 4 2 4 2 6 4 5 6 6 4 ... 1 3 1 6 1 2 3 6 3 2
4 4 2 4 2 8 5 7 6 8 6 ... 1 5 1 8 3 4 3 8 3 3
... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...
78 104 89 74 116 98 108 99 69 108 77 ... 50 106 63 107 81 91 58 105 87 80
79 106 90 74 116 98 109 100 71 110 79 ... 51 108 63 109 83 93 58 107 87 80
80 108 91 74 118 100 111 100 73 112 79 ... 53 110 65 109 85 95 58 109 89 82
81 108 92 76 119 102 113 100 73 114 81 ... 55 111 67 111 87 96 60 109 91 84
82 110 94 76 119 104 115 100 75 116 81 ... 57 111 68 113 89 98 60 109 92 84

83 rows × 32 columns

Ready for Visualizing#

totalpointsbygame.plot(kind = 'line', legend = False, xlim = [0,8], ylim = [0,16])
<matplotlib.axes._subplots.AxesSubplot at 0x7fc979e03e50>
../../_images/58c26696557b8742e82287f773183f27c5ece331d331d247c3bf44a5679a6a44.png

Next I need to make the transformation to look at points above average. I’ll need the average of the league to do that.

np.mean(totalpointsbygame, axis = 1)
0      0.00000
1      1.28125
2      2.34375
3      3.65625
4      4.65625
        ...   
78    86.43750
79    87.53125
80    88.75000
81    89.96875
82    91.00000
Length: 83, dtype: float64

Now I’ll convert the entries to be how much above or below this teams are at any point in the season.

def comparetoaverage(score,average):
  return score - average

totalpointsbygame.apply(lambda x: comparetoaverage(x,np.mean(totalpointsbygame, axis = 1)))
tampabaylightning vegasgoldenknights anaheimducks coloradoavalanche edmontonoilers torontomapleleafs washingtoncapitals buffalosabres carolinahurricanes columbusbluejackets ... arizonacoyotes calgaryflames chicagoblackhawks minnesotawild winnipegjets dallasstars seattlekraken stlouisblues vancouvercanucks newyorkislanders
0 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 ... 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000
1 -1.28125 0.71875 0.71875 0.71875 0.71875 0.71875 0.71875 0.71875 0.71875 0.71875 ... -1.28125 -1.28125 -1.28125 0.71875 -1.28125 0.71875 -1.28125 0.71875 -0.28125 -1.28125
2 -0.34375 -0.34375 -0.34375 -0.34375 1.65625 -0.34375 0.65625 1.65625 1.65625 1.65625 ... -1.34375 -1.34375 -1.34375 1.65625 -2.34375 -0.34375 -0.34375 1.65625 0.65625 -2.34375
3 0.34375 -1.65625 0.34375 -1.65625 2.34375 0.34375 1.34375 2.34375 2.34375 0.34375 ... -2.65625 -0.65625 -2.65625 2.34375 -2.65625 -1.65625 -0.65625 2.34375 -0.65625 -1.65625
4 -0.65625 -2.65625 -0.65625 -2.65625 3.34375 0.34375 2.34375 1.34375 3.34375 1.34375 ... -3.65625 0.34375 -3.65625 3.34375 -1.65625 -0.65625 -1.65625 3.34375 -1.65625 -1.65625
... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...
78 17.56250 2.56250 -12.43750 29.56250 11.56250 21.56250 12.56250 -17.43750 21.56250 -9.43750 ... -36.43750 19.56250 -23.43750 20.56250 -5.43750 4.56250 -28.43750 18.56250 0.56250 -6.43750
79 18.46875 2.46875 -13.53125 28.46875 10.46875 21.46875 12.46875 -16.53125 22.46875 -8.53125 ... -36.53125 20.46875 -24.53125 21.46875 -4.53125 5.46875 -29.53125 19.46875 -0.53125 -7.53125
80 19.25000 2.25000 -14.75000 29.25000 11.25000 22.25000 11.25000 -15.75000 23.25000 -9.75000 ... -35.75000 21.25000 -23.75000 20.25000 -3.75000 6.25000 -30.75000 20.25000 0.25000 -6.75000
81 18.03125 2.03125 -13.96875 29.03125 12.03125 23.03125 10.03125 -16.96875 24.03125 -8.96875 ... -34.96875 21.03125 -22.96875 21.03125 -2.96875 6.03125 -29.96875 19.03125 1.03125 -5.96875
82 19.00000 3.00000 -15.00000 28.00000 13.00000 24.00000 9.00000 -16.00000 25.00000 -10.00000 ... -34.00000 20.00000 -23.00000 22.00000 -2.00000 7.00000 -31.00000 18.00000 1.00000 -7.00000

83 rows × 32 columns

totalpointsbygame.apply(lambda x: comparetoaverage(x,np.mean(totalpointsbygame, axis = 1))).plot(kind = 'line', legend = False, xlim = [0,8], ylim = [-8,8])
<matplotlib.axes._subplots.AxesSubplot at 0x7fc979ccddd0>
../../_images/269b24a047941a9128c89dd67433731b7b765dbcdf22508a00d6a431316614c3.png

Let’s try to cut the graph off at 10 games but leave some room for team emblems.

totalpointsbygame.apply(lambda x: comparetoaverage(x,np.mean(totalpointsbygame, axis = 1))).iloc[0:10,:].plot(kind = 'line', legend = False, xlim = [0,15], ylim = [-10,10], yticks = range(-10,10,2))
<matplotlib.axes._subplots.AxesSubplot at 0x7fc979846ad0>
../../_images/846666b6f031b707eb65b84553913843893d13d4a3f7daff7b40e571361ffb23.png

Team Colors#

Next I am going to work on the colors so that they correspond to the team colors.

colors = {
    'anaheimducks':'#F47A38',
    'arizonacoyotes':'#8C2633'
}
totalpointsbygame.apply(lambda x: comparetoaverage(x,np.mean(totalpointsbygame, axis = 1))).loc[0:10,['anaheimducks','arizonacoyotes']].plot(kind = 'line', legend = False, xlim = [0,15], ylim = [-10,10], yticks = range(-10,10,2), color = colors)
<matplotlib.axes._subplots.AxesSubplot at 0x7fc979cbdd90>
../../_images/cf1da8d29650ce23a53fd444330927054cbff82191e666e50676de4bf9c34323.png

I think that is working. This is not the most exciting way to do this but the website I found requires lots of clicking…

colors['bostonbruins'] = '#FFB81C'
colors['buffalosabres'] = '#002654'
colors['calgaryflames'] = '#c8102E'
colors['carolinahurricanes'] = '#cc0000'
colors['chicagoblackhawks'] = '#CF0A2C'
colors['coloradoavalanche'] = '#6F263D'
colors['columbusbluejackets'] = '#002654'
colors['dallasstars'] = '#006847'
colors['detroitredwings'] = '#ce1126'
colors['edmontonoilers'] = '#041E42'
colors['floridapanthers'] = '#041E42'
colors['losangeleskings'] = '#111111'
colors['minnesotawild'] = '#A6192E'
colors['montrealcanadiens'] = '#AF1E2D'
colors['nashvillepredators'] = '#FFB81C'
colors['newjerseydevils'] = '#CE1126'
colors['newyorkislanders'] = '#00539b'
colors['newyorkrangers'] = '#0038A8'
colors['ottawasenators'] = '#c52032'
colors['pittsburghpenguins'] = '#000000'
colors['philadelphiaflyers'] = '#F74902'
colors['stlouisblues'] = '#002F87'
colors['sanjosesharks'] = '#006D75'
colors['seattlekraken'] = '#001628'
colors['tampabaylightning'] = '#002868'
colors['torontomapleleafs'] = '#00205b'
colors['vancouvercanucks'] = '#00205B'
colors['vegasgoldenknights'] = '#B4975A'
colors['washingtoncapitals'] = '#041E42'
colors['winnipegjets'] = '#041E42'
len(colors)
32
totalpointsbygame.apply(lambda x: comparetoaverage(x,np.mean(totalpointsbygame, axis = 1))).iloc[0:10,:].plot(kind = 'line', legend = False, xlim = [0,15], ylim = [-10,10], yticks = range(-10,10,2), color = colors)
<matplotlib.axes._subplots.AxesSubplot at 0x7fc97bda0750>
../../_images/56cab7adabd798950e942353ac18e02ce9bf8ef2a8b5bb1be7b73c82dc964e8e.png

Divisions#

I am going to need the divisions for each club.

atlantic = [
            'floridapanthers',
            'torontomapleleafs',
            'tampabaylightning',
            'bostonbruins',
            'detroitredwings',
            'buffalosabres',
            'ottawasenators',
            'montrealcanadiens'
]

metropolotian = [
                 'carolinahurricanes',
                 'newyorkrangers',
                 'newyorkislanders',
                 'pittsburghpenguins',
                 'washingtoncapitals',
                 'columbusbluejackets',
                 'newjerseydevils',
                 'philadelphiaflyers'
]

central = [
           'coloradoavalanche',
           'minnesotawild',
           'stlouisblues',
           'dallasstars',
           'nashvillepredators',
           'winnipegjets',
           'chicagoblackhawks',
           'arizonacoyotes'
]

pacific = [
           'calgaryflames',
           'edmontonoilers',
           'losangeleskings',
           'vegasgoldenknights',
           'vancouvercanucks',
           'sanjosesharks',
           'anaheimducks',
           'seattlekraken'
]

division = [atlantic, metropolotian, central, pacific]
Divisions = ['Atlantic', 'Metropolotian', 'Central', 'Pacific']

Emblems#

linkstub = "https://raw.githubusercontent.com/nurfnick/Data_Viz/main/Content/Project_Examples/NHL_Logos/"
from matplotlib.offsetbox import TextArea, DrawingArea, OffsetImage, AnnotationBbox
fig, ax = plt.subplots()

ax.set_xlim(0, 1)
ax.set_ylim(0, 1)

arr_lena = plt.imread(linkstub +'bostonbruins.png')

#ax.imshow(arr_lena)
newax = fig.add_axes([0.8, 0.8, 0.2, 0.2], anchor='NE', zorder=1)
newax.imshow(arr_lena)
newax.axis('off')
#imagebox = OffsetImage(arr_lena, zoom=0.2)

#ab = AnnotationBbox(imagebox, (0.4, 0.6))

#ax.add_artist(ab)
plt.draw()
plt.show()
../../_images/e365a7f274e63e9fccf06a858534b8f3aa1ba5d4f24a9cdc5d87b2dd718afff6.png


fig = totalpointsbygame.apply(lambda x: comparetoaverage(x,np.mean(totalpointsbygame, axis = 1))).iloc[0:10,:].plot(kind = 'line', legend = False, xlim = [0,15], ylim = [-10,10], yticks = range(-10,10,2), color = colors)


arr_lena = plt.imread(linkstub + 'bostonbruins.png')


axin = fig.inset_axes([0.8,0.8,0.2,0.2], anchor='NE', zorder=1)    # create new inset axes in data coordinates
axin.imshow(arr_lena)
axin.axis('off')




plt.show()
../../_images/2861e0bcc0099302a73405407d30c4b8bcb53a83dfccb700a8fcfaf141b058c5.png
fig, ax = plt.subplots()

ax.set_xlim(0, 1)
ax.set_ylim(0, 1)

arr_lena = plt.imread(linkstub + 'bostonbruins.png')


imagebox = OffsetImage(arr_lena, zoom=0.2)

ab = AnnotationBbox(imagebox, (0.4, 0.6), frameon = False)

ax.add_artist(ab)
plt.draw()
plt.show()
../../_images/f3b66503e2ffc1e384553fe2f7b1b57ca3d4bd319d4cd31fa4f8bda99aedb7a4.png
fig = totalpointsbygame.apply(lambda x: comparetoaverage(x,np.mean(totalpointsbygame, axis = 1))).iloc[0:10,:].plot(kind = 'line', legend = False, xlim = [0,15], ylim = [-10,10], yticks = range(-10,10,2), color = colors)




arr_lena = plt.imread(linkstub + 'bostonbruins.png')


imagebox = OffsetImage(arr_lena, zoom=0.1)

ab = AnnotationBbox(imagebox, (9.5, 0), frameon = False)

fig.add_artist(ab)




plt.show()
../../_images/4585d9e2ff45fcc9f150c3524548a830d417f8c2078d07620e7541a8113e7cc4.png
fig = totalpointsbygame.apply(lambda x: comparetoaverage(x,np.mean(totalpointsbygame, axis = 1))).loc[0:9,central].plot(kind = 'line', legend = False, xlim = [0,15], ylim = [-10,10], yticks = range(-10,10,2), color = colors)
dontoverlay = []
for team in central:
  y = totalpointsbygame.apply(lambda x: comparetoaverage(x,np.mean(totalpointsbygame, axis = 1))).loc[9,team]
  if y in dontoverlay:
    move = .6
  else:
    move = 0
  dontoverlay.append(y)
  arr_lena = plt.imread(linkstub + team + '.png') #needs to be team name +".png"
  imagebox = OffsetImage(arr_lena, zoom=0.1)
  ab = AnnotationBbox(imagebox, (9.5+move,totalpointsbygame.apply(lambda x: comparetoaverage(x,np.mean(totalpointsbygame, axis = 1))).loc[9,team] ), frameon = False)
  fig.add_artist(ab)

plt.show()
../../_images/0cdfbf60e9ca771323b44cd7f0599a7b35db8e82a6579582e8e24a4103c97531.png
fig = totalpointsbygame.apply(lambda x: comparetoaverage(x,np.mean(totalpointsbygame, axis = 1))).loc[0:,central].plot(kind = 'line', 
                                                                                                                        legend = False, 
                                                                                                                        #xlim = [0,15], 
                                                                                                                        #ylim = [-10,10], 
                                                                                                                        #yticks = range(-10,10,2), 
                                                                                                                        color = colors)
dontoverlay = []
for team in central:
  y = totalpointsbygame.apply(lambda x: comparetoaverage(x,np.mean(totalpointsbygame, axis = 1))).loc[9,team]
  if y in dontoverlay:
    move = .6
  else:
    move = 0
  dontoverlay.append(y)
  arr_lena = plt.imread(linkstub + team + '.png') #needs to be team name +".png"
  imagebox = OffsetImage(arr_lena, zoom=0.1)
  ab = AnnotationBbox(imagebox, (75+move,totalpointsbygame.apply(lambda x: comparetoaverage(x,np.mean(totalpointsbygame, axis = 1))).loc[72,team] ), frameon = False)
  fig.add_artist(ab)

plt.show()
../../_images/742d685dbb31498dd99cf53d007b44572174113b18d0eef88ed46da3027cb9ef.png

Putting it all Together#

fig, ax = plt.subplots(4,linewidth=10, edgecolor="#04253a")
fig.set_figheight(50)
fig.set_figwidth(20)

for i, div in enumerate(division):
  totalpointsbygame.apply(lambda x: comparetoaverage(x,np.mean(totalpointsbygame, axis = 1))).loc[0:,div].plot(kind = 'line', 
                                                                                                                        legend = False, 
                                                                                                                        #xlim = [0,15], 
                                                                                                                        #ylim = [-10,10], 
                                                                                                                        #yticks = range(-10,10,2), 
                                                                                                                        color = colors,
                                                                                                                        ax = ax[i])
  dontoverlay = []
  for team in div:
    y = totalpointsbygame.apply(lambda x: comparetoaverage(x,np.mean(totalpointsbygame, axis = 1))).loc[9,team]
    if y in dontoverlay:
      move = .6
    else:
      move = 0
    dontoverlay.append(y)
    arr_lena = plt.imread(linkstub + team + '.png') #needs to be team name +".png"
    imagebox = OffsetImage(arr_lena, zoom=0.3)
    ab = AnnotationBbox(imagebox, (78+move,totalpointsbygame.apply(lambda x: comparetoaverage(x,np.mean(totalpointsbygame, axis = 1))).loc[76,team] ), frameon = False)
    ax[i].add_artist(ab)
  ax[i].set_title("NHL {} Division 2022".format(Divisions[i]))
  ax[i].set(xlabel = 'Games')

plt.show()
../../_images/028c1f682e14bcb9c99b1cfd8a3dcb278a3cc8b0b5eb3d34f79f466fad74c6c1.png

Trying to add the borders.

fig, ax = plt.subplots(4,linewidth=10, edgecolor="#04253a")
fig.set_figheight(50)
fig.set_figwidth(20)

for i, div in enumerate(division):
  totalpointsbygame.apply(lambda x: comparetoaverage(x,np.mean(totalpointsbygame, axis = 1))).loc[0:,div].plot(kind = 'line', 
                                                                                                                        legend = False, 
                                                                                                                        #xlim = [0,15], 
                                                                                                                        #ylim = [-10,10], 
                                                                                                                        #yticks = range(-10,10,2), 
                                                                                                                        color = colors,
                                                                                                                        ax = ax[i])
  rect = plt.Rectangle(
    # (lower-left corner), width, height
    (0.0, 0.72), 0.97, 0.1, fill=False, color="k", lw=2, 
    zorder=1000, transform=fig.transFigure, figure=fig
  )
  fig.patches.extend([rect])
  dontoverlay = []
  for team in div:
    y = totalpointsbygame.apply(lambda x: comparetoaverage(x,np.mean(totalpointsbygame, axis = 1))).loc[9,team]
    if y in dontoverlay:
      move = .6
    else:
      move = 0
    dontoverlay.append(y)
    arr_lena = plt.imread(linkstub + team + '.png') #needs to be team name +".png"
    imagebox = OffsetImage(arr_lena, zoom=0.3)
    ab = AnnotationBbox(imagebox, (78+move,totalpointsbygame.apply(lambda x: comparetoaverage(x,np.mean(totalpointsbygame, axis = 1))).loc[77,team] ), frameon = False)
    ax[i].add_artist(ab)
  ax[i].set_title("NHL {} Division 2022".format(Divisions[i]))
  ax[i].set(xlabel = 'Games')

plt.show()



plt.tight_layout()
../../_images/8064f3b85c74b32fbbd8c16ccc92c2d97213c38dcee8f4d77e69ce6f4955c3e0.png
<Figure size 432x288 with 0 Axes>

I cannot seem to get the frames to work. Something with the rectangles is just not going to do it. That’s not great but something I should move on from and keep as something I was not able to do.

I am seeing my emblems sit on top of one another. I don’t like that at all so I’ll try to fix that. Before I had used the dontoverlay but that worked well only when the numbers were small (and the graphics too!) I’ll need to look for a range around them!

gamesplayed = (~pa.isnull(totalpointsbygame).loc[1:,]).cumsum(0).max()

fig, ax = plt.subplots(4)
fig.set_figheight(50)
fig.set_figwidth(20)

for i, div in enumerate(division):
  totalpointsbygame.apply(lambda x: comparetoaverage(x,np.mean(totalpointsbygame, axis = 1))).loc[0:,div].plot(kind = 'line', 
                                                                                                                        legend = False, 
                                                                                                                        xlim = [0,85], 
                                                                                                                        #ylim = [-10,10], 
                                                                                                                        #yticks = range(-10,10,2), 
                                                                                                                        color = colors,
                                                                                                                        ax = ax[i],
                                                                                                                        grid = True)
  for line in ax[i].get_lines():
    line.set_linewidth(7)
  dontoverlay = []
  for team in div:
    y = totalpointsbygame.apply(lambda x: comparetoaverage(x,np.mean(totalpointsbygame, axis = 1))).loc[gamesplayed[team],team]
    testagainstploted = [100]
    for x in dontoverlay:
      testagainstploted.append(x-y)
    if min(np.abs(testagainstploted))<4:
      move = move - 3
    else:
      move = 0
    dontoverlay.append(y)
    arr = plt.imread(linkstub + team + '.png') #needs to be team name +".png"
    imagebox = OffsetImage(arr, zoom=0.25)
    ab = AnnotationBbox(imagebox, (gamesplayed[team] + 1,totalpointsbygame.apply(lambda x: comparetoaverage(x,np.mean(totalpointsbygame, axis = 1))).loc[gamesplayed[team],team]+move-1 ), frameon = False)
    ax[i].add_artist(ab)
  ax[i].set_title("NHL {} Division 2022".format(Divisions[i]))
  ax[i].set(xlabel = 'Games')
  ax[i].axhline(color = 'black')

plt.show()



#plt.tight_layout()
../../_images/7ceebb343879922ee8fcb863b2d64afdaf46d57472923a5dc554ababba15db62.png

I am not super happy with that outcome either. I have it moving an emblom up regaurdless of whether they are above in the standings.

I did add a clever piece of coding. Not all teams had played the same number of games so I found how many games they had played by counting how many were not null.

(~pa.isnull(totalpointsbygame).loc[1:,]).cumsum(0).max()
tampabaylightning      82
vegasgoldenknights     82
anaheimducks           82
coloradoavalanche      82
edmontonoilers         82
torontomapleleafs      82
washingtoncapitals     82
buffalosabres          82
carolinahurricanes     82
columbusbluejackets    82
detroitredwings        82
floridapanthers        82
losangeleskings        82
nashvillepredators     82
newyorkrangers         82
ottawasenators         82
newjerseydevils        82
philadelphiaflyers     82
bostonbruins           82
montrealcanadiens      82
pittsburghpenguins     82
sanjosesharks          82
arizonacoyotes         82
calgaryflames          82
chicagoblackhawks      82
minnesotawild          82
winnipegjets           82
dallasstars            82
seattlekraken          82
stlouisblues           82
vancouvercanucks       82
newyorkislanders       82
dtype: int64

I keep making changes without doing a new cell. I tweeked the size of the lines, added grids and but the \(x\)-axis on the graph. I also limited the length of the \(x\)-axis so as not to include the negative values.

gamesplayed = (~pa.isnull(totalpointsbygame).loc[1:,]).cumsum(0).max()

fig, ax = plt.subplots(4)
fig.set_figheight(50)
fig.set_figwidth(20)

for i, div in enumerate(division):
  totalpointsbygame.apply(lambda x: comparetoaverage(x,np.mean(totalpointsbygame, axis = 1))).loc[0:,div].plot(kind = 'line', 
                                                                                                                        legend = False, 
                                                                                                                        xlim = [0,85], 
                                                                                                                        #ylim = [-10,10], 
                                                                                                                        #yticks = range(-10,10,2), 
                                                                                                                        color = colors,
                                                                                                                        ax = ax[i],
                                                                                                                        grid = True)
  for line in ax[i].get_lines():
    line.set_linewidth(7)
  dontoverlay = []
  for team in div:
    y = totalpointsbygame.apply(lambda x: comparetoaverage(x,np.mean(totalpointsbygame, axis = 1))).loc[gamesplayed[team],team]
    testagainstploted = [100]#needed this to be non-empty so put a huge value that will not be achieved by any team.
    for x in dontoverlay:
      testagainstploted.append(x-y)
    if min(np.abs(testagainstploted))<4:
      if min(np.abs(testagainstploted)) in testagainstploted:
        move = move - 2
      else:
        move = move + 2
    else:
      move = 0
    dontoverlay.append(y)
    arr = plt.imread(linkstub + team + '.png') #needs to be team name +".png"
    imagebox = OffsetImage(arr, zoom=0.25)
    ab = AnnotationBbox(imagebox, (gamesplayed[team] + 1,totalpointsbygame.apply(lambda x: comparetoaverage(x,np.mean(totalpointsbygame, axis = 1))).loc[gamesplayed[team],team]+move ), frameon = False)
    ax[i].add_artist(ab)
  ax[i].set_title("NHL {} Division 2022".format(Divisions[i]), fontsize = 30)
  ax[i].set_xlabel('Games', fontsize = 20)
  ax[i].axhline(color = 'black')

plt.show()
../../_images/9927ba377502ea1030d57410dfe657bb897b8461da0616d693e0219e68f8c12b.png

Above I changed font size on the titles and labels. I think I have the embloms not overlapping too bad. I think I am ready to put the big boy on here with all the teams together…



fig, ax = plt.subplots(5)
fig.set_figheight(50)
fig.set_figwidth(20)

for i, div in enumerate(division):
  totalpointsbygame.apply(lambda x: comparetoaverage(x,np.mean(totalpointsbygame, axis = 1))).loc[0:,div].plot(kind = 'line', 
                                                                                                                        legend = False, 
                                                                                                                        xlim = [0,85], 
                                                                                                                        #ylim = [-10,10], 
                                                                                                                        #yticks = range(-10,10,2), 
                                                                                                                        color = colors,
                                                                                                                        ax = ax[i],
                                                                                                                        grid = True)
  for line in ax[i].get_lines():
    line.set_linewidth(7)
  dontoverlay = []
  for team in div:
    y = totalpointsbygame.apply(lambda x: comparetoaverage(x,np.mean(totalpointsbygame, axis = 1))).loc[gamesplayed[team],team]
    testagainstploted = [100]#needed this to be non-empty so put a huge value that will not be achieved by any team.
    for x in dontoverlay:
      testagainstploted.append(x-y)
    if min(np.abs(testagainstploted))<4:
      if min(np.abs(testagainstploted)) in testagainstploted:
        move = move - 2
      else:
        move = move + 2
    else:
      move = 0
    dontoverlay.append(y)
    arr = plt.imread(linkstub + team + '.png') #needs to be team name +".png"
    imagebox = OffsetImage(arr, zoom=0.25)
    ab = AnnotationBbox(imagebox, (gamesplayed[team] + 1,totalpointsbygame.apply(lambda x: comparetoaverage(x,np.mean(totalpointsbygame, axis = 1))).loc[gamesplayed[team],team]+move ), frameon = False)
    ax[i].add_artist(ab)
  ax[i].set_title("NHL {} Division 2022".format(Divisions[i]), fontsize = 30)
  ax[i].set_xlabel('Games', fontsize = 20)
  ax[i].axhline(color = 'black')
### Adding all teams together
totalpointsbygame.apply(lambda x: comparetoaverage(x,np.mean(totalpointsbygame, axis = 1))).loc[0:,:].plot(kind = 'line', 
                                                                                                                        legend = False, 
                                                                                                                        xlim = [0,85], 
                                                                                                                        #ylim = [-10,10], 
                                                                                                                        #yticks = range(-10,10,2), 
                                                                                                                        color = colors,
                                                                                                                        ax = ax[4],
                                                                                                                        grid = True)
for div in division:
  for team in div:
      y = totalpointsbygame.apply(lambda x: comparetoaverage(x,np.mean(totalpointsbygame, axis = 1))).loc[gamesplayed[team],team]
      testagainstploted = [100]#needed this to be non-empty so put a huge value that will not be achieved by any team.
      for x in dontoverlay:
        testagainstploted.append(x-y)
      if min(np.abs(testagainstploted))<4:
        if min(np.abs(testagainstploted)) in testagainstploted:
          move = move - 2
        else:
          move = move + 2
      else:
        move = 0
      dontoverlay.append(y)
      arr = plt.imread(linkstub + team + '.png') #needs to be team name +".png"
      imagebox = OffsetImage(arr, zoom=0.1)
      ab = AnnotationBbox(imagebox, (gamesplayed[team] + 1,totalpointsbygame.apply(lambda x: comparetoaverage(x,np.mean(totalpointsbygame, axis = 1))).loc[gamesplayed[team],team]+move ), frameon = False)
      ax[4].add_artist(ab)
ax[4].set_title("NHL 2022", fontsize = 30)
ax[4].set_xlabel('Games', fontsize = 20)
ax[4].axhline(color = 'black')
for line in ax[4].get_lines():
  line.set_linewidth(2)
plt.show()
../../_images/756ff3c7358caa6a0dfdd29dcc9c742eb4ae3f8d015c6490610ec06282a1e754.png
fig, ax = plt.subplots(5, sharey = True)
fig.set_figheight(50)
fig.set_figwidth(20)


for i, div in enumerate(division):
  totalpointsbygame.apply(lambda x: comparetoaverage(x,np.mean(totalpointsbygame, axis = 1))).loc[0:,div].plot(kind = 'line', 
                                                                                                                        legend = False, 
                                                                                                                        xlim = [0,85], 
                                                                                                                        #ylim = [-10,10], 
                                                                                                                        #yticks = range(-10,10,2), 
                                                                                                                        color = colors,
                                                                                                                        ax = ax[i],
                                                                                                                        grid = True)
  for line in ax[i].get_lines():
    line.set_linewidth(7)
  dontoverlay = []
  for team in div:
    y = totalpointsbygame.apply(lambda x: comparetoaverage(x,np.mean(totalpointsbygame, axis = 1))).loc[gamesplayed[team],team]
    testagainstploted = [100]#needed this to be non-empty so put a huge value that will not be achieved by any team.
    for x in dontoverlay:
      testagainstploted.append(x-y)
    if min(np.abs(testagainstploted))<4:
      if min(np.abs(testagainstploted)) in testagainstploted:
        move = move - 2
      else:
        move = move + 2
    else:
      move = 0
    dontoverlay.append(y)
    arr = plt.imread(linkstub + team + '.png') #needs to be team name +".png"
    imagebox = OffsetImage(arr, zoom=0.25)
    ab = AnnotationBbox(imagebox, (gamesplayed[team] + 1,totalpointsbygame.apply(lambda x: comparetoaverage(x,np.mean(totalpointsbygame, axis = 1))).loc[gamesplayed[team],team]+move ), frameon = False)
    ax[i].add_artist(ab)
  ax[i].set_title("NHL {} Division 2022".format(Divisions[i]), fontsize = 30)
  ax[i].set_xlabel('Games', fontsize = 20)
  ax[i].axhline(color = 'black')
### Adding all teams together
totalpointsbygame.apply(lambda x: comparetoaverage(x,np.mean(totalpointsbygame, axis = 1))).loc[0:,:].plot(kind = 'line', 
                                                                                                                        legend = False, 
                                                                                                                        xlim = [0,85], 
                                                                                                                        #ylim = [-10,10], 
                                                                                                                        #yticks = range(-10,10,2), 
                                                                                                                        color = colors,
                                                                                                                        ax = ax[4],
                                                                                                                        grid = True)
for div in division:
  for team in div:
      y = totalpointsbygame.apply(lambda x: comparetoaverage(x,np.mean(totalpointsbygame, axis = 1))).loc[gamesplayed[team],team]
      testagainstploted = [100]#needed this to be non-empty so put a huge value that will not be achieved by any team.
      for x in dontoverlay:
        testagainstploted.append(x-y)
      if min(np.abs(testagainstploted))<4:
        if min(np.abs(testagainstploted)) in testagainstploted:
          move = move - 2
        else:
          move = move + 2
      else:
        move = 0
      dontoverlay.append(y)
      arr = plt.imread(linkstub + team + '.png') #needs to be team name +".png"
      imagebox = OffsetImage(arr, zoom=0.13)
      ab = AnnotationBbox(imagebox, (gamesplayed[team] + 1,totalpointsbygame.apply(lambda x: comparetoaverage(x,np.mean(totalpointsbygame, axis = 1))).loc[gamesplayed[team],team]+move ), frameon = False)
      ax[4].add_artist(ab)
ax[4].set_title("NHL 2022", fontsize = 30)
ax[4].set_xlabel('Games', fontsize = 20)
ax[4].axhline(color = 'black')
for line in ax[4].get_lines():
  line.set_linewidth(2)
plt.show()
../../_images/8097f66a1ee1e4eca637b323caf0bcabfef34549b61f7f83c643e213fd19cc4f.png

I still need to figure out the percentage of points that are expected. Then I should be able to pass that as a percentage to a sub-title for each of my outputs. Let’s see what we can do.

expected = [i for i in range(1,83)] #one point per game is the expected.
centralstand = []


actual = [totalpointsbygame.loc[78,team] for team in central]
expected = [78 for team in central]

(sum(actual) - sum(expected))/(78*4)
0.26282051282051283

What is clear to me is that I didn;t know what the P% was. I think it is the point percentage or the percentage of games that a team gets points.

np.mean([i>0 for i in stlouisblues])
0.7317073170731707
divavg = []
for team in central:
  divavg.append(np.mean([i>0 for i in globals()[team]]))

np.mean(divavg)
0.6234756097560976

There it is! Let’s add that back in!

fig, ax = plt.subplots(5, sharey = True)
fig.set_figheight(50)
fig.set_figwidth(20)
lgavg = []

for i, div in enumerate(division):
  divavg = []
  totalpointsbygame.apply(lambda x: comparetoaverage(x,np.mean(totalpointsbygame, axis = 1))).loc[0:,div].plot(kind = 'line', 
                                                                                                                        legend = False, 
                                                                                                                        xlim = [0,85], 
                                                                                                                        #ylim = [-10,10], 
                                                                                                                        #yticks = range(-10,10,2), 
                                                                                                                        color = colors,
                                                                                                                        ax = ax[i],
                                                                                                                        grid = True)
  for line in ax[i].get_lines():
    line.set_linewidth(7)
  dontoverlay = []
  for team in div:
    divavg.append(np.mean([i>0 for i in globals()[team]]))
    y = totalpointsbygame.apply(lambda x: comparetoaverage(x,np.mean(totalpointsbygame, axis = 1))).loc[gamesplayed[team],team]
    testagainstploted = [100]#needed this to be non-empty so put a huge value that will not be achieved by any team.
    for x in dontoverlay:
      testagainstploted.append(x-y)
    if min(np.abs(testagainstploted))<4:
      if min(np.abs(testagainstploted)) in testagainstploted:
        move = move - 2
      else:
        move = move + 2
    else:
      move = 0
    dontoverlay.append(y)
    arr = plt.imread(linkstub + team + '.png') #needs to be team name +".png"
    imagebox = OffsetImage(arr, zoom=0.25)
    ab = AnnotationBbox(imagebox, (gamesplayed[team] + 1,totalpointsbygame.apply(lambda x: comparetoaverage(x,np.mean(totalpointsbygame, axis = 1))).loc[gamesplayed[team],team]+move ), frameon = False)
    ax[i].add_artist(ab)
  P = np.mean(divavg)
  lgavg.append(P)
  ax[i].set_title("NHL {} Division 2022 \n Wins Above Division Average P% ({})".format(Divisions[i],round(P,3)), fontsize = 25)
  ax[i].set_xlabel('Games', fontsize = 15)
  ax[i].axhline(color = 'black')


### Adding all teams together
totalpointsbygame.apply(lambda x: comparetoaverage(x,np.mean(totalpointsbygame, axis = 1))).loc[0:,:].plot(kind = 'line', 
                                                                                                                        legend = False, 
                                                                                                                        xlim = [0,85], 
                                                                                                                        #ylim = [-10,10], 
                                                                                                                        #yticks = range(-10,10,2), 
                                                                                                                        color = colors,
                                                                                                                        ax = ax[4],
                                                                                                                        grid = True)
for div in division:
  for team in div:
      y = totalpointsbygame.apply(lambda x: comparetoaverage(x,np.mean(totalpointsbygame, axis = 1))).loc[gamesplayed[team],team]
      testagainstploted = [100]#needed this to be non-empty so put a huge value that will not be achieved by any team.
      for x in dontoverlay:
        testagainstploted.append(x-y)
      if min(np.abs(testagainstploted))<4:
        if min(np.abs(testagainstploted)) in testagainstploted:
          move = move - 2
        else:
          move = move + 2
      else:
        move = 0
      dontoverlay.append(y)
      arr = plt.imread(linkstub + team + '.png') #needs to be team name +".png"
      imagebox = OffsetImage(arr, zoom=0.13)
      ab = AnnotationBbox(imagebox, (gamesplayed[team] + 1,totalpointsbygame.apply(lambda x: comparetoaverage(x,np.mean(totalpointsbygame, axis = 1))).loc[gamesplayed[team],team]+move ), frameon = False)
      ax[4].add_artist(ab)
ax[4].set_title("NHL 2022 \n Wins Above League Average P% ({})".format(round(np.mean(lgavg),3)), fontsize = 25)
ax[4].set_xlabel('Games', fontsize = 20)
ax[4].axhline(color = 'black')
for line in ax[4].get_lines():
  line.set_linewidth(2)
plt.show()
../../_images/1ec961ca7c21af08f5adcc2ae338f96e79c2d00895dfb50c18fda7b5ea5f43fd.png

Adding Text Box#

fig, ax = plt.subplots(5, sharey = True)
fig.set_figheight(50)
fig.set_figwidth(15)
lgavg = []

for i, div in enumerate(division):
  divavg = []
  totalpointsbygame.apply(lambda x: comparetoaverage(x,np.mean(totalpointsbygame, axis = 1))).loc[0:,div].plot(kind = 'line', 
                                                                                                                        legend = False, 
                                                                                                                        xlim = [0,85], 
                                                                                                                        #ylim = [-10,10], 
                                                                                                                        #yticks = range(-10,10,2), 
                                                                                                                        color = colors,
                                                                                                                        ax = ax[i],
                                                                                                                        grid = True)
  for line in ax[i].get_lines():
    line.set_linewidth(7)
  dontoverlay = []
  for team in div:
    divavg.append(np.mean([i>0 for i in globals()[team]]))
    y = totalpointsbygame.apply(lambda x: comparetoaverage(x,np.mean(totalpointsbygame, axis = 1))).loc[gamesplayed[team],team]
    testagainstploted = [100]#needed this to be non-empty so put a huge value that will not be achieved by any team.
    for x in dontoverlay:
      testagainstploted.append(x-y)
    if min(np.abs(testagainstploted))<4:
      if min(np.abs(testagainstploted)) in testagainstploted:
        move = move - 2
      else:
        move = move + 2
    else:
      move = 0
    dontoverlay.append(y)
    arr = plt.imread(linkstub + team + '.png') #needs to be team name +".png"
    imagebox = OffsetImage(arr, zoom=0.25)
    ab = AnnotationBbox(imagebox, (gamesplayed[team] + 1,totalpointsbygame.apply(lambda x: comparetoaverage(x,np.mean(totalpointsbygame, axis = 1))).loc[gamesplayed[team],team]+move ), frameon = False)
    ax[i].add_artist(ab)
  P = np.mean(divavg)
  lgavg.append(P)
  ax[i].set_title("NHL {} Division 2022 \n Wins Above Division Average P% ({})".format(Divisions[i],round(P,3)), fontsize = 25)
  ax[i].set_xlabel('Games', fontsize = 15)
  ax[i].axhline(color = 'black')


### Adding all teams together
totalpointsbygame.apply(lambda x: comparetoaverage(x,np.mean(totalpointsbygame, axis = 1))).loc[0:,:].plot(kind = 'line', 
                                                                                                                        legend = False, 
                                                                                                                        xlim = [0,85], 
                                                                                                                        #ylim = [-10,10], 
                                                                                                                        #yticks = range(-10,10,2), 
                                                                                                                        color = colors,
                                                                                                                        ax = ax[4],
                                                                                                                        grid = True)
for div in division:
  for team in div:
      y = totalpointsbygame.apply(lambda x: comparetoaverage(x,np.mean(totalpointsbygame, axis = 1))).loc[gamesplayed[team],team]
      testagainstploted = [100]#needed this to be non-empty so put a huge value that will not be achieved by any team.
      for x in dontoverlay:
        testagainstploted.append(x-y)
      if min(np.abs(testagainstploted))<4:
        if min(np.abs(testagainstploted)) in testagainstploted:
          move = move - 2
        else:
          move = move + 2
      else:
        move = 0
      dontoverlay.append(y)
      arr = plt.imread(linkstub + team + '.png') #needs to be team name +".png"
      imagebox = OffsetImage(arr, zoom=0.13)
      ab = AnnotationBbox(imagebox, (gamesplayed[team] + 1,totalpointsbygame.apply(lambda x: comparetoaverage(x,np.mean(totalpointsbygame, axis = 1))).loc[gamesplayed[team],team]+move ), frameon = False)
      ax[4].add_artist(ab)
ax[4].set_title("NHL 2022 \n Wins Above League Average P% ({})".format(round(np.mean(lgavg),3)), fontsize = 25)
ax[4].set_xlabel('Games', fontsize = 20)
ax[4].axhline(color = 'black')
for line in ax[4].get_lines():
  line.set_linewidth(2)

text = fig.text(0, .01, 
    'The Y-Axis is the number of wins above or below the average P%. E.g., a team at a minus-five can climb back up to zero with a five-game win streak.\n\n The average P% varies with the number of OT games.  In a typical season, 22% to 24% of games go into OT, and the average P% is between .555 and .560', 
    horizontalalignment='left', 
    fontsize = 15,
    wrap=True) # I am not getting this text to wrap, just made the font size smaller so as not to extend the box out too much
fig.tight_layout(rect=(0,.05,1,1)) 
plt.show()
../../_images/5011aba0d0593222720a756b0235810a4634c3f7e1ab04764ca2f40b576eb5ea.png

Change Background Colors#

fig, ax = plt.subplots(5, sharey = True)
fig.set_figheight(50)
fig.set_figwidth(15)
lgavg = []


for i, div in enumerate(division):
  divavg = []
  totalpointsbygame.apply(lambda x: comparetoaverage(x,np.mean(totalpointsbygame, axis = 1))).loc[0:,div].plot(kind = 'line', 
                                                                                                                        legend = False, 
                                                                                                                        xlim = [0,85], 
                                                                                                                        #ylim = [-10,10], 
                                                                                                                        #yticks = range(-10,10,2), 
                                                                                                                        color = colors,
                                                                                                                        ax = ax[i],
                                                                                                                        grid = True)
  for line in ax[i].get_lines():
    line.set_linewidth(7)
  dontoverlay = []
  for team in div:
    divavg.append(np.mean([i>0 for i in globals()[team]]))
    y = totalpointsbygame.apply(lambda x: comparetoaverage(x,np.mean(totalpointsbygame, axis = 1))).loc[gamesplayed[team],team]
    testagainstploted = [100]#needed this to be non-empty so put a huge value that will not be achieved by any team.
    for x in dontoverlay:
      testagainstploted.append(x-y)
    if min(np.abs(testagainstploted))<4:
      if min(np.abs(testagainstploted)) in testagainstploted:
        move = move - 2
      else:
        move = move + 2
    else:
      move = 0
    dontoverlay.append(y)
    arr = plt.imread(linkstub + team + '.png') #needs to be team name +".png"
    imagebox = OffsetImage(arr, zoom=0.25)
    ab = AnnotationBbox(imagebox, (gamesplayed[team] + 1,totalpointsbygame.apply(lambda x: comparetoaverage(x,np.mean(totalpointsbygame, axis = 1))).loc[gamesplayed[team],team]+move ), frameon = False)
    ax[i].add_artist(ab)
  P = np.mean(divavg)
  lgavg.append(P)
  ax[i].set_title("NHL {} Division 2022 \n Wins Above Division Average P% ({})".format(Divisions[i],round(P,3)), fontsize = 25)
  ax[i].set_xlabel('Games', fontsize = 15)
  ax[i].axhline(color = 'black')
  ax[i].set_facecolor('whitesmoke')


### Adding all teams together
totalpointsbygame.apply(lambda x: comparetoaverage(x,np.mean(totalpointsbygame, axis = 1))).loc[0:,:].plot(kind = 'line', 
                                                                                                                        legend = False, 
                                                                                                                        xlim = [0,85], 
                                                                                                                        #ylim = [-10,10], 
                                                                                                                        #yticks = range(-10,10,2), 
                                                                                                                        color = colors,
                                                                                                                        ax = ax[4],
                                                                                                                        grid = True)
for div in division:
  for team in div:
      y = totalpointsbygame.apply(lambda x: comparetoaverage(x,np.mean(totalpointsbygame, axis = 1))).loc[gamesplayed[team],team]
      testagainstploted = [100]#needed this to be non-empty so put a huge value that will not be achieved by any team.
      for x in dontoverlay:
        testagainstploted.append(x-y)
      if min(np.abs(testagainstploted))<4:
        if min(np.abs(testagainstploted)) in testagainstploted:
          move = move - 2
        else:
          move = move + 2
      else:
        move = 0
      dontoverlay.append(y)
      arr = plt.imread(linkstub + team + '.png') #needs to be team name +".png"
      imagebox = OffsetImage(arr, zoom=0.13)
      ab = AnnotationBbox(imagebox, (gamesplayed[team] + 1,totalpointsbygame.apply(lambda x: comparetoaverage(x,np.mean(totalpointsbygame, axis = 1))).loc[gamesplayed[team],team]+move ), frameon = False)
      ax[4].add_artist(ab)
ax[4].set_title("NHL 2022 \n Wins Above League Average P% ({})".format(round(np.mean(lgavg),3)), fontsize = 25)
ax[4].set_xlabel('Games', fontsize = 20)
ax[4].axhline(color = 'black')
ax[4].set_facecolor('whitesmoke')
for line in ax[4].get_lines():
  line.set_linewidth(2)

text = fig.text(0, .01, 
    'The Y-Axis is the number of wins above or below the average P%. E.g., a team at a minus-five can climb back up to zero with a five-game win streak.\n\n The average P% varies with the number of OT games.  In a typical season, 22% to 24% of games go into OT, and the average P% is between .555 and .560', 
    horizontalalignment='left', 
    fontsize = 15,
    wrap=True) # I am not getting this text to wrap, just made the font size smaller so as not to extend the box out too much
fig.tight_layout(rect=(0,.05,1,1)) 
plt.show()
../../_images/1313c252cb78e977760bb666b59a0e32ba7532a347b637a6d1e677ca0962c71d.png

Trying For Borders One More Time#

The method described here seems useable. Let’s see!

fig, ax = plt.subplots(5, sharey = True)
fig.set_figheight(50)
fig.set_figwidth(15)
lgavg = []


for i, div in enumerate(division):
  divavg = []
  totalpointsbygame.apply(lambda x: comparetoaverage(x,np.mean(totalpointsbygame, axis = 1))).loc[0:,div].plot(kind = 'line', 
                                                                                                                        legend = False, 
                                                                                                                        xlim = [0,85], 
                                                                                                                        ylim = [-80,80], 
                                                                                                                        #yticks = range(-10,10,2), 
                                                                                                                        color = colors,
                                                                                                                        ax = ax[i],
                                                                                                                        grid = True)
  for line in ax[i].get_lines():
    line.set_linewidth(7)
  dontoverlay = []
  for team in div:
    divavg.append(np.mean([i>0 for i in globals()[team]]))
    y = totalpointsbygame.apply(lambda x: comparetoaverage(x,np.mean(totalpointsbygame, axis = 1))).loc[gamesplayed[team],team]
    testagainstploted = [100]#needed this to be non-empty so put a huge value that will not be achieved by any team.
    for x in dontoverlay:
      testagainstploted.append(x-y)
    if min(np.abs(testagainstploted))<4:
      if min(np.abs(testagainstploted)) in testagainstploted:
        move = move - 2
      else:
        move = move + 2
    else:
      move = 0
    dontoverlay.append(y)
    arr = plt.imread(linkstub + team + '.png') #needs to be team name +".png"
    imagebox = OffsetImage(arr, zoom=0.25)
    ab = AnnotationBbox(imagebox, (gamesplayed[team] + 1,totalpointsbygame.apply(lambda x: comparetoaverage(x,np.mean(totalpointsbygame, axis = 1))).loc[gamesplayed[team],team]+move ), frameon = False)
    ax[i].add_artist(ab)
  P = np.mean(divavg)
  lgavg.append(P)
  ax[i].set_title("NHL {} Division 2022 \n Wins Above Division Average P% ({})".format(Divisions[i],round(P,3)), fontsize = 25)
  ax[i].set_xlabel('Games', fontsize = 15)
  ax[i].axhline(color = 'black')
  ax[i].set_facecolor('whitesmoke')
  edges = ax[i].axis()
  rec = plt.Rectangle((edges[0] - 5, -91), (edges[1] - edges[0]) + 10, (edges[3] - edges[2]) + 27.5, fill=False, lw=10)
  rec = ax[i].add_patch(rec)
  rec.set_clip_on(False)


### Adding all teams together
totalpointsbygame.apply(lambda x: comparetoaverage(x,np.mean(totalpointsbygame, axis = 1))).loc[0:,:].plot(kind = 'line', 
                                                                                                                        legend = False, 
                                                                                                                        xlim = [0,85], 
                                                                                                                        ylim = [-80,80], 
                                                                                                                        #yticks = range(-10,10,2), 
                                                                                                                        color = colors,
                                                                                                                        ax = ax[4],
                                                                                                                        grid = True)
for div in division:
  for team in div:
      y = totalpointsbygame.apply(lambda x: comparetoaverage(x,np.mean(totalpointsbygame, axis = 1))).loc[gamesplayed[team],team]
      testagainstploted = [100]#needed this to be non-empty so put a huge value that will not be achieved by any team.
      for x in dontoverlay:
        testagainstploted.append(x-y)
      if min(np.abs(testagainstploted))<4:
        if min(np.abs(testagainstploted)) in testagainstploted:
          move = move - 2
        else:
          move = move + 2
      else:
        move = 0
      dontoverlay.append(y)
      arr = plt.imread(linkstub + team + '.png') #needs to be team name +".png"
      imagebox = OffsetImage(arr, zoom=0.13)
      ab = AnnotationBbox(imagebox, (gamesplayed[team] + 1,totalpointsbygame.apply(lambda x: comparetoaverage(x,np.mean(totalpointsbygame, axis = 1))).loc[gamesplayed[team],team]+move ), frameon = False)
      ax[4].add_artist(ab)
ax[4].set_title("NHL 2022 \n Wins Above League Average P% ({})".format(round(np.mean(lgavg),3)), fontsize = 25)
ax[4].set_xlabel('Games', fontsize = 20)
ax[4].axhline(color = 'black')
ax[4].set_facecolor('whitesmoke')
edges = ax[4].axis()
rec = plt.Rectangle((edges[0] - 5, -91), (edges[1] - edges[0]) + 10, (edges[3] - edges[2]) + 27.5, fill=False, lw=10)
rec = ax[4].add_patch(rec)
rec.set_clip_on(False)

for line in ax[4].get_lines():
  line.set_linewidth(2)

text = fig.text(0, .01, 
    'The Y-Axis is the number of wins above or below the average P%. E.g., a team at a minus-five can climb back up to zero with a five-game win streak.\n\n The average P% varies with the number of OT games.  In a typical season, 22% to 24% of games go into OT, and the average P% is between .555 and .560', 
    horizontalalignment='left', 
    fontsize = 15,
    wrap=True) # I am not getting this text to wrap, just made the font size smaller so as not to extend the box out too much

rec = plt.Rectangle((0,.01), 105, 30, fill=False, lw=10)


fig.tight_layout(rect=(0,.05,1,1)) 
plt.show()



../../_images/e5e38e2d7a05ea9ab2a6f47c53deb9407f0fe2dab05e045777b5310c38526842.png