knitr::opts_chunk$set( collapse = TRUE, comment = "#>", out.width = "100%", dpi = 600 ) # Preset dataframes library(dplyr) filtered_df <- tibble::tribble( ~Team, ~ERA, ~FIP, ~HR, "ARI", 4.3, 4.25, 19, "ATL", 3.04, 3.31, 15, "BAL", 3.62, 4.62, 30, "BOS", 3.75, 2.79, 15, "CHC", 4.77, 4.89, 31, "CHW", 2.37, 2.65, 13, "CIN", 3.37, 3.97, 17, "CLE", 3.12, 4.05, 14, "COL", 4.33, 4.63, 20, "DET", 3.71, 4.71, 24, "HOU", 3.14, 4.01, 12, "KCR", 4.77, 5.6, 22, "LAA", 3.18, 3.52, 15, "LAD", 2.47, 3.16, 19, "MIA", 2.64, 2.55, 6, "MIL", 2.43, 1.63, 7, "MIN", 3.72, 4.27, 17, "NYM", 3.02, 3.49, 17, "NYY", 3.23, 2.92, 24, "OAK", 3.15, 3.34, 15, "PHI", 2.78, 2.59, 16, "PIT", 5.36, 5.16, 28, "SDP", 3.27, 3.73, 22, "SEA", 3.61, 3.89, 19, "SFG", 2.81, 3, 20, "STL", 3.05, 3.66, 21, "TBR", 3.43, 3.31, 14, "TEX", 4.55, 3.94, 12, "TOR", 2.84, 3.69, 33, "WSN", 4.02, 4.43, 17 ) top_12 <- tibble::tribble( ~playerid, ~ERA, ~FIP, 16137, 2.37, 2.65, 19361, 2.43, 1.63, 3137, 2.46, 2.97, 19374, 2.47, 3.16, 16162, 2.56, 2.96, 12703, 2.59, 4.03, 22286, 2.64, 2.55, 2520, 2.69, 3.32, 10310, 2.78, 2.59, 14107, 2.81, 3, 11486, 2.84, 3.69, 18679, 2.85, 3.14 )
The easiest way to get mlbplotR is to install it from CRAN with:
install.packages("mlbplotR")
To get a bug fix or use a feature from the development version, you can install the development version from GitHub with:
# install.packages("devtools") devtools::install_github("camdenk/mlbplotR")
Let's plot every team on a grid with some extra customization:
library(mlbplotR) library(ggplot2) library(dplyr) teams_colors_logos <- mlbplotR::load_mlb_teams() |> dplyr::filter(!team_abbr %in% c("AL", "NL", "MLB")) |> dplyr::mutate( a = rep(1:6, 5), b = sort(rep(1:5, 6), decreasing = TRUE), # Keep alpha == 1 for teams that have an "A" alpha = ifelse(grepl("A", team_abbr), 1, 0.75), # Set teams that have an "E" to black & white color = ifelse(grepl("E", team_abbr), "b/w", NA) ) ggplot2::ggplot(teams_colors_logos, aes(x = a, y = b)) + mlbplotR::geom_mlb_logos(aes(team_abbr = team_abbr, color = color, alpha = alpha), width = 0.075) + ggplot2::geom_label(aes(label = team_abbr), nudge_y = -0.35, alpha = 0.5) + ggplot2::scale_color_identity() + ggplot2::scale_alpha_identity() + ggplot2::theme_void()
This is a basic example with FanGraphs data (pulled using baseballr) which compares ERA to FIP for each team's top starting pitcher by ERA:
# Uncomment this to pull data, currently commented out to save # a dependency on baseballr # # library(baseballr) # # df <- baseballr::fg_pitcher_leaders(x = 2021, y = 2021, # q = 100, pitcher_type = "sta") # # filtered_df <- df |> # dplyr::filter(Team != "- - -") |> # # FanGraphs Team abbreviations aren't the standard # # for what's used in the plotting functions so # # you could clean them with the following line, # # but the geom_*_logos() functions should all # # clean the abbreviations before plotting # # # # dplyr::mutate(Team = clean_team_abbrs(Team)) |> # dplyr::group_by(Team) |> # dplyr::slice_min(ERA, n = 1) |> # dplyr::ungroup() library(scales) filtered_df |> ggplot2::ggplot(aes(x = ERA, y = FIP)) + mlbplotR::geom_mlb_logos(aes(team_abbr = Team), width = 0.075, alpha = 0.7) + ggplot2::labs(title = "2021: ERA vs. FIP", subtitle = "Each Team's Top Starter By ERA | Min. 100 IP", caption = "Data: FanGraphs via baseballr") + ggplot2::theme_minimal() + ggplot2::theme(plot.title = ggplot2::element_text(face = "bold")) + ggplot2::scale_x_reverse(breaks = scales::pretty_breaks(), labels = scales::number_format(accuracy = 0.01), expand = c(.1, .1)) + ggplot2::scale_y_reverse(breaks = scales::pretty_breaks(), labels = scales::number_format(accuracy = 0.01), expand = c(.1, .1))
Here's another that looks at Home Runs Allowed by top pitchers:
filtered_df |> # The scale_*_mlb() functions don't auto-clean abbreviations dplyr::mutate(Team = clean_team_abbrs(Team)) |> ggplot2::ggplot(aes(x = Team, y = HR)) + ggplot2::geom_col(aes(color = Team, fill = Team), width = 0.5) + mlbplotR::geom_mlb_logos(aes(team_abbr = Team), width = 0.07, alpha = 0.9) + mlbplotR::scale_color_mlb(type = "secondary") + mlbplotR::scale_fill_mlb(alpha = 0.4) + ggplot2::labs(title = "2021: Home Runs Allowed For Top Pitchers", subtitle = "HRs Allowed By Each Team's Top Starter By ERA | Min. 100 IP", caption = "Data: FanGraphs via baseballr") + ggplot2::theme_minimal() + ggplot2::theme(plot.title = ggplot2::element_text(face = "bold"), axis.title.x = ggplot2::element_blank(), axis.text.x = ggplot2::element_blank(), panel.grid.major.x = element_blank()) + ggplot2::scale_x_discrete(expand = c(0.05, 0.075))
Instead of putting the logos in the plot, we can have them be the axis labels:
filtered_df |> # The scale_*_mlb() functions don't auto-clean abbreviations dplyr::mutate(Team = clean_team_abbrs(Team)) |> ggplot2::ggplot(aes(x = Team, y = HR)) + ggplot2::geom_col(aes(color = Team, fill = Team), width = 0.5) + #mlbplotR::geom_mlb_logos(aes(team_abbr = Team), width = 0.07, alpha = 0.9) + mlbplotR::scale_color_mlb(type = "secondary") + mlbplotR::scale_fill_mlb(alpha = 0.4) + ggplot2::labs(title = "2021: Home Runs Allowed", subtitle = "HRs Allowed By Each Team's Top Starter By ERA | Min. 100 IP", caption = "Data: FanGraphs via baseballr") + ggplot2::theme_minimal() + ggplot2::theme(plot.title = ggplot2::element_text(face = "bold"), axis.title.x = ggplot2::element_blank(), panel.grid.major.x = ggplot2::element_blank(), # this line triggers the replacement of team abbreviations with logos axis.text.x = mlbplotR::element_mlb_logo()) + ggplot2::scale_x_discrete(expand = c(0.05, 0.075)) + ggplot2::scale_y_continuous(expand = c(0, 0, 0.05, 0))
The family of element_*()
functions allows for a lot of extra customization with axes labels and can even be used for facet_wrap()/facet_grid()
strip headers.
Lastly, here's an example using headshots:
# top_12 <- df |> # dplyr::mutate(playerid = as.double(playerid)) |> # dplyr::slice_min(ERA, n = 12) top_12 |> dplyr::left_join(mlbplotR::load_headshots(), by = c("playerid" = "fangraphs_id")) |> ggplot(aes(x = ERA, y = FIP)) + mlbplotR::geom_mlb_headshots(aes(player_id = savant_id), height = 0.15) + ggplot2::scale_x_reverse(breaks = scales::pretty_breaks(), labels = scales::number_format(accuracy = 0.01), expand = c(.1, .1)) + ggplot2::scale_y_reverse(breaks = scales::pretty_breaks(), labels = scales::number_format(accuracy = 0.01), expand = c(.1, .1)) + ggplot2::labs(title = "2021 SP ERA Leaders", subtitle = "Minimum 100 IP", caption = "Data: FanGraphs via baseballr") + ggplot2::theme_minimal() + ggplot2::theme(plot.title = ggplot2::element_text(face = "bold"))
Note: If a player's headshot data can't be found, their headshot will be replaced with the MLB logo by default.
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.