A Comparison of NHL Head Injuries Approximately 20 Years Apart
2005-2006 and 2024-2025 Seasons
Kris Letang, Pittsburgh Penguins, 2017, in a helmet with visor. Source: Wikipedia Commons
Avalanche Nathan MacKinnon took a puck to the face May 11th, 2026 during a playoff game. Source: ESPN, Associated Press
Introduction
My data set is the NHL Injury Database, compiled by LW3H, from data from the teams, puckpedia.com, cbssports.com, the former capfriendly.com, tsn.ca, and sportsforcaster.com, consisting of injury data for all NHL teams to from the 2000-2001 season to midway through 2025-2026, when I downloaded it. It is posted on the NHL Injury Viz blog page, and Tableau Public. I joined this with team rosters and player stats from Hockey-reference.com, official NHL data provided by sportsradar.
Variable (dataset)
Defintion
Notes
Season (both)
Season of play, presented as the year it ended it
either 2006 or 2025
Team (both)
Team player was signed with
used in joining the datasets
Position (injuries)
Position played (Forward, Defense, or Goalie)
also indicates retired – filtered for only Forward and Defense
fullname (injuries) /Player (roster)
Player’s given and surname
had to wrangle injuries dataset to create to join to rosters
InjuryType (injuries)
What the injury or illness was
injurygroup (created)
classified InjuryType by area of body
head, upper or lower body, or other for sickness, undisclosed, non location specific injuries
GamesMissed (injuries)
how many games were missed
Nationality (roster)
What country the player is from
modified from original column “Birth” due to formatting
Pos (roster)
also position, but classifies as Center, Left and Right Wing, Defense, and Goalie
Age (roster)
Players age as of February of that season
height (roster)
height in inches
wrangled this column from original
Wt (roster)
weight in pounds
Shoots (roster)
side player shoots puck from L or R
often opposite of dominate hand
Exp (Experience) (roster)
Years in league before that season
GP (Games Played) (roster)
how many games played that season
specifically for that team
Goals
Goals scored
Assists
Goals they contributed to
usually by making one of the last two passes
PTS (Points) (Roster)
Sum of Goals and Assists
+/- (plus minus) (Roster
Differential of goals scored for and against when player is on the ice
PIM (Roster)
Penalties in minutes
minor penalties are 2 min, major is 5, game misconduct is 10
TOI (Roster
Time on Ice, total for whole season
displayed as mm:ss
ATOI (roster)
Average time on ice, TOI/Games played
displayed as mm:ss
TOI_min (roster)
Time on ice, total
converted to minutes as a decimal
ATOI_min (roster)
Average time on ice, TOI/Games played
converted to minutes as a decimal
I have been a hockey fan for years, following the Pittsburgh Penguins, and it has bugged me in a time when more and more attention is being payed to head injuries and concussions in sports, the National Hockey League does not wear full face masks. Collegiate hockey requires full facial protection. The new Professional Womens Hockey League wear helmets with cages. Instead, skaters in the NHL wear visors that protect the eyes only – and those were only made mandatory starting in the 2013-2014 season.
In 2012-2013, around 70% of the league was voluntarily wearing visors when New York Rangers defenseman Marc Staal was hit in the eye by a puck, and missed the remainder of the season (Johnson). Staal was not wearing a visor. In June, the NHL and NHL Players Association voted for a visor mandate that included a grandfather clause for anyone who had already played 25 games. Before Staal’s injury, a mandate had been rejected (Halford).
In the beginning of the 2005-2006 season, 38% of the NHL were wearing visors (CBC). In 2024-2025 and currently, only four players do not (0.46% of the league, in March of 2026) Jamie Benn of the Dallas Stars, Zach Bogosian of the Minnesota Wild, Ryan O’Reilly of the Nashville Predators, and Ryan Reaves of the San Jose Sharks (Johnson, Trettenero). I am comparing head injuries from two seasons approximately two decades apart to see how the increase safety measures, including visors, have performed over the years. The seasons are approximately two decades apart as the current season (2025-2026) was still in progress when I started this project, and 2004-2005 was not played.
Two important notes about this dataset:
One: Injuries are not independent necessarily independent, as the same players can get repeat injuries – Blake Lizzote of the Penguins even does with conussions in 2025; and are often injuring each other.
Two:Only injuries that meant the player missed subsequent games appear on this database. The above picture of Nathan MacKinnon’s injury likely would not appear in this dataset later this week as he came back in that game, and I doubt he will miss a game.
Data
Load Libraries and Data
library(tidyverse)library(readxl)
Warning: package 'readxl' was built under R version 4.5.3
library(webshot2)
Warning: package 'webshot2' was built under R version 4.5.3
Warning: package 'patchwork' was built under R version 4.5.3
library(ggfortify)
setwd("~/Schol Stuff/Montgomery College 2025/Data 110 Data Visualization/110 Final Project")nhlinjury <-read_csv("NHL Injury Database_data.csv") Roster06 <-read_excel("2006_2025Rosters.xlsx", sheet =1)Roster25 <-read_excel("2006_2025Rosters.xlsx", sheet =2)
Preview and Clean The Rosters
starting with the Rosters and player stats: two different tables from Hockey-reference.com were combined per team in Excel, and not all columns were used.
head(Roster06)
# A tibble: 6 × 21
Season Team Player Birth Nationality Pos Age Ht Wt `S/C` Exp
<dbl> <chr> <chr> <chr> <chr> <chr> <dbl> <chr> <dbl> <chr> <chr>
1 2006 Anaheim François… ca CA CA D 25 5-11 208 L/- 1
2 2006 Anaheim Kip Bren… ca CA CA LW 25 6-4 230 L/- 3
3 2006 Anaheim Ilya Bry… su SU SU G 25 6-3 213 -/L 2
4 2006 Anaheim Keith Ca… us US US D 35 6-1 207 L/- 13
5 2006 Anaheim Joe DiPe… ca CA CA D 26 6-2 199 L/- 1
6 2006 Anaheim Sergei F… su SU SU C 36 6-2 207 L/- 14
# ℹ 10 more variables: `Birth Date` <chr>, Summary <chr>, GP <dbl>,
# Goals <dbl>, Assists <dbl>, PTS <dbl>, `+/-` <dbl>, PIM <dbl>, TOI <chr>,
# ATOI <chr>
head(Roster25)
# A tibble: 6 × 21
Season Team Player Birth Nationality Pos Age Ht Wt `S/C` Exp
<dbl> <chr> <chr> <chr> <chr> <chr> <dbl> <chr> <dbl> <chr> <chr>
1 2025 Anaheim Leo Carl… se SE SE C 20 6-3 208 L/- 1
2 2025 Anaheim Sam Cola… us US US RW 23 6-2 213 R/- 1
3 2025 Anaheim Lukáš Do… cz CZ CZ G 24 6-2 190 -/L 3
4 2025 Anaheim Brian Du… us US US D 33 6-4 215 L/- 11
5 2025 Anaheim Robby Fa… ca CA CA C 29 5-11 185 L/- 8
6 2025 Anaheim Cam Fowl… ca CA CA D 33 6-2 213 L/- 14
# ℹ 10 more variables: `Birth Date` <chr>, Summary <chr>, GP <dbl>,
# Goals <dbl>, Assists <dbl>, PTS <dbl>, `+/-` <dbl>, PIM <dbl>, TOI <chr>,
# ATOI <chr>
Nationality was created as the lowercase characters in ‘Birth’ were a country flag image on the website.
Bind the rosters
Combine the two roster dataframes into one before any other cleaning is done to them:
# change Roster06 Goals to numeric so the bind worksRoster06$Goals <-as.numeric(Roster06$Goals) Rosterall <-bind_rows(Roster06, Roster25)dim(Rosterall)
[1] 2205 21
head(Rosterall)
# A tibble: 6 × 21
Season Team Player Birth Nationality Pos Age Ht Wt `S/C` Exp
<dbl> <chr> <chr> <chr> <chr> <chr> <dbl> <chr> <dbl> <chr> <chr>
1 2006 Anaheim François… ca CA CA D 25 5-11 208 L/- 1
2 2006 Anaheim Kip Bren… ca CA CA LW 25 6-4 230 L/- 3
3 2006 Anaheim Ilya Bry… su SU SU G 25 6-3 213 -/L 2
4 2006 Anaheim Keith Ca… us US US D 35 6-1 207 L/- 13
5 2006 Anaheim Joe DiPe… ca CA CA D 26 6-2 199 L/- 1
6 2006 Anaheim Sergei F… su SU SU C 36 6-2 207 L/- 14
# ℹ 10 more variables: `Birth Date` <chr>, Summary <chr>, GP <dbl>,
# Goals <dbl>, Assists <dbl>, PTS <dbl>, `+/-` <dbl>, PIM <dbl>, TOI <chr>,
# ATOI <chr>
Making Numeric and Seperating Columns (or both)
Time on Ice (TOI) and Average Time on Ice (ATOI) need converted to numeric
Experience (Exp) (years in league) needs the R for rookie replaced with 0, and converted to numeric
# ms() pulls out the mm:ss format, as.numeric converts to total seconds, divide by 60 to make minutesRosterall$TOI_min <-as.numeric(ms(Rosterall$TOI))/60Rosterall$ATOI_min <-as.numeric(ms(Rosterall$ATOI))/60Rosterall$Exp <-as.numeric(gsub("R", "0", Rosterall$Exp))head(Rosterall)
# A tibble: 6 × 23
Season Team Player Birth Nationality Pos Age Ht Wt `S/C` Exp
<dbl> <chr> <chr> <chr> <chr> <chr> <dbl> <chr> <dbl> <chr> <dbl>
1 2006 Anaheim François… ca CA CA D 25 5-11 208 L/- 1
2 2006 Anaheim Kip Bren… ca CA CA LW 25 6-4 230 L/- 3
3 2006 Anaheim Ilya Bry… su SU SU G 25 6-3 213 -/L 2
4 2006 Anaheim Keith Ca… us US US D 35 6-1 207 L/- 13
5 2006 Anaheim Joe DiPe… ca CA CA D 26 6-2 199 L/- 1
6 2006 Anaheim Sergei F… su SU SU C 36 6-2 207 L/- 14
# ℹ 12 more variables: `Birth Date` <chr>, Summary <chr>, GP <dbl>,
# Goals <dbl>, Assists <dbl>, PTS <dbl>, `+/-` <dbl>, PIM <dbl>, TOI <chr>,
# ATOI <chr>, TOI_min <dbl>, ATOI_min <dbl>
Ht (height) in feet-inches needs to be separated and recombined. S/C (shoots/catches) needs to be separated as well
Rosterall2 <- Rosterall |>separate(Ht, into =c("feet", "inch"), sep ="-", convert =TRUE) |>mutate(height =as.numeric(feet)*12+as.numeric(inch), .after ="inch") |>#multiply feet by 12, add to inches to get height in inches as new column separate(`S/C`, into=c("shoots", "catches"), sep ="/", convert =TRUE) # separate S/C and names them; not concerned about the dashes in place of NAs as Catches is only relevant for goalies and they should be the only ones without "shoots" and I'm filtering them out! head(Rosterall2)
# A tibble: 6 × 26
Season Team Player Birth Nationality Pos Age feet inch height Wt
<dbl> <chr> <chr> <chr> <chr> <chr> <dbl> <int> <int> <dbl> <dbl>
1 2006 Anaheim Françoi… ca CA CA D 25 5 11 71 208
2 2006 Anaheim Kip Bre… ca CA CA LW 25 6 4 76 230
3 2006 Anaheim Ilya Br… su SU SU G 25 6 3 75 213
4 2006 Anaheim Keith C… us US US D 35 6 1 73 207
5 2006 Anaheim Joe DiP… ca CA CA D 26 6 2 74 199
6 2006 Anaheim Sergei … su SU SU C 36 6 2 74 207
# ℹ 15 more variables: shoots <chr>, catches <chr>, Exp <dbl>,
# `Birth Date` <chr>, Summary <chr>, GP <dbl>, Goals <dbl>, Assists <dbl>,
# PTS <dbl>, `+/-` <dbl>, PIM <dbl>, TOI <chr>, ATOI <chr>, TOI_min <dbl>,
# ATOI_min <dbl>
Rosterall3 <- Rosterall2 |># removing a few columns I absolutely don't need for ease of viewingselect(-Birth, -feet, -inch, -catches, -Summary)head(Rosterall3)
# A tibble: 6 × 21
Season Team Player Nationality Pos Age height Wt shoots Exp
<dbl> <chr> <chr> <chr> <chr> <dbl> <dbl> <dbl> <chr> <dbl>
1 2006 Anaheim François Bea… CA D 25 71 208 L 1
2 2006 Anaheim Kip Brennan CA LW 25 76 230 L 3
3 2006 Anaheim Ilya Bryzgal… SU G 25 75 213 - 2
4 2006 Anaheim Keith Carney US D 35 73 207 L 13
5 2006 Anaheim Joe DiPenta CA D 26 74 199 L 1
6 2006 Anaheim Sergei Fedor… SU C 36 74 207 L 14
# ℹ 11 more variables: `Birth Date` <chr>, GP <dbl>, Goals <dbl>,
# Assists <dbl>, PTS <dbl>, `+/-` <dbl>, PIM <dbl>, TOI <chr>, ATOI <chr>,
# TOI_min <dbl>, ATOI_min <dbl>
Cleaning the Injury Data base
head(nhlinjury)
# A tibble: 6 × 8
Season Team Position Player `Injury Type` `Cap Hit` Chip `Games Missed`
<chr> <chr> <chr> <chr> <chr> <dbl> <dbl> <dbl>
1 2000/01 Anaheim F Kariya,… Foot NA NA 16
2 2000/01 Anaheim F Leclerc… Abdominal NA NA 13
3 2000/01 Anaheim F Leclerc… Knee NA NA 15
4 2000/01 Anaheim F McDonal… Concussion NA NA 7
5 2000/01 Anaheim F McInnis… Groin NA NA 3
6 2000/01 Anaheim F McInnis… Neck NA NA 3
Remove spaces in column names
Fix Season to be just the ending year of the season
names(nhlinjury) <-gsub(" ", "", names(nhlinjury))str_sub(nhlinjury$Season, start=3, end =5) <-""head(nhlinjury)
# A tibble: 6 × 8
Season Team Position Player InjuryType CapHit Chip GamesMissed
<chr> <chr> <chr> <chr> <chr> <dbl> <dbl> <dbl>
1 2001 Anaheim F Kariya, Paul Foot NA NA 16
2 2001 Anaheim F Leclerc, Mike Abdominal NA NA 13
3 2001 Anaheim F Leclerc, Mike Knee NA NA 15
4 2001 Anaheim F McDonald, Andy Concussion NA NA 7
5 2001 Anaheim F McInnis, Marty Groin NA NA 3
6 2001 Anaheim F McInnis, Marty Neck NA NA 3
Then separate Player from Surname, Given name and recombine into Given Surname to match the Rosters
# A tibble: 6 × 8
Season Team Position Player InjuryType CapHit Chip GamesMissed
<chr> <chr> <chr> <chr> <chr> <dbl> <dbl> <dbl>
1 2001 Anaheim F Kariya, Paul Foot NA NA 16
2 2001 Anaheim F Leclerc, Mike Abdominal NA NA 13
3 2001 Anaheim F Leclerc, Mike Knee NA NA 15
4 2001 Anaheim F McDonald, Andy Concussion NA NA 7
5 2001 Anaheim F McInnis, Marty Groin NA NA 3
6 2001 Anaheim F McInnis, Marty Neck NA NA 3
# A tibble: 6 × 11
Season Team Position surname given fullname InjuryType injurygroup CapHit
<chr> <chr> <chr> <chr> <chr> <chr> <chr> <chr> <dbl>
1 2006 Anaheim F Brennan " Kip" " Kip B… Shoulder upper NA
2 2006 Anaheim F Fedorov " Ser… " Serge… Groin lower NA
3 2006 Anaheim F Fedoruk " Tod… " Todd … Back upper NA
4 2006 Anaheim F Getzlaf " Rya… " Ryan … Shoulder upper NA
5 2006 Anaheim F Hedström " Jon… " Jonat… Groin lower NA
6 2006 Anaheim F Konopka " Zen… " Zenon… Ankle lower NA
# ℹ 2 more variables: Chip <dbl>, GamesMissed <dbl>
Join the dataframes
First trim all whitespace from the joining columns
Rosterall3$Player <-trimws(Rosterall3$Player) # weirdly this did not seem to work on every row and I had to manually remove spaces from the Excel fileinjury2$fullname <-trimws(injury2$fullname)Rosterall$Team <-trimws(Rosterall3$Team)injury2$Team <-trimws(injury2$Team)Rosterall3$Season <-trimws(Rosterall3$Season)injury2$Season <-trimws(injury2$Season)
complete the join
joined <-left_join(injury2, Rosterall3, by =c("Season"="Season", "fullname"="Player", "Team"="Team"), relationship ="many-to-many")head(joined)
# A tibble: 6 × 29
Season Team Position surname given fullname InjuryType injurygroup CapHit
<chr> <chr> <chr> <chr> <chr> <chr> <chr> <chr> <dbl>
1 2006 Anaheim F Brennan " Kip" Kip Bre… Shoulder upper NA
2 2006 Anaheim F Fedorov " Ser… Sergei … Groin lower NA
3 2006 Anaheim F Fedoruk " Tod… Todd Fe… Back upper NA
4 2006 Anaheim F Getzlaf " Rya… Ryan Ge… Shoulder upper NA
5 2006 Anaheim F Hedström " Jon… Jonatha… Groin lower NA
6 2006 Anaheim F Konopka " Zen… Zenon K… Ankle lower NA
# ℹ 20 more variables: Chip <dbl>, GamesMissed <dbl>, Nationality <chr>,
# Pos <chr>, Age <dbl>, height <dbl>, Wt <dbl>, shoots <chr>, Exp <dbl>,
# `Birth Date` <chr>, GP <dbl>, Goals <dbl>, Assists <dbl>, PTS <dbl>,
# `+/-` <dbl>, PIM <dbl>, TOI <chr>, ATOI <chr>, TOI_min <dbl>,
# ATOI_min <dbl>
Please note that joins sometimes failed due to the player never actually playing a game (during the regular season) with the team they were signed to when reported as injured. In some cases, this is because they missed the entire season due to injury. In others, it is because they were traded or otherwise changed teams mid-season, or were signed to an NHL level contract, but played solely for the minor league affiliate team.
Filter for only active Forwards and Defensmen
Goalies have completely different stats that I did not grab. They also had all been wearing full face masks.
The “retired” status is for players who haven’t played since a previous season due to injuries or physical condition but had not officially retired. Those players would matter for salary cap investigations, but I’m not looking at money at all.
join1 <- joined |>filter(Position %in%c("F", "D")) |>select(-CapHit, -Chip) # remove the columns concerning injury time effect on team's salary cap, as that is outside of the scope of this projecthead(join1)
# A tibble: 6 × 27
Season Team Position surname given fullname InjuryType injurygroup
<chr> <chr> <chr> <chr> <chr> <chr> <chr> <chr>
1 2006 Anaheim F Brennan " Kip" Kip Brenn… Shoulder upper
2 2006 Anaheim F Fedorov " Sergei" Sergei Fe… Groin lower
3 2006 Anaheim F Fedoruk " Todd" Todd Fedo… Back upper
4 2006 Anaheim F Getzlaf " Ryan" Ryan Getz… Shoulder upper
5 2006 Anaheim F Hedström " Jonathan" Jonathan … Groin lower
6 2006 Anaheim F Konopka " Zenon" Zenon Kon… Ankle lower
# ℹ 19 more variables: GamesMissed <dbl>, Nationality <chr>, Pos <chr>,
# Age <dbl>, height <dbl>, Wt <dbl>, shoots <chr>, Exp <dbl>,
# `Birth Date` <chr>, GP <dbl>, Goals <dbl>, Assists <dbl>, PTS <dbl>,
# `+/-` <dbl>, PIM <dbl>, TOI <chr>, ATOI <chr>, TOI_min <dbl>,
# ATOI_min <dbl>
# A tibble: 6 × 27
Season Team Position surname given fullname InjuryType injurygroup
<chr> <chr> <chr> <chr> <chr> <chr> <chr> <chr>
1 2006 Anaheim F Lupul " Joffrey" Joffrey… Concussion head
2 2006 Anaheim F Niedermayer " Rob" Rob Nie… Concussion head
3 2006 Anaheim F Perry " Corey" Corey P… Concussion head
4 2006 Anaheim D Marshall " Jason" Jason M… Nose head
5 2006 Anaheim D Salei " Ruslan" Ruslan … Orbital b… head
6 2006 Boston D Leetch " Brian" Brian L… Head head
# ℹ 19 more variables: GamesMissed <dbl>, Nationality <chr>, Pos <chr>,
# Age <dbl>, height <dbl>, Wt <dbl>, shoots <chr>, Exp <dbl>,
# `Birth Date` <chr>, GP <dbl>, Goals <dbl>, Assists <dbl>, PTS <dbl>,
# `+/-` <dbl>, PIM <dbl>, TOI <chr>, ATOI <chr>, TOI_min <dbl>,
# ATOI_min <dbl>
Model: Head Injury Severity (GamesMissed)
Check for collinearity using library DataExplorer on the numeric predictor variables
Age and Experience are highly correlated; as are height and Wt (weight); PTS highly correlates with goals, assists, and TOI_min; TOI_min with Games played (GP); Goals and assists are right on the boarder of judgement call.
Create model
Fit1 using Season, Position, InjuryType, Nationality, Wt (weight), shoots, sqrt(Exp), log(GP) (games played), sqrt(PTS_, +/-, log(Penalty Minutes) (PIM), and Average Time on Ice (ATOI_min).
NOTE Log of Games Played is still not normally distributed, highly skewed left, with the curve not coming all the way down, but at least it is no longer nearly linear
My model only explains 39.46% of the variation in GamesMissed, so it is not a very good model.
Based on NationalityCA being in the intercept and all the other nationalities having negative coefficents, Canadians had the most severe injuries. I highly doubt Canadians actually get injured more severely; this probably due to Canada and the US having the highest numbers of players in the league. (While three of the four players who don’t wear visors are Canadian, none of them got head injuries in 2025)
Visualizations
Count the number of each injury group for 2006 and 2025 seasons
p1 <- groupcount |>ggplot((aes(reorder(injurygroup,n), n, fill = Season))) +geom_col() +labs(title ="Injuries* by Body Part Area",#subtitle = "*that required absence from 1+ games",x ="Injury Body Area",y ="Count",fill ="Season") +scale_fill_manual(values =c("#b4d4ed","#83b6de")) +theme_bw()
p2 <- headcount |>ggplot((aes(reorder(InjuryType, n),n , fill = Season))) +geom_col() +coord_flip() +labs(title ="Head Injuries* to NHL Players in 2006 & 2025",#subtitle = "*that required absence from 1+ games",x ="Injury", y ="Count",fill ="Season")+# using a joint caption belowscale_fill_manual(values =c("#b4d4ed","#83b6de")) +theme_bw()
p1 + p2 +plot_layout(guides ="collect") +plot_annotation(title ="Injuries* to NHL Players in 2005-2006 & 2024-2025",subtitle ="*that required absence from 1+ games",caption ="Source: puckpedia.com, cbssports.com, the former capfriendly.com, tsn.ca, and sportsforcaster.com")
# plot_layout shares the legends, plot_annotation gives collective title and caption
The first chart shows that injuries in general have decreased in the 2024-2025 season compared to 2005-2006. Upper body injuries stayed about the same, and “other” increased, but as “other” includes illness, that category is not as useful.
The head injuries chart shows nearly all types of head injuries have decreased! Concussions and eye injuries in particular have a noticeable drop off. This is consistent with the research by Benson in youth and collegiate hockey. It is notable that “Facial” injuries look to be about equal between the two seasons, along with “jaw” injuries – the jaw is not covered by the visor. “Facial” can include parts parts of the face that both are and are not covered by the visor.
Vizualization 2:
highchart() |>hc_add_series(headjoin,type ="scatter",hcaes(x ="ATOI_min",y ="GamesMissed",group ="Season"))|>hc_colors(c("#b4d4ed","#83b6de")) |>hc_add_theme(hc_theme_handdrawn()) |>hc_title(text ="Games Missed for Head Injuries vs Average Time on Ice\n 2006 and 2025") |>hc_xAxis(title=list(text="Average Time on Ice (minutes)")) |>hc_yAxis(title =list(text="Games Missed due to Injury")) |>hc_caption(text ="Source: puckpedia.com, cbssports.com, the former capfriendly.com, tsn.ca, and sportsforcaster.com, and sportsradar", align ="right") |>hc_legend(align ="right", verticalAlign ="top") |>hc_tooltip(pointFormat ="<b>{point.fullname}</b>, {point.Pos} <br> {point.Team}, {point.Season} <br> <b>Injury</b>: {point.InjuryType}<br> <b>ATOI: </b> {point.ATOI} mm:ss <br> <b>Games Missed:</b> {point.GamesMissed} <b> Games Played:</b> {point.GP}")
This graph shows Games missed due to head injury vs Average Time on Ice in minute. While ATOI_min was taken out of my linear model, I was interested in which players were getting injured, and ATOI can be a proxy for how good a player is, as the better players play more per game. As taking ATOI_min out of the linear model showed, there is no connection between player quality and severity of injury, but it is interesting to note that the severity has gone down for 2025.
I took advantage of highcharter’s interactive tooltips to have the mouseover display the player’s name, position (the more detailed one from the roster), team and injury year, as well as ATOI (in the original mm:ss for readability), games missed, and games played.
References
Benson, B. W., et al. “The Impact of Face Shield Use on Concussions in Ice Hockey: A Multivariate Analysis.” British Journal of Sports Medicine, vol. 36, no. 1, Feb. 2002, pp. 27–32. Original Articles. bjsm.bmj.com, https://doi.org/10.1136/bjsm.36.1.27.
CBC. “Use of Visors in NHL on the Rise: Report.” CBC Sports, 18 Oct. 2005. CBC.ca, https://www.cbc.ca/sports/hockey/use-of-visors-in-nhl-on-the-rise-report-1.528068.
Halford, Mike. “NHL Makes Visors Mandatory for New Players.” NBC Sports, 4 June 2013, https://www.nbcsports.com/nhl/news/nhl-makes-visors-mandatory-for-new-players.
Johnston, Chris. “Why 4 NHL Players Still Don’t Wear Visors, and Who Will Be the Last Standing?” The New York Times, 13 Mar. 2026. NYTimes.com, https://www.nytimes.com/athletic/7108800/2026/03/12/nhl-players-visor-holdouts/.
Press, Associated. “Avs Star MacKinnon Bloodied after Puck to Face from Teammate.” ESPN.Com, 12 May 2026, https://www.espn.com/nhl/story/_/id/48746176/avs-star-mackinnon-bloodied-puck-face-teammate.