Introduction
This vignette demonstrates how to create rich MBB (Men’s College Basketball) visualizations by combining hoopR for player and team data and sdvplotR for team logos, headshots, colors, and gt tables.
Loading MBB Data
Use hoopR to load this season’s ESPN team and player box
scores:
# The last completed regular season (hoopR names a season for the year it
# ends; the regular season ends in mid-March)
season <- as.integer(format(Sys.Date(), "%Y")) -
(format(Sys.Date(), "%m-%d") < "03-20")
# One row per team per game (ESPN box scores), regular season only; Division I
# teams only (the box scores also hold their games against other divisions)
team_stats <- hoopR::load_mbb_team_box(seasons = season) |>
filter(season_type == 2, team_abbreviation %in% team_reference("mbb")$team_abbr)
# One row per player per game, with ESPN athlete IDs; players who did not
# play are dropped so games played counts real games
player_stats <- hoopR::load_mbb_player_box(seasons = season) |>
filter(season_type == 2, !did_not_play)MBB Team Performance
Visualize team performance with team logos:
# Calculate team metrics
team_perf <- team_stats |>
filter(!is.na(team_abbreviation)) |>
group_by(team_id, team_abbreviation) |>
summarise(
avg_points = mean(team_score, na.rm = TRUE),
avg_rebounds = mean(total_rebounds, na.rm = TRUE),
games = n(),
.groups = "drop"
) |>
filter(games >= 10)
ggplot(team_perf, aes(x = avg_points, y = avg_rebounds)) +
geom_sdv_logos(
aes(team = team_abbreviation),
sport = "mbb",
width = 0.075
) +
labs(
title = "MBB Team Performance",
subtitle = paste("Season", season),
x = "Average Points per Game",
y = "Average Rebounds per Game",
caption = "Data: hoopR | Viz: sdvplotR"
) +
theme_minimal()MBB Team Colors
Use team colors to visualize win percentages:
# Calculate win percentage
team_wins <- team_stats |>
filter(!is.na(team_abbreviation)) |>
group_by(team_id, team_abbreviation) |>
summarise(
wins = sum(team_winner, na.rm = TRUE),
games = n(),
.groups = "drop"
) |>
filter(games >= 10) |>
mutate(win_pct = wins / games) |>
arrange(desc(win_pct)) |>
head(25)
ggplot(team_wins, aes(x = reorder(team_abbreviation, win_pct), y = win_pct)) +
geom_col(aes(fill = team_abbreviation), width = 0.7) +
scale_fill_sdv(sport = "mbb", alpha = 0.8) +
scale_y_continuous(labels = scales::percent) +
labs(
title = "Top 25 MBB Teams by Win Percentage",
x = NULL,
y = "Win Percentage"
) +
theme_minimal() +
theme(
axis.text.x = element_text(angle = 45, hjust = 1),
legend.position = "none"
)Player Headshots
Visualize top performers with player headshots:
# Top scorers
top_scorers <- player_stats |>
filter(!is.na(athlete_id)) |>
group_by(athlete_id, athlete_display_name) |>
summarise(
avg_points = mean(points, na.rm = TRUE),
games = n(),
.groups = "drop"
) |>
filter(games >= 15) |>
arrange(desc(avg_points)) |>
head(8)
ggplot(top_scorers, aes(x = games, y = avg_points)) +
geom_sdv_headshots(
aes(player_id = athlete_id),
sport = "mbb",
height = 0.15
) +
geom_label(
aes(label = athlete_display_name),
nudge_y = -1.5,
size = 3,
alpha = 0.7
) +
labs(
title = "Top 8 MBB Scorers",
subtitle = paste("Season", season),
x = "Games Played",
y = "Average Points per Game"
) +
theme_minimal()Tournament Seeds with Logos
Plot a set of tournament seeds with team logos. These seeds are an example; swap in the real bracket once it is announced:
# For demonstration, create sample bracket data
bracket_data <- data.frame(
seed = 1:16,
team = c("HOU", "UCLA", "KANSAS", "PURDUE", "GONZAGA", "BAYLOR",
"ARIZONA", "DUKE", "CREIGHTON", "MARQUETTE", "TEXAS",
"AUBURN", "MSU", "TENN", "SDSU", "TCU")
)
ggplot(bracket_data, aes(x = seed, y = 1)) +
geom_sdv_logos(
aes(team = team),
sport = "mbb",
width = 0.075
) +
scale_x_continuous(breaks = 1:16) +
labs(
title = "NCAA Tournament Seeds",
subtitle = paste("Season", season),
x = "Seed",
y = NULL
) +
theme_minimal() +
theme(
axis.text.y = element_blank(),
panel.grid.major.y = element_blank(),
panel.grid.minor = element_blank()
)MBB Team Tiers
Create a tier plot ranking MBB teams:
# Top 25 teams by win percentage
top_25 <- team_wins |>
mutate(
tier_no = case_when(
win_pct > 0.85 ~ 1,
win_pct > 0.75 ~ 2,
win_pct > 0.65 ~ 3,
win_pct > 0.55 ~ 4,
TRUE ~ 5
)
) |>
select(tier_no, team = team_abbreviation)
sdv_team_tiers(
top_25,
sport = "mbb",
title = "MBB Power Rankings",
subtitle = paste("Example tiers,", season, "season"),
tier_desc = c(
"1" = "Elite",
"2" = "Championship Contenders",
"3" = "Top 25",
"4" = "Bubble Teams",
"5" = "Rebuilding"
),
presort = TRUE
)MBB Conference Map
Show each major conference’s teams in a column:
# The five major conferences, from the conferences sdvplotR keeps for every team
conference_map <- team_reference("mbb") |>
filter(conference %in% c("ACC", "Big 12", "Big East", "Big Ten", "SEC")) |>
arrange(conference, team_location) |>
group_by(conference) |>
mutate(team_rank = row_number()) |>
ungroup() |>
mutate(conference_num = as.numeric(factor(conference)))
ggplot(conference_map, aes(x = conference_num, y = team_rank)) +
geom_sdv_logos(
aes(team = team_abbr),
sport = "mbb",
width = 0.05
) +
scale_x_continuous(
breaks = seq_along(levels(factor(conference_map$conference))),
labels = levels(factor(conference_map$conference))
) +
scale_y_reverse() +
labs(
title = "MBB Teams in the Major Conferences",
x = NULL,
y = NULL
) +
theme_minimal() +
theme(
axis.text.y = element_blank(),
panel.grid = element_blank()
)MBB Standings Table with Logos
Create a gt table with team logos:
standings_table <- team_wins |>
head(20) |>
mutate(
logo = team_abbreviation,
rank = row_number()
) |>
select(rank, logo, team_abbreviation, wins, games, win_pct)
standings_table |>
gt() |>
gt_sdv_logos(columns = "logo", sport = "mbb", height = 30) |>
fmt_number(columns = "win_pct", decimals = 3) |>
cols_label(
rank = "#",
logo = "Team",
team_abbreviation = "Abbrev",
wins = "Wins",
games = "Games",
win_pct = "Win %"
) |>
tab_header(
title = "MBB Top 20",
subtitle = paste("Season", season)
)Axis Labels with Logos
Replace axis labels with team logos:
top_8 <- team_wins |>
head(8) |>
mutate(team_abbreviation = factor(team_abbreviation, levels = team_abbreviation))
ggplot(top_8, aes(x = team_abbreviation, y = win_pct)) +
geom_col(aes(fill = team_abbreviation), width = 0.6) +
scale_fill_sdv(sport = "mbb", alpha = 0.7) +
scale_x_sdv(sport = "mbb") +
theme_minimal() +
theme_x_sdv() +
labs(
title = "Top 8 MBB Teams by Win %",
x = NULL,
y = "Win Percentage"
) +
theme(legend.position = "none")Next Steps
- Explore hoopR documentation
- Combine with oddsapiR for betting lines
