Skip to content

Instantly share code, notes, and snippets.

@OTStats
Created December 18, 2024 02:23
Show Gist options
  • Save OTStats/cf11d84e20afebdc746f30f4f710a95a to your computer and use it in GitHub Desktop.
Save OTStats/cf11d84e20afebdc746f30f4f710a95a to your computer and use it in GitHub Desktop.
# -- Created by Owen Thompson (@OTStats)
# 2024-12-10
# -- Load libraries
library(tidyverse)
library(ggchicklet)
library(ggtext)
# -- Load data
# Data downloaded on 12/11/24 from Moneypuck.com
df <- read_csv("Downloads/shots_2024 3.csv")
# -- Prep data
df_summary <-
df %>%
filter(isPlayoffGame == 0) %>%
group_by(game_id = str_c(season, "-", game_id)) %>%
transmute(
season,
game_id,
period,
home_team = homeTeamCode,
away_team = awayTeamCode,
home_goals = homeTeamGoals,
away_goals = awayTeamGoals,
time,
game_score = str_c(homeTeamGoals, "-", awayTeamGoals),
score_change = if_else(game_score != lag(game_score, default = "1"), 1, 0)
) %>%
ungroup() %>%
filter(score_change == 1) %>%
mutate(
lead_diff = home_goals - away_goals, # Calculate the lead difference
home_lead = lead_diff > 0,
away_lead = lead_diff < 0
) %>%
group_by(game_id) %>%
mutate(
winner = if_else(last(home_goals) > last(away_goals), "home", "away"),
home_behind = any(lag(away_lead, default = FALSE) & winner == "home"),
away_behind = any(lag(home_lead, default = FALSE) & winner == "away"),
comeback_win = case_when(
winner == "home" & home_behind ~ TRUE,
winner == "away" & away_behind ~ TRUE,
TRUE ~ FALSE
)
# max_home_lead = max(lead_diff[lead_diff > 0], na.rm = TRUE), # Greatest lead for home team
# min_home_deficit = min(lead_diff[lead_diff > 0], na.rm = TRUE), # Greatest lead for home team
# max_away_deficit = min(lead_diff[lead_diff > 0], na.rm = TRUE)*-1, # Greatest lead for home team
# max_away_lead = max(lead_diff[lead_diff > 0], na.rm = TRUE)*-1, # Greatest lead for home team
) %>%
ungroup()
# -- Table for end of the game
end_game_df <- df_summary %>%
filter(time <= 3600) %>%
group_by(game_id) %>%
filter(time == max(time)) %>%
mutate(time = 3600)
# start_game_df <- df_summary %>%
# filter(time <= 3600) %>%
# group_by(game_id) %>%
# filter(time == min(time)) %>%
# mutate(time = 0)
df_game_state_summary <-
df_summary %>%
filter(time <= 3600) %>%
bind_rows(end_game_df) %>%
arrange(game_id, time) %>%
group_by(game_id) %>%
mutate(game_score_id = row_number(), .after = "game_id") %>%
mutate(time = if_else(game_score_id == 1, 0, time), # prep time for initial 0-0
time_in_state = lead(time) - time, .after = time) %>%
ungroup()
# filter(team != c("L.A", "N.J", "S.J"))
df_prepped_for_viz <-
bind_rows(
transmute(df_game_state_summary,
team = home_team,
opponent = away_team,
game_id,
time,
time_in_state,
goals = home_goals,
opp_goals = away_goals),
transmute(df_game_state_summary,
team = away_team,
opponent = home_team,
game_id,
time,
time_in_state,
goals = away_goals,
opp_goals = home_goals)
) %>%
mutate(goal_diff = goals - opp_goals,
goal_diff_fct = case_when(goal_diff >= 3 ~ "Up 3+",
goal_diff <= -3 ~ "Dn 3+",
goal_diff == 2 ~ "Up 2",
goal_diff == 1 ~ "Up 1",
goal_diff == 0 ~ "Tied",
goal_diff == -1 ~ "Dn 1",
goal_diff == -2 ~ "Dn 2",
TRUE ~ str_c(goal_diff)
)) %>%
filter(!is.na(time_in_state)) %>%
mutate(game_state_winning = if_else((goals-opp_goals) > 0, time_in_state, 0),
team_order = fct_reorder(team, game_state_winning, .fun = sum)) %>% #filter(is.na(game_state_winning))
group_by(
# team,
team_order,
goal_diff_fct = factor(goal_diff_fct, levels = c("Dn 3+", "Dn 2", "Dn 1", "Tied", "Up 1", "Up 2", "Up 3+"))) %>%
summarize(total_time = sum(time_in_state, na.rm = TRUE),
total_time_winning = sum(game_state_winning),
.groups = 'drop') %>%
with_groups(team_order, mutate, overall_time = sum(total_time)) %>%
mutate(percent_of_time = total_time/overall_time,
game_state_winning = if_else(goal_diff_fct %in% c("Up 1", "Up 2", "Up 3+"), percent_of_time, 0),
team_order = fct_reorder(team_order, game_state_winning, .fun = sum))
df_prepped_for_viz %>%
group_by(team_order = str_c(team_order)) %>%
summarize(time_winning = sum(total_time_winning)) %>%
arrange(desc(time_winning))
# source("Downloads/add_logo.R")
# remotes::install_git("https://git.rud.is/hrbrmstr/ggchicklet.git")
# remotes::install_gitlab("hrbrmstr/ggchicklet")
# library(ggchicklet)
# library(ggtext)
df_prepped_for_viz %>%
ggplot(aes(x = team_order,
y = percent_of_time,
fill = goal_diff_fct %>% fct_rev())) +
geom_chicklet(position = ggplot2::position_stack(reverse = F)) +
geom_hline(yintercept = .25, linetype = "dashed", colour = "white") +
geom_hline(yintercept = .5, linetype = "dashed", colour = "white") +
geom_hline(yintercept = .75, linetype = "dashed", colour = "white") +
labs(fill = "",
x = "",
y = "",
caption = "Data as of 12/11/2024\nSource: Moneypuck.com\nMotivation: @owenlhjphillips",
# title = "How often are teams Up, Down, or Tied",
title = "<span style='font-size:20pt'>NHL 2024: How often are teams <span style='color:#738877;'>Up</span>,
<br><span style='color:#6A51A3;'>Down</span>, or <span style='color:#B3B3B3;'>Tied</span></span>",
subtitle = "Teams are sorted by how often they are winning") +
scale_y_continuous(
expand = c(0, 0.005),
breaks = c(0, .25, .5, .75, 1),
labels = c("0%", "25%", "50%", "75%", "100%")
) +
coord_flip() +
scale_fill_manual(values =
c(
"#475841",
"#738877",
"#9fb8ad",
"grey90",
"#DADAEB",
"#9E9AC8",
"#6A51A3"
)) +
theme(legend.position = 'top',
legend.direction = "horizontal",
legend.box = "horizontal",
legend.text = element_text(face = 'bold'),
# legend.text = element_text(hjust = 0.5)
plot.title = element_markdown(hjust =0.5, face = "bold"),
plot.subtitle = element_text(hjust = 0.5, size = 10),
axis.text.y = element_text(),
axis.ticks = element_blank(),
plot.caption = element_text(hjust = 0, color = "grey25"),
panel.background = element_blank()
# plot.title.position = "plot"
) +
guides(fill = guide_legend(nrow = 1, reverse = TRUE,
# title.position = "top",
# hjust = 0.5 #centers the title horizontally
# title.hjust = 0.5,
label.position = "top"))
# library(magick)
# -- Add Leauge logo to plot
ggsave(filename = "20241214 NHL Teams game state.png",
plot = last_plot(),
width = 6.5, height = 9, dpi = "retina")
# library(glue)
# plot_with_logo <- add_logo(plot_path = "20241211 NHL Teams game state.png",
# logo_path = glue("https://loodibee.com/wp-content/uploads/NHL-league-logo.png"),
# logo_position = "bottom right",
# logo_scale = 1000)
@OTStats
Copy link
Author

OTStats commented Dec 18, 2024

20241214 NHL Teams game state

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment