Animated Bar Plot for NBA Standing
Inspired by the viral animated bar plot, I plan to implement the idea on NBA standing so that we can have an idea how the teams behavior through out the whole season. special thanks to the two blogs by Michael and Abdul for instructions how to make animated bar plots using R, ggplot2, and package gganimate.
Data Preparation
First we need to load three great R packages:
library(tidyverse)
library(nbastatR)
library(gganimate)
Package tidyverse is for data manipulation; nbastatR is a great package using NBA Stats API Wrapper; gganimate is to make animated plots.
Get Team Color
Next step, I am going to use the nba_teams()
function to get the team
information along with their main color.
nba_team = nba_teams()
nba_team %>%
filter(isNonNBATeam == 0) %>%
select(cityTeam, hexColor1) -> teamcolor
head(teamcolor)
## # A tibble: 6 x 2
## cityTeam hexColor1
## <chr> <chr>
## 1 Washington #002B5C
## 2 Utah #002B5C
## 3 Toronto #CE1141
## 4 San Antonio #C4CED4
## 5 Sacramento #5A2D81
## 6 Portland #E03A3E
Then make it a named list:
colorlist = as.character(teamcolor$hexColor1)
teamname2 = teamcolor$cityTeam
teamname2 = replace(teamname2, teamname2=='Los Angeles', 'L.A. Lakers')
teamname2 = replace(teamname2, teamname2=='LA', 'LA Clippers')
names(colorlist) = teamname2
colorlist
## Washington Utah Toronto San Antonio Sacramento
## "#002B5C" "#002B5C" "#CE1141" "#C4CED4" "#5A2D81"
## Portland Phoenix Philadelphia Orlando Oklahoma City
## "#E03A3E" "#E56020" "#006BB6" "#0077C0" "#007AC1"
## New York New Orleans Minnesota Milwaukee Miami
## "#F58426" "#0C2340" "#0C2340" "#00471B" "#98002E"
## Memphis L.A. Lakers LA Clippers Indiana Houston
## "#6189B9" "#552583" "#ED174C" "#FDBB30" "#CE1141"
## Golden State Detroit Denver Dallas Cleveland
## "#FDB927" "#006BB6" "#418FDE" "#00538C" "#6F263D"
## Chicago Charlotte Brooklyn Boston Atlanta
## "#CE1141" "#00788C" "#000000" "#007A33" "#E03A3E"
Get Standing by Day
Use the function day_scores
to pull the standing information by day
and wrap up as function:
pull_east_standing = function(date){
days_scores(game_dates = date,
include_standings = T, return_message = F)
dataScoreEastConfStandingsByDayNBA
}
pull_west_standing = function(date){
days_scores(game_dates = date,
include_standings = T, return_message = F)
dataScoreWestConfStandingsByDayNBA
}
Wrap up and Plot
gif_standing = function(seasonyear, conf){
# get season info start date and end date
season = seasons_schedule(seasons = seasonyear)
datelist = unique(season %>% select(dateGame))
# get season standing by day
if (conf == 'East') {
standing_day = datelist %>% map_dfr(pull_east_standing)
} else if (conf == 'West') {
standing_day = datelist %>% map_dfr(pull_west_standing)
}
# add rank per day
standing_day %>%
group_by(dateGame) %>%
mutate(rank = row_number(),
wl = str_c(wins, losses, sep = '-')) %>%
ungroup() -> final
# title
mytitle = str_c(conf, ' Conference Standing, ', seasonyear)
# gif
gif = final %>%
ggplot(aes(x = rank,y = pctWins, group = slugTeam)) +
geom_tile(aes(y = pctWins/2, height = pctWins, fill = slugTeam), width = 0.9) +
geom_text(aes(label = slugTeam), hjust = "right", colour = "black", fontface = "bold", nudge_y = -0.02) +
geom_text(aes(label = wl), hjust = "left", nudge_y = .01, colour = "grey30") +
coord_flip(clip="off") +
scale_fill_manual(name = 'Team', values = colorlist) +
scale_x_reverse("", breaks = 1:15) +
scale_y_continuous(limits = c(0, 1), "Win Rate") +
geom_vline(xintercept = 8.5) +
#hrbrthemes::theme_ipsum(plot_title_size = 32, subtitle_size = 24, caption_size = 20, base_size = 20) +
theme(panel.grid.major.y=element_blank(),
panel.grid.minor.x=element_blank()) +
# gganimate code to transition by date:
transition_time(dateGame) +
ease_aes('cubic-in-out') +
labs(title=mytitle,
subtitle='Date: {round(frame_time,0)}',
caption='Source: NBA Stat
Minzhao Liu')
}
Make Gif and MP4
gif_2019e = gif_standing(2019, 'East')
gif_2019w = gif_standing(2019, 'West')
animate(gif_2019e, duration = 60, fps = 20, width = 1200, height = 1000, end_pause = 30,
renderer = gifski_renderer("gganim_2019e.gif"))
animate(gif_2019w, duration = 60, fps = 30, width = 1200, height = 1000,
end_pause = 30, renderer = gifski_renderer("gganim_2019w.gif"))
# For MP4
animate(gif_2019w, duration = 60, fps = 30, width = 1200, height = 1000, end_pause = 30,
renderer = ffmpeg_renderer()) -> for_mp4
anim_save("animation_2019w.mp4", animation = for_mp4 )
Results
View post on imgur.com