Created
December 18, 2024 02:23
-
-
Save OTStats/cf11d84e20afebdc746f30f4f710a95a to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# -- 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) | |
Author
OTStats
commented
Dec 18, 2024
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment