NHL API: Get Year-By-Year Stats

 

Introduction

The NHL has a publicly accessible Application Programming Interface (or API) that allows users to obtain a lot of useful data (including detailed play-by-play data). There are a couple of obstacles though: 1) the NHL API does not come with a user manual; and 2) the NHL API is most easily accessed using a programming language such as R or Python. To help you overcome those obstacles I’m writing articles that provide the code (in the R programming language) for functions that pull data from the NHL API.

In this article I provide a function that pulls a skater’s yearly stats for the NHL. The function also pulls stats for other leagues (such as the AHL) to the extent those stats are available.

The Data

Before I provide the code, here’s a sample of the data. Note: I included the stats for only one season in this sample. The function pulls these same stats for every year that they’re available.

player_id: 8478402

player: Connor McDavid

season: 20222023

league_id: 133

league: National Hockey League

team_id: 22

team: Edmonton Oilers

gp: 82

toi_as: 110137

toi_es: 84569

toi_pp: 19313

toi_sh: 6255

goals: 64

assists: 89

points: 153

shots: 352

hits: 89

blocks: 40

pim: 36

goals_es: 39

goals_pp: 21

goals_sh: 4

goals_ot: 2

assists_es: 36

assists_pp: 50

assists_sh: 3

points_pp: 71

points_sh: 7

shooting_pct: 18.2

face_off_pct: 51.93

plus_minus: 22


The Code

Here’s the code for the function that pulls the above data.

# This function pulls a player's yearly stats (including pre-NHL stats)
# Results for more than one team per season are returned on separate rows
# SKATERS ONLY
# PLAYOFFS ARE EXCLUDED
# Time-on-ice data is returned as seconds
# Use my get_team_rosters() function to find player_ids
# Wrap this function in a loop to pull data for multiple players at the same time (see EXAMPLE on GitHub)

get_year_by_year_stats <- function(player_id) {
        
        # Get the player's full name
        
        player_site <- read_json(paste0("https://statsapi.web.nhl.com/api/v1/people/", player_id))
        player_name <- player_site$people %>%
                tibble() %>%
                unnest_wider(1)
        player_name <- player_name$fullName
        
        # Pull and organize the raw data
        
        yby_site <- read_json(paste0("https://statsapi.web.nhl.com/api/v1/people/", player_id, "/stats/?stats=yearByYear"))
        
        stats <- yby_site$stats %>%
                tibble() %>%
                unnest_wider(1) 
        stats <- stats$splits %>%
                tibble() %>%
                unnest(1) %>%
                unnest_wider(1) %>%
                unnest_wider(stat) %>%
                unnest_wider(team, names_sep = "_") %>%
                unnest_wider(league, names_sep = "_")
                
        # Add player data
        
        stats <- mutate(stats, player_id = player_id,
                        player = player_name)
        
        # Add special teams assists data
        
        stats <- mutate(stats, assists_pp = powerPlayPoints - powerPlayGoals,
                        assists_sh = shortHandedPoints - shortHandedGoals)
        
        # Add even strength scoring data
        
        stats <- mutate(stats, goals_es = goals - (powerPlayGoals + shortHandedGoals), 
                        assists_es = assists - (assists_pp + assists_sh))
        
        # Select the data to be returned by the function
        
        stats <- select(stats, player_id,
                        player,
                        season,
                        league_id,
                        league = league_name,
                        team_id,
                        team = team_name,
                        gp = games, 
                        toi_as = timeOnIce, 
                        toi_es = evenTimeOnIce, 
                        toi_pp = powerPlayTimeOnIce, 
                        toi_sh = shortHandedTimeOnIce, 
                        goals, 
                        assists,
                        points,
                        shots, 
                        hits, 
                        blocks = blocked, 
                        pim, 
                        goals_es, 
                        goals_pp = powerPlayGoals, 
                        goals_sh = shortHandedGoals, 
                        goals_ot = overTimeGoals, 
                        assists_es, 
                        assists_pp, 
                        assists_sh,
                        points_pp = powerPlayPoints,
                        points_sh = shortHandedPoints,
                        shooting_pct = shotPct,
                        face_off_pct = faceOffPct,
                        plus_minus = plusMinus)
        
        # Final clean up for time
        
        stats$toi_as <- ms(stats$toi_as, quiet = TRUE)
        stats$toi_as <- period_to_seconds(stats$toi_as)
        stats$toi_es <- ms(stats$toi_es, quiet = TRUE)
        stats$toi_es <- period_to_seconds(stats$toi_es)
        stats$toi_pp <- ms(stats$toi_pp, quiet = TRUE)
        stats$toi_pp <- period_to_seconds(stats$toi_pp)
        stats$toi_sh <- ms(stats$toi_sh, quiet = TRUE)
        stats$toi_sh <- period_to_seconds(stats$toi_sh)
        
        stats <- arrange(stats, desc(season))
        
        return(stats)
}

Get It On GitHub

I’ve created a public repository on GitHub where I’ll be sharing my functions for accessing the NHL’s API. You can go to the repository by clicking here.

The End Of The Article

That’s the end of this article. Follow me on twitter to be notified about new content.

Cheers,

Mark (18 Skaters)