├── .Rbuildignore ├── .github ├── .gitignore └── workflows │ ├── R-CMD-check.yaml │ └── pkgdown.yaml ├── .gitignore ├── DESCRIPTION ├── LICENSE ├── LICENSE.md ├── NAMESPACE ├── NEWS.md ├── R ├── build_grobs.R ├── geom_cap_logos.R ├── geom_from_path.R ├── geom_lines.R ├── geom_milb_logos.R ├── geom_mlb_headshots.R ├── geom_mlb_logos.R ├── ggpreview.R ├── gt_helpers.R ├── load_data.R ├── mlb_team_factors.R ├── mlb_tier_maker.R ├── mlbplotR-package.R ├── scale_mlb.R ├── sysdata.rda ├── theme_elements.R ├── theme_mlb.R └── utils.R ├── README.Rmd ├── README.md ├── _pkgdown.yml ├── cran-comments.md ├── data-raw ├── .gitignore ├── MLB_Colors_Logos.csv ├── build_internal_data.R ├── build_logo.R ├── generate_headshot_rds.R ├── logo.png ├── old_data │ ├── old_logo_lists.rds │ └── saving_internal_data_from_previous_version.R └── preview logo.png ├── man ├── clean_team_abbrs.Rd ├── element.Rd ├── figures │ ├── README-every-team-1.png │ ├── lifecycle-archived.svg │ ├── lifecycle-defunct.svg │ ├── lifecycle-deprecated.svg │ ├── lifecycle-experimental.svg │ ├── lifecycle-maturing.svg │ ├── lifecycle-questioning.svg │ ├── lifecycle-stable.svg │ ├── lifecycle-superseded.svg │ └── logo.png ├── geom_cap_logos.Rd ├── geom_from_path.Rd ├── geom_lines.Rd ├── geom_milb_logos.Rd ├── geom_mlb_headshots.Rd ├── geom_mlb_logos.Rd ├── ggpreview.Rd ├── gt_merge_stack_team_color.Rd ├── gt_milb.Rd ├── gt_mlb.Rd ├── gt_mlb_column_labels.Rd ├── gt_mlb_headshots.Rd ├── load_headshots.Rd ├── load_milb_teams.Rd ├── load_mlb_teams.Rd ├── mlb_player_tiers.Rd ├── mlb_team_factor.Rd ├── mlb_team_tiers.Rd ├── mlbplotR-package.Rd ├── scale_axes_mlb.Rd ├── scale_mlb.Rd ├── theme_mlb.Rd └── valid_team_names.Rd ├── mlbplotR.Rproj ├── pkgdown └── favicon │ ├── apple-touch-icon-120x120.png │ ├── apple-touch-icon-152x152.png │ ├── apple-touch-icon-180x180.png │ ├── apple-touch-icon-60x60.png │ ├── apple-touch-icon-76x76.png │ ├── apple-touch-icon.png │ ├── favicon-16x16.png │ ├── favicon-32x32.png │ └── favicon.ico ├── revdep ├── .gitignore ├── README.md ├── cran.md ├── email.yml ├── failures.md └── problems.md └── vignettes └── articles ├── man └── figures │ ├── README-axis-example-1.png │ ├── README-bar-example-1.png │ ├── README-every-team-1.png │ ├── README-headshot-example-1.png │ └── README-scatter-example-1.png └── mlbplotR.Rmd /.Rbuildignore: -------------------------------------------------------------------------------- 1 | ^.*\.Rproj$ 2 | ^\.Rproj\.user$ 3 | ^LICENSE\.md$ 4 | ^README\.Rmd$ 5 | ^data-raw$ 6 | ^_pkgdown\.yml$ 7 | ^docs$ 8 | ^pkgdown$ 9 | ^\.github$ 10 | ^vignettes/articles$ 11 | ^cran-comments\.md$ 12 | ^CRAN-SUBMISSION$ 13 | ^revdep$ 14 | -------------------------------------------------------------------------------- /.github/.gitignore: -------------------------------------------------------------------------------- 1 | *.html 2 | -------------------------------------------------------------------------------- /.github/workflows/R-CMD-check.yaml: -------------------------------------------------------------------------------- 1 | # Workflow derived from https://github.com/r-lib/actions/tree/v2/examples 2 | # Need help debugging build failures? Start at https://github.com/r-lib/actions#where-to-find-help 3 | on: 4 | push: 5 | branches: [main, master] 6 | pull_request: 7 | branches: [main, master] 8 | 9 | name: R-CMD-check 10 | 11 | jobs: 12 | R-CMD-check: 13 | runs-on: ${{ matrix.config.os }} 14 | 15 | name: ${{ matrix.config.os }} (${{ matrix.config.r }}) 16 | 17 | strategy: 18 | fail-fast: false 19 | matrix: 20 | config: 21 | - {os: macos-latest, r: 'release'} 22 | - {os: windows-latest, r: 'release'} 23 | - {os: ubuntu-latest, r: 'devel', http-user-agent: 'release'} 24 | - {os: ubuntu-latest, r: 'release'} 25 | - {os: ubuntu-latest, r: 'oldrel-1'} 26 | 27 | env: 28 | GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} 29 | R_KEEP_PKG_SOURCE: yes 30 | 31 | steps: 32 | - uses: actions/checkout@v3 33 | 34 | - uses: r-lib/actions/setup-pandoc@v2 35 | 36 | - uses: r-lib/actions/setup-r@v2 37 | with: 38 | r-version: ${{ matrix.config.r }} 39 | http-user-agent: ${{ matrix.config.http-user-agent }} 40 | use-public-rspm: true 41 | 42 | - uses: r-lib/actions/setup-r-dependencies@v2 43 | with: 44 | extra-packages: any::rcmdcheck 45 | needs: check 46 | 47 | - uses: r-lib/actions/check-r-package@v2 48 | with: 49 | upload-snapshots: true 50 | -------------------------------------------------------------------------------- /.github/workflows/pkgdown.yaml: -------------------------------------------------------------------------------- 1 | # Workflow derived from https://github.com/r-lib/actions/tree/v2/examples 2 | # Need help debugging build failures? Start at https://github.com/r-lib/actions#where-to-find-help 3 | on: 4 | push: 5 | branches: [main, master] 6 | pull_request: 7 | branches: [main, master] 8 | release: 9 | types: [published] 10 | workflow_dispatch: 11 | 12 | name: pkgdown 13 | 14 | jobs: 15 | pkgdown: 16 | runs-on: ubuntu-latest 17 | # Only restrict concurrency for non-PR jobs 18 | concurrency: 19 | group: pkgdown-${{ github.event_name != 'pull_request' || github.run_id }} 20 | env: 21 | GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} 22 | steps: 23 | - uses: actions/checkout@v2 24 | 25 | - uses: r-lib/actions/setup-pandoc@v2 26 | 27 | - uses: r-lib/actions/setup-r@v2 28 | with: 29 | use-public-rspm: true 30 | 31 | - uses: r-lib/actions/setup-r-dependencies@v2 32 | with: 33 | extra-packages: any::pkgdown, local::., any::XML 34 | needs: website 35 | 36 | - name: Build site 37 | run: pkgdown::build_site_github_pages(new_process = FALSE, install = FALSE) 38 | shell: Rscript {0} 39 | 40 | - name: Deploy to GitHub pages 🚀 41 | if: github.event_name != 'pull_request' 42 | uses: JamesIves/github-pages-deploy-action@4.1.4 43 | with: 44 | clean: false 45 | branch: gh-pages 46 | folder: docs 47 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .Rproj.user 2 | .Rhistory 3 | .RData 4 | .Ruserdata 5 | .DS_Store 6 | docs 7 | -------------------------------------------------------------------------------- /DESCRIPTION: -------------------------------------------------------------------------------- 1 | Package: mlbplotR 2 | Type: Package 3 | Title: Create 'ggplot2' and 'gt' Visuals with Major League Baseball Logos 4 | Version: 1.1.0.9008 5 | Authors@R: 6 | c( 7 | person(given = "Sebastian", 8 | family = "Carl", 9 | role = c("aut"), 10 | email = "mrcaseb@gmail.com"), 11 | person(given = "Camden", 12 | family = "Kay", 13 | role = c("aut", "cre", "cph"), 14 | email = "camden.kay23@gmail.com") 15 | ) 16 | Description: Tools to help visualize Major League Baseball analysis in 'ggplot2' 17 | and 'gt'. You provide team/player information and 'mlbplotR' will transform 18 | that information into team colors, logos, or player headshots for graphics. 19 | URL: https://github.com/camdenk/mlbplotR, 20 | https://camdenk.github.io/mlbplotR/ 21 | BugReports: https://github.com/camdenk/mlbplotR/issues 22 | Imports: 23 | cli, 24 | data.table, 25 | ggplot2, 26 | gt, 27 | lifecycle, 28 | magick, 29 | magrittr, 30 | rlang, 31 | scales 32 | Suggests: 33 | base64enc, 34 | dplyr, 35 | ggtext, 36 | gridtext, 37 | knitr, 38 | rsvg, 39 | rmarkdown, 40 | rstudioapi, 41 | sjmisc 42 | Encoding: UTF-8 43 | LazyData: true 44 | License: MIT + file LICENSE 45 | Roxygen: list(markdown = TRUE) 46 | RoxygenNote: 7.3.2 47 | Depends: 48 | R (>= 3.5.0) 49 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | YEAR: 2022 2 | COPYRIGHT HOLDER: mlbplotR authors 3 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | # MIT License 2 | 3 | Copyright (c) 2022 mlbplotR authors 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /NAMESPACE: -------------------------------------------------------------------------------- 1 | # Generated by roxygen2: do not edit by hand 2 | 3 | S3method(element_grob,element_milb_dot_headshot) 4 | S3method(element_grob,element_milb_dot_logo) 5 | S3method(element_grob,element_milb_light_cap_logo) 6 | S3method(element_grob,element_milb_logo) 7 | S3method(element_grob,element_mlb_dark_cap_logo) 8 | S3method(element_grob,element_mlb_dot_headshot) 9 | S3method(element_grob,element_mlb_dot_logo) 10 | S3method(element_grob,element_mlb_headshot) 11 | S3method(element_grob,element_mlb_light_cap_logo) 12 | S3method(element_grob,element_mlb_logo) 13 | S3method(element_grob,element_mlb_scoreboard_logo) 14 | S3method(element_grob,element_path) 15 | S3method(grobHeight,axisImageGrob) 16 | S3method(grobWidth,axisImageGrob) 17 | export(GeomFromPath) 18 | export(GeomMLBdarkcaplogo) 19 | export(GeomMLBdotheads) 20 | export(GeomMLBdotlogo) 21 | export(GeomMLBheads) 22 | export(GeomMLBlightcaplogo) 23 | export(GeomMLBlogo) 24 | export(GeomMLBscoreboardlogo) 25 | export(GeomMiLBdotheads) 26 | export(GeomMiLBdotlogo) 27 | export(GeomMiLBlightcaplogo) 28 | export(GeomMiLBlogo) 29 | export(GeomRefLines) 30 | export(clean_team_abbrs) 31 | export(element_milb_dot_headshot) 32 | export(element_milb_dot_logo) 33 | export(element_milb_light_cap_logo) 34 | export(element_milb_logo) 35 | export(element_mlb_dark_cap_logo) 36 | export(element_mlb_dot_headshot) 37 | export(element_mlb_dot_logo) 38 | export(element_mlb_headshot) 39 | export(element_mlb_light_cap_logo) 40 | export(element_mlb_logo) 41 | export(element_mlb_scoreboard_logo) 42 | export(element_path) 43 | export(geom_from_path) 44 | export(geom_mean_lines) 45 | export(geom_median_lines) 46 | export(geom_milb_dot_headshots) 47 | export(geom_milb_dot_logos) 48 | export(geom_milb_light_cap_logos) 49 | export(geom_milb_logos) 50 | export(geom_mlb_dark_cap_logos) 51 | export(geom_mlb_dot_headshots) 52 | export(geom_mlb_dot_logos) 53 | export(geom_mlb_headshots) 54 | export(geom_mlb_light_cap_logos) 55 | export(geom_mlb_logos) 56 | export(geom_mlb_scoreboard_logos) 57 | export(ggpreview) 58 | export(gt_fmt_milb_dot_headshot) 59 | export(gt_fmt_milb_dot_logo) 60 | export(gt_fmt_milb_logo) 61 | export(gt_fmt_mlb_dot_headshot) 62 | export(gt_fmt_mlb_dot_logo) 63 | export(gt_fmt_mlb_headshot) 64 | export(gt_fmt_mlb_logo) 65 | export(gt_fmt_mlb_scoreboard_logo) 66 | export(gt_merge_stack_team_color) 67 | export(gt_mlb_column_labels) 68 | export(load_headshots) 69 | export(load_milb_teams) 70 | export(load_mlb_teams) 71 | export(mlb_player_tiers) 72 | export(mlb_team_factor) 73 | export(mlb_team_tiers) 74 | export(scale_color_mlb) 75 | export(scale_colour_mlb) 76 | export(scale_fill_mlb) 77 | export(scale_x_mlb) 78 | export(scale_y_mlb) 79 | export(theme_x_mlb) 80 | export(theme_y_mlb) 81 | export(valid_team_names) 82 | import(grid) 83 | importFrom(data.table,fread) 84 | importFrom(ggplot2,element_grob) 85 | importFrom(lifecycle,deprecated) 86 | importFrom(magrittr,"%>%") 87 | importFrom(rlang,"%||%") 88 | importFrom(rlang,.data) 89 | -------------------------------------------------------------------------------- /NEWS.md: -------------------------------------------------------------------------------- 1 | # mlbplotR (development version) 2 | 3 | * Add `load_milb_teams()` with Minor League data (v1.1.0.9001) 4 | * Added ability to use dot headshots with `geom_mlb_dot_headshots()`, `gt_fmt_mlb_dot_headshot()`, and extra functionality within preexisting functions (v1.1.0.9002) 5 | * Update AZ logos and team colors (v1.1.0.9003) 6 | * Update `gt_*` functions to be used in gt row group labels and accept unquoted column names, add `gt_fmt_milb_logo()` (v1.1.0.9004) 7 | * Add `gt_` and `geom_` functions for MiLB dot team logos and headshots (v1.1.0.9005) 8 | * Documentation updates (v1.1.0.9006) 9 | * Added "ATH" -> "OAK" in `clean_team_abbrs()` (v1.1.0.9007) 10 | * Flipped "OAK" -> "ATH" in `clean_team_abbrs()` and had `gt_fmt_mlb_dot_logo` return the MLB dot logo if there's a mismatch (v1.1.0.9008) 11 | 12 | # mlbplotR 1.1.0 13 | 14 | * Corrected Arizona's team abbreviation in `mlb_team_factor()` (v1.0.1.9001) 15 | * Updated Twins logo, updated Brewers Scoreboard Logo, added more names to be cleaned (ANA to LAA and LA to LAD), added new dot logos and corresponding functions (`geom_mlb_dot_logos()`, `gt_fmt_mlb_dot_logo()`, and `element_mlb_dot_logo()`) (v1.0.1.9002) 16 | * Updated `valid_team_names()` to allow for truncated outputs without league level abbreviations (v1.0.1.9003) 17 | 18 | # mlbplotR 1.0.1 19 | 20 | * Added the `geom_mlb_logos()` geom. 21 | * Added the color and fill scales `scale_color_mlb()` and `scale_fill_mlb()` along with the axis scales `scale_x_mlb()` and `scale_y_mlb()` in combination with the theme update functions `theme_x_mlb()` and `theme_y_mlb()`. Also added the ggplot2 theme-element `element_mlb_logo()` which translates MLB team abbreviations into team logos (v0.0.0.9002) 22 | * Added the `geom_mlb_headshots()` geom that plots headshots for valid MLB IDs. Along with the function `ggpreview()` which allows to preview a ggplot in it's actual dimensions. (v0.0.0.9003) 23 | * Added the ggplot2 theme-element `element_mlb_headshot()` and which translates player IDs into player headshots. (v0.0.0.9004) 24 | * Added the function `ggpreview()` which allows to preview a ggplot in it's actual dimensions. (v0.0.0.9005) 25 | * Added the `geom_from_path()` geom that plots images from urls, local paths, and more. Also added `element_path()` which translates supplied links into images for axes labeling (v0.0.0.9006) 26 | * Added the `geom_mlb_scoreboard_logos()`, `geom_mlb_dark_cap_logos()`, `geom_mlb_light_cap_logos()` geoms which translate MLB team abbreviations into team logos. Also added corresponding element functions (`element_mlb_scoreboard_logo()`, `element_mlb_dark_cap_logo()`, `element_mlb_light_cap_logo()`) which translates supplied abbreviations into images for theming. Also updated function parameter names. (v0.0.0.9007) 27 | * Added the `load_headshots()` function to the exported functions. (v0.0.0.9008) 28 | * Added the `clean_team_abbrs()` function and implemented it with proper geoms. (v0.0.0.9009) 29 | * Added the `gt_fmt_mlb_logo()`, `gt_fmt_mlb_scoreboard_logo()`, `gt_fmt_mlb_headshot()` and `gt_merge_stack_team_color()` functions to aid in making gt tables. (v0.0.0.9010) 30 | * Updated internal data to use "AZ" as Diamondbacks new team abbreviation. (v0.0.0.9011) 31 | * Removed `glue` dependency, updated "Getting Started" vignette, and set `scale_x_mlb()`, `scale_y_mlb()`, `theme_x_mlb()`, and `theme_y_mlb()` as superseded (v0.0.0.9012) 32 | * Updated gt helper functions to prepare for an eventual CRAN submission (v0.0.0.9013) 33 | * Updated `na_headshot()`, `gt_fmt_mlb_headshot()`, and `geom_mlb_headshots()` to allow for use of a general gray headshot instead of just returning the MLB logo (v0.0.0.9014) 34 | * Added `gt_mlb_column_labels()` to easily replace column labels with images (v0.0.0.9015) 35 | * Reworked `gt_mlb_column_labels()` to more cleanly accept customization (v0.0.0.9016) 36 | * Added `mlb_team_tiers()` and `mlb_player_tiers()` (v0.0.0.9017) 37 | * Added `mlb_team_factor()` (v0.0.0.9018) 38 | * Added `geom_mean_lines()` and `geom_median_lines()` (v0.0.0.9019) 39 | * Added ability to use `nudge_x` and `nudge_y` to the geom family of functions and cleaned up documentation to prepare for CRAN release (v0.0.0.9020) 40 | -------------------------------------------------------------------------------- /R/build_grobs.R: -------------------------------------------------------------------------------- 1 | # INTERNAL HELPER THAT BUILDS THE GROBS FOR 2 | # GEOM LOGOS AND HEADSHOTS 3 | build_grobs <- function(i, alpha, colour, data, type = c("teams", "light_cap", "dark_cap", "scoreboard", "dot", "milb_logo", "milb_light_cap", "milb_dot", "logo_headshots", "gray_headshots", "dot_headshots", "milb_dot_headshots", "path")) { 4 | make_null <- FALSE 5 | type <- rlang::arg_match(type) 6 | if(type == "teams") { 7 | team_abbr <- data$team_abbr[i] 8 | image_to_read <- logo_list[[team_abbr]] 9 | if (is.na(team_abbr)) make_null <- TRUE 10 | } else if(type == "dark_cap"){ 11 | team_abbr <- data$team_abbr[i] 12 | image_to_read <- dark_logo_list[[team_abbr]] 13 | if (is.na(team_abbr)) make_null <- TRUE 14 | } else if(type == "light_cap"){ 15 | team_abbr <- data$team_abbr[i] 16 | image_to_read <- light_logo_list[[team_abbr]] 17 | if (is.na(team_abbr)) make_null <- TRUE 18 | } else if(type == "scoreboard"){ 19 | team_abbr <- data$team_abbr[i] 20 | image_to_read <- scoreboard_logo_list[[team_abbr]] 21 | if (is.na(team_abbr)) make_null <- TRUE 22 | } else if(type == "dot") { 23 | team_abbr <- data$team_abbr[i] 24 | image_to_read <- dot_logo_list[[team_abbr]] 25 | } else if (type == "milb_logo") { 26 | team_name <- data$team_name[i] 27 | milb_map <- load_milb_teams() 28 | image_to_read <- milb_map$team_logo[milb_map$team_name == team_name] 29 | } else if (type == "milb_light_cap") { 30 | team_name <- data$team_name[i] 31 | milb_map <- load_milb_teams() 32 | image_to_read <- milb_map$team_cap_logo_on_light[milb_map$team_name == team_name] 33 | } else if (type == "milb_dot") { 34 | team_name <- data$team_name[i] 35 | milb_map <- load_milb_teams() 36 | image_to_read <- milb_map$team_dot_logo[milb_map$team_name == team_name] 37 | } else if (type == "path"){ 38 | image_to_read <- data$path[i] 39 | } else if (type == "logo_headshots") { 40 | id <- data$player_id[i] 41 | headshot_map <- load_headshots() 42 | image_to_read <- headshot_map$espn_headshot[headshot_map$savant_id == id] 43 | if(length(image_to_read) == 0 || is.na(image_to_read)){ 44 | image_to_read <- na_headshot(TRUE) 45 | } 46 | } else if (type == "gray_headshots") { 47 | id <- data$player_id[i] 48 | headshot_map <- load_headshots() 49 | image_to_read <- headshot_map$espn_headshot[headshot_map$savant_id == id] 50 | if(length(image_to_read) == 0 || is.na(image_to_read)){ 51 | image_to_read <- na_headshot(FALSE) 52 | } 53 | } else if (type == "dot_headshots") { 54 | id <- data$player_id[i] 55 | image_to_read <- paste0("https://midfield.mlbstatic.com/v1/people/", id, "/spots/436") 56 | # if(length(image_to_read) == 0 || is.na(image_to_read)){ 57 | # image_to_read <- na_headshot(FALSE) 58 | # } 59 | } else if (type == "milb_dot_headshots") { 60 | id <- data$player_id[i] 61 | image_to_read <- paste0("https://midfield.mlbstatic.com/v1/people/", id, "/milb/436?circle=true") 62 | # if(length(image_to_read) == 0 || is.na(image_to_read)){ 63 | # image_to_read <- na_headshot(FALSE) 64 | # } 65 | } 66 | 67 | if (is.na(make_null)){ 68 | grid <- grid::nullGrob() 69 | } else if (is.null(alpha)) { 70 | img <- reader_function(image_to_read) 71 | col <- colour[i] 72 | if (!is.null(col) && col %in% "b/w"){ 73 | new <- magick::image_quantize(img, colorspace = 'gray') 74 | } else{ 75 | opa <- ifelse(is.na(col) || is.null(col), 0, 100) 76 | col <- ifelse(is.na(col) || is.null(col), "none", col) 77 | new <- magick::image_colorize(img, opa, col) 78 | } 79 | grid <- grid::rasterGrob(new) 80 | } else if (length(alpha) == 1L) { 81 | if (as.numeric(alpha) <= 0 || as.numeric(alpha) >= 1) { 82 | cli::cli_abort("aesthetic {.var alpha} requires a value between {.val 0} and {.val 1}") 83 | } 84 | img <- reader_function(image_to_read) 85 | new <- magick::image_fx(img, expression = paste0(alpha, "*a"), channel = "alpha") 86 | col <- colour[i] 87 | if (!is.null(col) && col %in% "b/w"){ 88 | new <- magick::image_quantize(new, colorspace = 'gray') 89 | } else{ 90 | opa <- ifelse(is.na(col) || is.null(col), 0, 100) 91 | col <- ifelse(is.na(col) || is.null(col), "none", col) 92 | new <- magick::image_colorize(new, opa, col) 93 | } 94 | grid <- grid::rasterGrob(new) 95 | } else { 96 | if (any(as.numeric(alpha) < 0) || any(as.numeric(alpha) > 1)) { 97 | cli::cli_abort("aesthetics {.var alpha} require values between {.val 0} and {.val 1}") 98 | } 99 | img <- reader_function(image_to_read) 100 | new <- magick::image_fx(img, expression = paste0(alpha[i], "*a"), channel = "alpha") 101 | col <- colour[i] 102 | if (!is.null(col) && col %in% "b/w"){ 103 | new <- magick::image_quantize(new, colorspace = 'gray') 104 | } else{ 105 | opa <- ifelse(is.na(col) || is.null(col), 0, 100) 106 | col <- ifelse(is.na(col) || is.null(col), "none", col) 107 | new <- magick::image_colorize(new, opa, col) 108 | } 109 | grid <- grid::rasterGrob(new) 110 | } 111 | 112 | grid$vp <- grid::viewport( 113 | x = grid::unit(data$x[i], "native"), 114 | y = grid::unit(data$y[i], "native"), 115 | width = grid::unit(data$width[i], "npc"), 116 | height = grid::unit(data$height[i], "npc"), 117 | just = c(data$hjust[i], data$vjust[i]), 118 | angle = data$angle[i], 119 | name = paste("geom_mlb.panel", data$PANEL[i], 120 | "row", i, 121 | sep = "." 122 | ) 123 | ) 124 | 125 | grid$name <- paste("mlb.grob", i, sep = ".") 126 | 127 | grid 128 | } 129 | 130 | reader_function <- function(img){ 131 | if(is.factor(img)) img <- as.character(img) 132 | if(is.raw(img) || tools::file_ext(img) != "svg"){ 133 | magick::image_read(img) 134 | } else if(tools::file_ext(img) == "svg"){ 135 | magick::image_read_svg(img) 136 | } 137 | } 138 | -------------------------------------------------------------------------------- /R/geom_cap_logos.R: -------------------------------------------------------------------------------- 1 | #' @name geom_cap_logos 2 | #' 3 | #' @title 4 | #' ggplot2 Layer for Visualizing MLB Team Cap Logos 5 | #' 6 | #' @description `geom_mlb_dark_cap_logos()` and `geom_mlb_light_cap_logos()` 7 | #' are used to plot MLB team cap and league logos instead of points in a 8 | #' ggplot. It requires x, y aesthetics as well as a valid MLB team 9 | #' abbreviation. The latter can be checked with [`valid_team_names()`] but is 10 | #' also cleaned before being plotted. 11 | #' 12 | #' @inheritParams ggplot2::geom_point 13 | #' @section Aesthetics: 14 | #' `geom_mlb_dark_cap_logos()` and `geom_mlb_light_cap_logos()` understand the following aesthetics: 15 | #' \describe{ 16 | #' \item{`x`}{ - The x-coordinate. Required.} 17 | #' \item{`y`}{ - The y-coordinate. Required.} 18 | #' \item{`team_abbr`}{ - The team abbreviation. Need to use Savant's abbreviation. Required.} 19 | #' \item{`alpha = NULL`}{ - The alpha channel, i.e. transparency level, as a numerical value between 0 and 1.} 20 | #' \item{`colour = NULL`}{ - The image will be colourized with this colour. Use the special character `"b/w"` to set it to black and white. For more information on valid colour names in ggplot2 see } 21 | #' \item{`angle = 0`}{ - The angle of the image as a numerical value between 0° and 360°.} 22 | #' \item{`hjust = 0.5`}{ - The horizontal adjustment relative to the given x coordinate. Must be a numerical value between 0 and 1.} 23 | #' \item{`vjust = 0.5`}{ - The vertical adjustment relative to the given y coordinate. Must be a numerical value between 0 and 1.} 24 | #' \item{`height = 1.0`}{ - The desired height of the image in `npc` (Normalised Parent Coordinates). 25 | #' The default value is set to 1.0 which is *big* but it is necessary 26 | #' because all used values are computed relative to the default. 27 | #' A typical size is `height = 0.1` (see below examples). 28 | #' For cap logos, the scaling works better when adjusting height and not width.} 29 | #' \item{`width = 1.0`}{ - The desired width of the image in `npc` (Normalised Parent Coordinates). 30 | #' The default value is set to 1.0 which is *big* but it is necessary 31 | #' because all used values are computed relative to the default. 32 | #' A typical size is `height = 0.075` (see below examples). 33 | #' For cap logos, the scaling works better when adjusting height and not width.} 34 | #' } 35 | #' @param ... Other arguments passed on to [ggplot2::layer()]. These are 36 | #' often aesthetics, used to set an aesthetic to a fixed value. See the below 37 | #' section "Aesthetics" for a full list of possible arguments. 38 | #' @param nudge_x,nudge_y Horizontal and vertical adjustment to nudge labels by. 39 | #' Useful for offsetting text from points, particularly on discrete scales. 40 | #' Cannot be jointly specified with `position`. 41 | #' @return A ggplot2 layer ([ggplot2::layer()]) that can be added to a plot 42 | #' created with [ggplot2::ggplot()]. 43 | #' @examples 44 | #' \donttest{ 45 | #' library(mlbplotR) 46 | #' library(ggplot2) 47 | #' 48 | #' team_abbr <- valid_team_names() 49 | #' # remove conference logos from this example 50 | #' team_abbr <- team_abbr[!team_abbr %in% c("NL", "AL", "MLB")] 51 | #' 52 | #' df <- data.frame( 53 | #' a = rep(1:6, 5), 54 | #' b = sort(rep(1:5, 6), decreasing = TRUE), 55 | #' teams = team_abbr 56 | #' ) 57 | #' 58 | #' # keep alpha == 1 for all teams including an "A" 59 | #' matches <- grepl("A", team_abbr) 60 | #' df$alpha <- ifelse(matches, 1, 0.2) 61 | #' # also set a custom fill colour for the non "A" teams 62 | #' df$colour <- ifelse(matches, NA, "gray") 63 | #' 64 | #' # scatterplot of all logos 65 | #' ggplot(df, aes(x = a, y = b)) + 66 | #' geom_mlb_dark_cap_logos(aes(team_abbr = teams), height = 0.075) + 67 | #' geom_label(aes(label = teams), nudge_y = -0.35, alpha = 0.5) + 68 | #' theme_void() 69 | #' 70 | #' # apply alpha via an aesthetic from inside the dataset `df` 71 | #' # please note that you have to add scale_alpha_identity() to use the alpha 72 | #' # values in your dataset! 73 | #' ggplot(df, aes(x = a, y = b)) + 74 | #' geom_mlb_dark_cap_logos(aes(team_abbr = teams, alpha = alpha), height = 0.075) + 75 | #' geom_label(aes(label = teams), nudge_y = -0.35, alpha = 0.5) + 76 | #' scale_alpha_identity() + 77 | #' theme_void() 78 | #' 79 | #' # apply alpha and colour via an aesthetic from inside the dataset `df` 80 | #' # please note that you have to add scale_alpha_identity() as well as 81 | #' # scale_colour_identity() to use the alpha and colour values in your dataset! 82 | #' ggplot(df, aes(x = a, y = b)) + 83 | #' geom_mlb_light_cap_logos(aes(team_abbr = teams, alpha = alpha, colour = colour), height = 0.075) + 84 | #' geom_label(aes(label = teams), nudge_y = -0.35, alpha = 0.5) + 85 | #' scale_alpha_identity() + 86 | #' scale_colour_identity() + 87 | #' theme_void() 88 | #' 89 | #' # apply alpha as constant for all logos 90 | #' ggplot(df, aes(x = a, y = b)) + 91 | #' geom_mlb_light_cap_logos(aes(team_abbr = teams), height = 0.075, alpha = 0.6) + 92 | #' geom_label(aes(label = teams), nudge_y = -0.35, alpha = 0.5) + 93 | #' theme_void() 94 | #' 95 | #' # it's also possible to plot league logos 96 | #' league <- data.frame(a = 1:3, b = 0, teams = c("AL", "NL", "MLB")) 97 | #' ggplot(league, aes(x = a, y = b)) + 98 | #' geom_mlb_dark_cap_logos(aes(team_abbr = teams), width = 0.3) + 99 | #' geom_label(aes(label = teams), nudge_y = -0.4, alpha = 0.5) + 100 | #' coord_cartesian(xlim = c(0.5,3.5), ylim = c(-0.75,.75)) + 101 | #' theme_void() 102 | #' } 103 | NULL 104 | 105 | #' @rdname geom_cap_logos 106 | #' @export 107 | geom_mlb_dark_cap_logos <- function(mapping = NULL, data = NULL, 108 | stat = "identity", position = "identity", 109 | ..., 110 | nudge_x = 0, 111 | nudge_y = 0, 112 | na.rm = FALSE, 113 | show.legend = FALSE, 114 | inherit.aes = TRUE) { 115 | 116 | if (!missing(nudge_x) || !missing(nudge_y)) { 117 | if (!missing(position)) { 118 | cli::cli_abort(c( 119 | "both {.arg position} and {.arg nudge_x}/{.arg nudge_y} are supplied", 120 | "i" = "Only use one approach to alter the position" 121 | )) 122 | } 123 | 124 | position <- ggplot2::position_nudge(nudge_x, nudge_y) 125 | } 126 | 127 | ggplot2::layer( 128 | data = data, 129 | mapping = mapping, 130 | stat = stat, 131 | geom = GeomMLBdarkcaplogo, 132 | position = position, 133 | show.legend = show.legend, 134 | inherit.aes = inherit.aes, 135 | params = list( 136 | na.rm = na.rm, 137 | ... 138 | ) 139 | ) 140 | } 141 | 142 | #' @rdname mlbplotR-package 143 | #' @export 144 | GeomMLBdarkcaplogo <- ggplot2::ggproto( 145 | "GeomMLBdarkcaplogo", ggplot2::Geom, 146 | required_aes = c("x", "y", "team_abbr"), 147 | # non_missing_aes = c(""), 148 | default_aes = ggplot2::aes( 149 | alpha = NULL, colour = NULL, angle = 0, hjust = 0.5, 150 | vjust = 0.5, width = 1.0, height = 1.0 151 | ), 152 | draw_panel = function(data, panel_params, coord, na.rm = FALSE) { 153 | data <- coord$transform(data, panel_params) 154 | 155 | data$team_abbr <- clean_team_abbrs(as.character(data$team_abbr), keep_non_matches = FALSE) 156 | 157 | grobs <- lapply(seq_along(data$team_abbr), build_grobs, alpha = data$alpha, colour = data$colour, data = data, type = "dark_cap") 158 | 159 | class(grobs) <- "gList" 160 | 161 | grid::gTree(children = grobs) 162 | }, 163 | draw_key = function(...) grid::nullGrob() 164 | ) 165 | 166 | 167 | 168 | 169 | #' @rdname geom_cap_logos 170 | #' @export 171 | geom_mlb_light_cap_logos <- function(mapping = NULL, data = NULL, 172 | stat = "identity", position = "identity", 173 | ..., 174 | nudge_x = 0, 175 | nudge_y = 0, 176 | na.rm = FALSE, 177 | show.legend = FALSE, 178 | inherit.aes = TRUE) { 179 | 180 | if (!missing(nudge_x) || !missing(nudge_y)) { 181 | if (!missing(position)) { 182 | cli::cli_abort(c( 183 | "both {.arg position} and {.arg nudge_x}/{.arg nudge_y} are supplied", 184 | "i" = "Only use one approach to alter the position" 185 | )) 186 | } 187 | 188 | position <- ggplot2::position_nudge(nudge_x, nudge_y) 189 | } 190 | 191 | ggplot2::layer( 192 | data = data, 193 | mapping = mapping, 194 | stat = stat, 195 | geom = GeomMLBlightcaplogo, 196 | position = position, 197 | show.legend = show.legend, 198 | inherit.aes = inherit.aes, 199 | params = list( 200 | na.rm = na.rm, 201 | ... 202 | ) 203 | ) 204 | } 205 | 206 | #' @rdname mlbplotR-package 207 | #' @export 208 | GeomMLBlightcaplogo <- ggplot2::ggproto( 209 | "GeomMLBlightcaplogo", ggplot2::Geom, 210 | required_aes = c("x", "y", "team_abbr"), 211 | # non_missing_aes = c(""), 212 | default_aes = ggplot2::aes( 213 | alpha = NULL, colour = NULL, angle = 0, hjust = 0.5, 214 | vjust = 0.5, width = 1.0, height = 1.0 215 | ), 216 | draw_panel = function(data, panel_params, coord, na.rm = FALSE) { 217 | data <- coord$transform(data, panel_params) 218 | 219 | data$team_abbr <- clean_team_abbrs(as.character(data$team_abbr), keep_non_matches = FALSE) 220 | 221 | grobs <- lapply(seq_along(data$team_abbr), build_grobs, alpha = data$alpha, colour = data$colour, data = data, type = "light_cap") 222 | 223 | class(grobs) <- "gList" 224 | 225 | grid::gTree(children = grobs) 226 | }, 227 | draw_key = function(...) grid::nullGrob() 228 | ) 229 | -------------------------------------------------------------------------------- /R/geom_from_path.R: -------------------------------------------------------------------------------- 1 | #' ggplot2 Layer for Visualizing Images from URLs or Local Paths 2 | #' 3 | #' @description This geom is used to plot MLB images instead 4 | #' of points in a ggplot. It requires x, y aesthetics as well as a path. 5 | #' 6 | #' @inheritParams ggplot2::geom_point 7 | #' @section Aesthetics: 8 | #' `geom_mlb_logos()` understands the following aesthetics: 9 | #' \describe{ 10 | #' \item{`x`}{ - The x-coordinate. Required.} 11 | #' \item{`y`}{ - The y-coordinate. Required.} 12 | #' \item{`path`}{ - a file path, url, raster object or bitmap array. See [`magick::image_read()`] for further information. Required.} 13 | #' \item{`alpha = NULL`}{ - The alpha channel, i.e. transparency level, as a numerical value between 0 and 1.} 14 | #' \item{`colour = NULL`}{ - The image will be colorized with this colour. Use the special character `"b/w"` to set it to black and white. For more information on valid colour names in ggplot2 see } 15 | #' \item{`angle = 0`}{ - The angle of the image as a numerical value between 0° and 360°.} 16 | #' \item{`hjust = 0.5`}{ - The horizontal adjustment relative to the given x coordinate. Must be a numerical value between 0 and 1.} 17 | #' \item{`vjust = 0.5`}{ - The vertical adjustment relative to the given y coordinate. Must be a numerical value between 0 and 1.} 18 | #' \item{`width = 1.0`}{ - The desired width of the image in `npc` (Normalised Parent Coordinates). 19 | #' The default value is set to 1.0 which is *big* but it is necessary 20 | #' because all used values are computed relative to the default. 21 | #' A typical size is `width = 0.1` (see below examples).} 22 | #' \item{`height = 1.0`}{ - The desired height of the image in `npc` (Normalised Parent Coordinates). 23 | #' The default value is set to 1.0 which is *big* but it is necessary 24 | #' because all used values are computed relative to the default. 25 | #' A typical size is `height = 0.1` (see below examples).} 26 | #' } 27 | #' @param ... Other arguments passed on to [ggplot2::layer()]. These are 28 | #' often aesthetics, used to set an aesthetic to a fixed value. See the below 29 | #' section "Aesthetics" for a full list of possible arguments. 30 | #' @param nudge_x,nudge_y Horizontal and vertical adjustment to nudge labels by. 31 | #' Useful for offsetting text from points, particularly on discrete scales. 32 | #' Cannot be jointly specified with `position`. 33 | #' @return A ggplot2 layer ([ggplot2::layer()]) that can be added to a plot 34 | #' created with [ggplot2::ggplot()]. 35 | #' @export 36 | #' @examples 37 | #' \donttest{ 38 | #' library(mlbplotR) 39 | #' library(ggplot2) 40 | #' 41 | #' # create x-y-coordinates of a triangle and add league logo urls 42 | #' df <- data.frame( 43 | #' a = c(sin(2 * pi * (0:4) / 5), 0), 44 | #' b = c(cos(2 * pi * (0:4) / 5), 0), 45 | #' url = c( 46 | #' "https://i.turner.ncaa.com/sites/default/files/images/logos/schools/bgl/virginia.svg", 47 | #' "https://i.turner.ncaa.com/sites/default/files/images/logos/schools/bgl/michigan-st.svg", 48 | #' "https://i.turner.ncaa.com/sites/default/files/images/logos/schools/bgl/lsu.svg", 49 | #' "https://i.turner.ncaa.com/sites/default/files/images/logos/schools/bgl/texas.svg", 50 | #' "https://i.turner.ncaa.com/sites/default/files/images/logos/schools/bgl/oregon.svg", 51 | #' "https://i.turner.ncaa.com/sites/default/files/images/logos/schools/bgl/james-madison.svg" 52 | #' ) 53 | #' ) 54 | #' 55 | #' # plot images directly from url 56 | #' ggplot(df, aes(x = a, y = b)) + 57 | #' geom_from_path(aes(path = url), width = 0.15) + 58 | #' coord_cartesian(xlim = c(-2, 2), ylim = c(-1.3, 1.5)) + 59 | #' theme_void() 60 | #' 61 | #' # plot images directly from url and apply transparency 62 | #' ggplot(df, aes(x = a, y = b)) + 63 | #' geom_from_path(aes(path = url), width = 0.15, alpha = 0.5) + 64 | #' coord_cartesian(xlim = c(-2, 2), ylim = c(-1.3, 1.5)) + 65 | #' theme_void() 66 | #' 67 | #' # It is also possible and recommended to use the underlying Geom inside a 68 | #' # ggplot2 annotation 69 | #' ggplot() + 70 | #' annotate( 71 | #' mlbplotR::GeomFromPath, 72 | #' x = 0, 73 | #' y = 0, 74 | #' path = "https://a.espncdn.com/combiner/i?img=/i/teamlogos/leagues/500/mlb.png", 75 | #' width = 0.4 76 | #' ) + 77 | #' theme_minimal() 78 | #' } 79 | geom_from_path <- function(mapping = NULL, data = NULL, 80 | stat = "identity", position = "identity", 81 | ..., 82 | nudge_x = 0, 83 | nudge_y = 0, 84 | na.rm = FALSE, 85 | show.legend = FALSE, 86 | inherit.aes = TRUE) { 87 | 88 | if (!missing(nudge_x) || !missing(nudge_y)) { 89 | if (!missing(position)) { 90 | cli::cli_abort(c( 91 | "both {.arg position} and {.arg nudge_x}/{.arg nudge_y} are supplied", 92 | "i" = "Only use one approach to alter the position" 93 | )) 94 | } 95 | 96 | position <- ggplot2::position_nudge(nudge_x, nudge_y) 97 | } 98 | 99 | ggplot2::layer( 100 | data = data, 101 | mapping = mapping, 102 | stat = stat, 103 | geom = GeomFromPath, 104 | position = position, 105 | show.legend = show.legend, 106 | inherit.aes = inherit.aes, 107 | params = list( 108 | na.rm = na.rm, 109 | ... 110 | ) 111 | ) 112 | } 113 | 114 | #' @rdname mlbplotR-package 115 | #' @export 116 | GeomFromPath <- ggplot2::ggproto( 117 | "GeomFromPath", ggplot2::Geom, 118 | required_aes = c("x", "y", "path"), 119 | # non_missing_aes = c(""), 120 | default_aes = ggplot2::aes( 121 | alpha = NULL, colour = NULL, angle = 0, hjust = 0.5, 122 | vjust = 0.5, width = 1.0, height = 1.0 123 | ), 124 | draw_panel = function(data, panel_params, coord, na.rm = FALSE) { 125 | data <- coord$transform(data, panel_params) 126 | 127 | grobs <- lapply(seq_along(data$path), build_grobs, alpha = data$alpha, colour = data$colour, data = data, type = "path") 128 | 129 | class(grobs) <- "gList" 130 | 131 | grid::gTree(children = grobs) 132 | }, 133 | draw_key = function(...) grid::nullGrob() 134 | ) 135 | -------------------------------------------------------------------------------- /R/geom_lines.R: -------------------------------------------------------------------------------- 1 | # Adapted from nflplotR 2 | 3 | #' ggplot2 Layer for Horizontal and Vertical Reference Lines 4 | #' 5 | #' @description These geoms can be used to draw horizontal or vertical reference 6 | #' lines in a ggplot. They use the data in the aesthetics `v_var` and `h_var` 7 | #' to compute their `median` or `mean` and draw the as a line. 8 | #' 9 | #' @inheritParams ggplot2::geom_hline 10 | #' @param inherit.aes If `FALSE`, overrides the default aesthetics, 11 | #' rather than combining with them. This is most useful for helper functions 12 | #' that define both data and aesthetics and shouldn't inherit behavior from 13 | #' the default plot specification. 14 | #' @section Aesthetics: 15 | #' `geom_median_lines()` and `geom_mean_lines()` understand the following 16 | #' aesthetics (at least one of `v_var` and `h_var` are required): 17 | #' \describe{ 18 | #' \item{`v_var`}{ - The variable for which to compute the median/mean that is drawn as vertical line.} 19 | #' \item{`h_var`}{ - The variable for which to compute the median/mean that is drawn as horizontal line.} 20 | #' \item{`alpha = NA`}{ - The alpha channel, i.e. transparency level, as a numerical value between 0 and 1.} 21 | #' \item{`color = "black"`}{ - The color of the drawn lines.} 22 | #' \item{`linetype = 2`}{ - The linetype of the drawn lines.} 23 | #' \item{`linewidth = 0.5`}{ - The size of the drawn lines.} 24 | #' } 25 | #' @seealso The underlying ggplot2 geoms [`geom_hline()`] and [`geom_vline()`] 26 | #' @name geom_lines 27 | #' @return A ggplot2 layer ([ggplot2::layer()]) that can be added to a plot 28 | #' created with [ggplot2::ggplot()]. 29 | #' @aliases NULL 30 | #' @examples 31 | #' \donttest{ 32 | #' library(mlbplotR) 33 | #' library(ggplot2) 34 | #' 35 | #' # inherit top level aesthetics 36 | #' ggplot(mtcars, aes(x = disp, y = mpg, h_var = mpg, v_var = disp)) + 37 | #' geom_point() + 38 | #' geom_median_lines() + 39 | #' geom_mean_lines(color = "blue") + 40 | #' theme_minimal() 41 | #' 42 | #' # draw horizontal line only 43 | #' ggplot(mtcars, aes(x = disp, y = mpg, h_var = mpg)) + 44 | #' geom_point() + 45 | #' geom_median_lines() + 46 | #' geom_mean_lines(color = "blue") + 47 | #' theme_minimal() 48 | #' 49 | #' # draw vertical line only 50 | #' ggplot(mtcars, aes(x = disp, y = mpg, v_var = disp)) + 51 | #' geom_point() + 52 | #' geom_median_lines() + 53 | #' geom_mean_lines(color = "blue") + 54 | #' theme_minimal() 55 | #' 56 | #' # choose your own value 57 | #' ggplot(mtcars, aes(x = disp, y = mpg)) + 58 | #' geom_point() + 59 | #' geom_median_lines(v_var = 400, h_var = 15) + 60 | #' geom_mean_lines(v_var = 150, h_var = 30, color = "blue") + 61 | #' theme_minimal() 62 | #' } 63 | NULL 64 | 65 | #' @rdname geom_lines 66 | #' @export 67 | geom_median_lines <- function(mapping = NULL, data = NULL, 68 | ..., 69 | na.rm = FALSE, 70 | show.legend = NA, 71 | inherit.aes = TRUE) { 72 | 73 | ggplot2::layer( 74 | data = data, 75 | mapping = mapping, 76 | stat = ggplot2::StatIdentity, 77 | geom = GeomRefLines, 78 | position = ggplot2::PositionIdentity, 79 | show.legend = show.legend, 80 | inherit.aes = inherit.aes, 81 | params = list( 82 | ref_function = stats::median, 83 | na.rm = na.rm, 84 | ... 85 | ) 86 | ) 87 | } 88 | 89 | #' @rdname geom_lines 90 | #' @export 91 | geom_mean_lines <- function(mapping = NULL, data = NULL, 92 | ..., 93 | na.rm = FALSE, 94 | show.legend = NA, 95 | inherit.aes = TRUE) { 96 | 97 | ggplot2::layer( 98 | data = data, 99 | mapping = mapping, 100 | stat = ggplot2::StatIdentity, 101 | geom = GeomRefLines, 102 | position = ggplot2::PositionIdentity, 103 | show.legend = show.legend, 104 | inherit.aes = inherit.aes, 105 | params = list( 106 | ref_function = base::mean, 107 | na.rm = na.rm, 108 | ... 109 | ) 110 | ) 111 | } 112 | 113 | #' @rdname mlbplotR-package 114 | #' @export 115 | GeomRefLines <- ggplot2::ggproto("GeomRefLines", ggplot2::Geom, 116 | 117 | optional_aes = c("v_var", "h_var"), 118 | 119 | default_aes = ggplot2::aes(colour = "black", linewidth = 0.5, linetype = 2, alpha = NA), 120 | 121 | setup_data = function(data, params){ 122 | # This step is important for transformations. ggplot2 transforms aesthetics 123 | # that are included in the ggplot2 environments ggplot_global$x_aes and 124 | # ggplot_global$y_aes. We can't modify that environment so we need to 125 | # modify our data here. 126 | # That's why this step overwrites v_var and h_var with x and y. These 127 | # x and y are already transformed if any kind of transformation is required, 128 | # e.g. trans = "reverse". Without transformation, x/v_var and y/h_var are 129 | # identical. 130 | # This approach does not work if h_var or v_var are set to a constant value 131 | # by the user. Therefore we check the number of unique values. 132 | vars <- names(data) 133 | if ("v_var" %in% vars && length(unique(data$v_var)) > 1) data$v_var <- data$x 134 | if ("h_var" %in% vars && length(unique(data$h_var)) > 1) data$h_var <- data$y 135 | data 136 | }, 137 | 138 | draw_panel = function(data, panel_params, coord, ref_function, na.rm = FALSE) { 139 | args <- names(data) 140 | 141 | # Can't do anything if either of h_var and v_var are aesthetics 142 | if (all(!c("v_var", "h_var") %in% args)) { 143 | cli::cli_abort("{.var geom_median_lines()} and {.var geom_mean_lines()} require at least one of the following aesthetics: {.var v_var}, {.var h_var}") 144 | } 145 | 146 | # Since h_var and v_var can be in data, it is necessary to select only 147 | # those variables that are required for the underlying Geoms to work. 148 | # This could also be achieved by setting inherit.aes to FALSE explicitly but 149 | # I want to be able to inherit aesthetics so I had to do this differently. 150 | relevant_columns <- c("PANEL", "group", "colour", "linewidth", "linetype", "alpha") 151 | 152 | # if v_var and/or h_var are present in data we have to compute the relevant 153 | # xintercept and yintercept variables and drop anything irrelevant from data 154 | # as the underlying Geoms will draw multiple lines if there are multiple 155 | # unique rows. This caused alpha to not work properly because the geom draws 156 | # many opaque lines which outputs as non-opaque lines. 157 | if ("v_var" %in% args){ 158 | data_v <- data 159 | data_v$xintercept <- ref_function(data_v$v_var, na.rm = na.rm) 160 | data_v <- data_v[,c("xintercept", relevant_columns)] 161 | } 162 | 163 | if ("h_var" %in% args){ 164 | data_h <- data 165 | data_h$yintercept <- ref_function(data_h$h_var, na.rm = na.rm) 166 | data_h <- data_h[,c("yintercept", relevant_columns)] 167 | } 168 | 169 | if (!"v_var" %in% args) { 170 | ggplot2::GeomHline$draw_panel(data_h, panel_params, coord) 171 | } else if (!"h_var" %in% args) { 172 | ggplot2::GeomVline$draw_panel(data_v, panel_params, coord) 173 | } else { 174 | grid::gList( 175 | ggplot2::GeomHline$draw_panel(data_h, panel_params, coord), 176 | ggplot2::GeomVline$draw_panel(data_v, panel_params, coord) 177 | ) 178 | } 179 | }, 180 | 181 | draw_key = ggplot2::draw_key_path 182 | ) 183 | -------------------------------------------------------------------------------- /R/ggpreview.R: -------------------------------------------------------------------------------- 1 | #' Preview ggplot in Specified Dimensions 2 | #' 3 | #' This function previews a ggplot in its actual dimensions in order to see how 4 | #' it will look when saved. It is also significantly faster than the default 5 | #' preview in RStudio for ggplots created using mlbplotR. 6 | #' 7 | #' @inheritParams ggplot2::ggsave 8 | #' @param asp The aspect ratio of the plot calculated as `width / height`. If 9 | #' this is a numeric value (and not `NULL`) the `height` of the plot will be 10 | #' recalculated to `height = width / asp`. 11 | #' @return No return value, called for side effects. 12 | #' @export 13 | #' @examples 14 | #' \donttest{ 15 | #' library(mlbplotR) 16 | #' library(ggplot2) 17 | #' 18 | #' team_abbr <- valid_team_names() 19 | #' # remove league logos from this example 20 | #' team_abbr <- team_abbr[!team_abbr %in% c("AL", "NL", "MLB")] 21 | #' 22 | #' df <- data.frame( 23 | #' random_value = runif(length(team_abbr), 0, 1), 24 | #' teams = team_abbr 25 | #' ) 26 | #' 27 | #' # use logos for x-axis 28 | #' # note that the plot is assigned to the object "p" 29 | #' p <- ggplot(df, aes(x = teams, y = random_value)) + 30 | #' geom_col(aes(color = teams, fill = teams), width = 0.5) + 31 | #' scale_color_mlb(type = "secondary") + 32 | #' scale_fill_mlb(alpha = 0.4) + 33 | #' theme_minimal() + 34 | #' theme(axis.text.x = element_mlb_logo()) 35 | #' 36 | #' # preview p with defined width and aspect ratio (only available in RStudio) 37 | #' if (rstudioapi::isAvailable()){ 38 | #' ggpreview(p, width = 5, asp = 16/9) 39 | #' } 40 | #' } 41 | ggpreview <- function(plot = ggplot2::last_plot(), 42 | width = NA, 43 | height = NA, 44 | asp = NULL, 45 | dpi = 300, 46 | device = "png", 47 | units = c("in", "cm", "mm", "px"), 48 | scale = 1, 49 | limitsize = TRUE, 50 | bg = NULL, 51 | ...){ 52 | rlang::check_installed("rstudioapi", reason = "to preview a ggplot file") 53 | file <- tempfile() 54 | if (is.numeric(asp)) height <- width / asp 55 | ggplot2::ggsave( 56 | file, 57 | plot = plot, 58 | device = device, 59 | scale = scale, 60 | width = width, 61 | height = height, 62 | units = units, 63 | dpi = dpi, 64 | limitsize = limitsize, 65 | bg = bg, 66 | ... 67 | ) 68 | rstudioapi::viewer(file) 69 | } 70 | -------------------------------------------------------------------------------- /R/load_data.R: -------------------------------------------------------------------------------- 1 | #' Load MLB Team Colors, and Logos 2 | #' 3 | #' @description Loads team colors, and logos - useful for plots! 4 | #' 5 | #' @examples 6 | #' \donttest{ 7 | #' load_mlb_teams() 8 | #' } 9 | #' 10 | #' @return A tibble of team-level abbreviations, image URLs, and hex color codes. 11 | #' 12 | #' @seealso Issues with this data should be filed here: 13 | #' 14 | #' @export 15 | load_mlb_teams <- function(){ 16 | out <- teams_colors_logos 17 | class(out) <- c("tbl_df","tbl","data.table","data.frame") 18 | out 19 | } 20 | 21 | #' Output Valid MLB Team Abbreviations 22 | #' 23 | #' @param remove_league_info Should "AL", "NL", and "MLB" be removed from the returned vector? Defaults to `FALSE`. 24 | #' 25 | #' @return A vector of type `"character"`. 26 | #' @examples 27 | #' \donttest{ 28 | #' # List valid team abbreviations excluding duplicates 29 | #' valid_team_names() 30 | #' valid_team_names(TRUE) 31 | #' } 32 | #' 33 | #' @export 34 | valid_team_names <- function(remove_league_info = FALSE){ 35 | if (isTRUE(remove_league_info)) { 36 | sort(names(logo_list)[!names(logo_list) %in% c("AL", "NL", "MLB")]) 37 | } else { 38 | sort(names(logo_list)) 39 | } 40 | } 41 | 42 | 43 | #' Standardize MLB Team Abbreviations 44 | #' 45 | #' This function standardizes MLB team abbreviations to Baseball Savant defaults. 46 | #' This helps for joins and plotting 47 | #' 48 | #' @param abbr a character vector of abbreviations 49 | #' @param keep_non_matches will non-matches be kept in the vector? 50 | #' 51 | #' @return A character vector with the length of `abbr` and cleaned team abbreviations 52 | #' if they are included in `team_data`. Non matches may be replaced 53 | #' with `NA` (depending on the value of `keep_non_matches`). 54 | #' @examples 55 | #' \donttest{ 56 | #' x <- c("PIE", "STL", "WSN", "CWS", "CHW") 57 | #' # use current location and keep non matches 58 | #' clean_team_abbrs(x) 59 | #' } 60 | #' @export 61 | clean_team_abbrs <- function(abbr, keep_non_matches = TRUE) { 62 | stopifnot(is.character(abbr)) 63 | 64 | abbrs <- unname(team_data[toupper(abbr)]) 65 | 66 | if (isTRUE(keep_non_matches)) abbrs <- abbrs %c% abbr 67 | 68 | abbrs 69 | } 70 | 71 | 72 | 73 | #' Output MLB Team Abbreviations 74 | #' 75 | #' @export 76 | #' @return A tibble of player names and ids from various sources. 77 | #' @examples 78 | #' \donttest{ 79 | #' load_headshots() 80 | #' } 81 | #' 82 | load_headshots <- function() rds_from_url("https://github.com/camdenk/mlbplotR-data/raw/main/Player-IDs.rds") 83 | 84 | 85 | 86 | #' Load MiLB Team Colors, and Logos 87 | #' 88 | #' @description Loads team information and logos - useful for plots! 89 | #' 90 | #' @examples 91 | #' \donttest{ 92 | #' load_milb_teams() 93 | #' } 94 | #' 95 | #' @importFrom data.table fread 96 | #' 97 | #' @return A tibble of team-level abbreviations, image URLs, and league info for Minor League Baseball Teams. 98 | #' 99 | #' @seealso Issues with this data should be filed here: 100 | #' 101 | #' @export 102 | load_milb_teams <- function(){ 103 | out <- data.table::fread("https://raw.githubusercontent.com/camdenk/mlbplotR-data/main/milb_map.csv", 104 | verbose = FALSE, showProgress = FALSE) 105 | class(out) <- c("tbl_df","tbl","data.table","data.frame") 106 | out 107 | } 108 | 109 | 110 | -------------------------------------------------------------------------------- /R/mlb_team_factors.R: -------------------------------------------------------------------------------- 1 | #' Create Ordered MLB Team Factor 2 | #' 3 | #' @description Convert a vector of MLB team abbreviations to an ordered factor 4 | #' by division and team name. Intended to be used for faceted plots where team 5 | #' logos are used in strip texts. 6 | #' 7 | #' @param teams A vector of MLB team abbreviations that should be included in 8 | #' [`valid_team_names()`]. The function tries to clean team names internally 9 | #' by calling [`clean_team_abbrs()`]. 10 | #' 11 | #' @return Object of class `"factor"` 12 | #' @export 13 | #' @examples 14 | #' \donttest{ 15 | #' # unsorted vector including NFL team abbreviations 16 | #' teams <- c("ATL", "WSH", "MIA", "BAL", "NYY", "BOS", "PHI", "NYM", "TB", "TOR") 17 | #' 18 | #' # defaults to sort by division and nick name in ascending order 19 | #' mlb_team_factor(teams) 20 | #' 21 | #' 22 | #' ######### HOW TO USE IN PRACTICE ######### 23 | #' 24 | #' library(ggplot2) 25 | #' library(magrittr) 26 | #' # load some sample data from the ggplot2 package 27 | #' plot_data <- mpg 28 | #' # add a new column by randomly sampling the above defined teams vector 29 | #' plot_data$team <- sample(teams, nrow(mpg), replace = TRUE) 30 | #' 31 | #' # Now we plot the data and facet by team abbreviation. ggplot automatically 32 | #' # converts the team names to a factor and sorts it alphabetically 33 | #' ggplot(plot_data, aes(displ, hwy)) + 34 | #' geom_point() + 35 | #' facet_wrap(~team, ncol = 5) + 36 | #' theme_minimal() 37 | #' 38 | #' # We'll change the order of facets by making another team name column and 39 | #' # converting it to an ordered factor. Again, this defaults to sort by division, 40 | #' # league, and location in ascending order. 41 | #' plot_data$ordered_team <- sample(teams, nrow(mpg), replace = TRUE) %>% 42 | #' mlb_team_factor() 43 | #' 44 | #' # Let's check how the facets are ordered now. 45 | #' ggplot(plot_data, aes(displ, hwy)) + 46 | #' geom_point() + 47 | #' facet_wrap(~ordered_team, ncol = 5) + 48 | #' theme_minimal() 49 | #' 50 | #' # The facet order looks weird because the defaults is meant to be used with 51 | #' # MLB team logos. So let's use the actual logos and look at the result. 52 | #' ggplot(plot_data, aes(displ, hwy)) + 53 | #' geom_point() + 54 | #' facet_wrap(~ordered_team, ncol = 5) + 55 | #' theme_minimal() + 56 | #' theme(strip.text = element_mlb_logo(size = .85)) 57 | #' 58 | #' } 59 | mlb_team_factor <- function(teams){ 60 | # clean the abbrs a bit to make them match the mlbplotR team abbrs 61 | teams <- mlbplotR::clean_team_abbrs(teams) 62 | 63 | 64 | # character vector of team abbrs in desired order 65 | levels <- c("BAL", "BOS", "NYY", "TB", "TOR", 66 | "ATL", "MIA", "NYM", "PHI", "WSH", 67 | "CWS", "CLE", "DET", "KC", "MIN", 68 | "CHC", "CIN", "MIL", "PIT", "STL", 69 | "HOU", "LAA", "OAK", "SEA", "TEX", 70 | "AZ", "COL", "LAD", "SD", "SF") 71 | 72 | factor( 73 | x = teams, 74 | levels = levels, 75 | ordered = TRUE 76 | ) 77 | } 78 | -------------------------------------------------------------------------------- /R/mlbplotR-package.R: -------------------------------------------------------------------------------- 1 | #' @keywords internal 2 | "_PACKAGE" 3 | 4 | # The following block is used by usethis to automatically manage 5 | # roxygen namespace tags. Modify with care! 6 | ## usethis namespace: start 7 | #' @import grid 8 | #' @importFrom ggplot2 element_grob 9 | #' @importFrom lifecycle deprecated 10 | #' @importFrom magrittr %>% 11 | #' @importFrom rlang .data %||% 12 | ## usethis namespace: end 13 | NULL 14 | -------------------------------------------------------------------------------- /R/scale_mlb.R: -------------------------------------------------------------------------------- 1 | # Color and Fill Scales --------------------------------------------------- 2 | 3 | #' Scales for MLB Team Colors 4 | #' 5 | #' @description These functions map MLB team names to their team colors in 6 | #' color and fill aesthetics 7 | #' @inheritParams ggplot2::scale_fill_manual 8 | #' @param type One of `"primary"` or `"secondary"` to decide which colortype to use. 9 | #' @param values If `NULL` (the default) use the internal team color vectors. Otherwise 10 | #' a set of aesthetic values to map data values to. The values 11 | #' will be matched in order (usually alphabetical) with the limits of the 12 | #' scale, or with `breaks` if provided. If this is a named vector, then the 13 | #' values will be matched based on the names instead. Data values that don't 14 | #' match will be given `na.value`. 15 | #' @param guide A function used to create a guide or its name. If `NULL` (the default) 16 | #' no guide will be plotted for this scale. See [ggplot2::guides()] for more information. 17 | #' @param alpha Factor to modify color transparency via a call to [`scales::alpha()`]. 18 | #' If `NA` (the default) no transparency will be applied. Can also be a vector of 19 | #' alphas. All alpha levels must be in range `[0,1]`. 20 | #' @name scale_mlb 21 | #' @return A discrete ggplot2 scale created with [ggplot2::scale_color_manual()] or 22 | #' [ggplot2::scale_fill_manual()]. 23 | #' @aliases NULL 24 | #' @examples 25 | #' \donttest{ 26 | #' library(mlbplotR) 27 | #' library(ggplot2) 28 | #' 29 | #' team_abbr <- valid_team_names() 30 | #' # remove league logos from this example 31 | #' team_abbr <- team_abbr[!team_abbr %in% c("AL", "NL", "MLB")] 32 | #' 33 | #' df <- data.frame( 34 | #' random_value = runif(length(team_abbr), 0, 1), 35 | #' teams = team_abbr 36 | #' ) 37 | #' ggplot(df, aes(x = teams, y = random_value)) + 38 | #' geom_col(aes(color = teams, fill = teams), width = 0.5) + 39 | #' scale_color_mlb(type = "secondary") + 40 | #' scale_fill_mlb(alpha = 0.4) + 41 | #' theme_minimal() + 42 | #' theme(axis.text.x = element_text(angle = 45, hjust = 1)) 43 | #' } 44 | NULL 45 | 46 | #' @rdname scale_mlb 47 | #' @export 48 | scale_color_mlb <- function(type = c("primary", "secondary"), 49 | values = NULL, 50 | ..., 51 | aesthetics = "colour", 52 | breaks = ggplot2::waiver(), 53 | na.value = "grey50", 54 | guide = NULL, 55 | alpha = NA) { 56 | 57 | type <- rlang::arg_match(type) 58 | 59 | if(is.null(values)){ 60 | values <- switch(type, 61 | "primary" = primary_colors, 62 | "secondary" = secondary_colors 63 | ) 64 | } 65 | 66 | if(!is.na(alpha)) values <- scales::alpha(values, alpha = alpha) 67 | 68 | ggplot2::scale_color_manual( 69 | ..., 70 | values = values, 71 | aesthetics = aesthetics, 72 | breaks = breaks, 73 | na.value = na.value, 74 | guide = guide 75 | ) 76 | } 77 | 78 | #' @rdname scale_mlb 79 | #' @export 80 | scale_colour_mlb <- scale_color_mlb 81 | 82 | 83 | #' @rdname scale_mlb 84 | #' @export 85 | scale_fill_mlb <- function(type = c("primary", "secondary"), 86 | values = NULL, 87 | ..., 88 | aesthetics = "fill", 89 | breaks = ggplot2::waiver(), 90 | na.value = "grey50", 91 | guide = NULL, 92 | alpha = NA) { 93 | 94 | type <- rlang::arg_match(type) 95 | 96 | if(is.null(values)){ 97 | values <- switch(type, 98 | "primary" = primary_colors, 99 | "secondary" = secondary_colors 100 | ) 101 | } 102 | 103 | if(!is.na(alpha)) values <- scales::alpha(values, alpha = alpha) 104 | 105 | ggplot2::scale_fill_manual( 106 | ..., 107 | values = values, 108 | aesthetics = aesthetics, 109 | breaks = breaks, 110 | na.value = na.value, 111 | guide = guide 112 | ) 113 | } 114 | 115 | 116 | # Axis Scales ------------------------------------------------------------- 117 | 118 | #' Axis Scales for MLB Team Logos 119 | #' 120 | #' @description 121 | #' `r lifecycle::badge("superseded")` 122 | #' `scale_x_mlb()` and `scale_y_mlb()` have been superceded in favor of `element_*_logo()` functions 123 | #' These functions map MLB team names to their team logos and make 124 | #' them available as axis labels 125 | #' @details The scale translates MLB team abbreviations into raw image 126 | #' html and places the html as axis labels. Because of the way ggplots are 127 | #' constructed, it is necessary to adjust the [`theme()`] after calling this 128 | #' scale. This can be done by calling [`theme_x_mlb()`] or [`theme_y_mlb()`] 129 | #' or alternatively by manually changing the relevant `axis.text` to 130 | #' [`ggtext::element_markdown()`]. However, this will only work if an underlying 131 | #' dependency, "gridtext", is installed with a newer version than 0.1.4 132 | #' @inheritParams ggplot2::scale_x_discrete 133 | #' @param size The logo size in pixels. It is applied as height for an x-scale 134 | #' and as width for an y-scale. 135 | #' @name scale_axes_mlb 136 | #' @return A discrete ggplot2 scale created with [ggplot2::scale_x_discrete()] or 137 | #' [ggplot2::scale_y_discrete()]. 138 | #' @aliases NULL 139 | #' @examples 140 | #' \donttest{ 141 | #' library(mlbplotR) 142 | #' library(ggplot2) 143 | #' 144 | #' team_abbr <- valid_team_names() 145 | #' # remove league logos from this example 146 | #' team_abbr <- team_abbr[!team_abbr %in% c("AL", "NL", "MLB")] 147 | #' 148 | #' df <- data.frame( 149 | #' random_value = runif(length(team_abbr), 0, 1), 150 | #' teams = team_abbr 151 | #' ) 152 | #' 153 | #' if (utils::packageVersion("gridtext") > "0.1.4"){ 154 | #' # use logos for x-axis 155 | #' ggplot(df, aes(x = teams, y = random_value)) + 156 | #' geom_col(aes(color = teams, fill = teams), width = 0.5) + 157 | #' scale_color_mlb(type = "secondary") + 158 | #' scale_fill_mlb(alpha = 0.4) + 159 | #' scale_x_mlb() + 160 | #' theme_minimal() + 161 | #' # theme_*_mlb requires gridtext version > 0.1.4 162 | #' theme_x_mlb() 163 | #' 164 | #' # use logos for y-axis 165 | #' ggplot(df, aes(y = teams, x = random_value)) + 166 | #' geom_col(aes(color = teams, fill = teams), width = 0.5) + 167 | #' scale_color_mlb(type = "secondary") + 168 | #' scale_fill_mlb(alpha = 0.4) + 169 | #' scale_y_mlb() + 170 | #' theme_minimal() + 171 | #' # theme_*_mlb requires gridtext version > 0.1.4 172 | #' theme_y_mlb() 173 | #'} 174 | #' } 175 | NULL 176 | 177 | #' @rdname scale_axes_mlb 178 | #' @export 179 | scale_x_mlb <- function(..., 180 | expand = ggplot2::waiver(), 181 | guide = ggplot2::waiver(), 182 | position = "bottom", 183 | size = 12) { 184 | 185 | position <- rlang::arg_match0(position, c("top", "bottom")) 186 | 187 | ggplot2::scale_x_discrete( 188 | ..., 189 | labels = function(x) { 190 | logo_html(x, type = "height", size = size) 191 | }, 192 | expand = expand, 193 | guide = guide, 194 | position = position 195 | ) 196 | } 197 | 198 | #' @rdname scale_axes_mlb 199 | #' @export 200 | scale_y_mlb <- function(..., 201 | expand = ggplot2::waiver(), 202 | guide = ggplot2::waiver(), 203 | position = "left", 204 | size = 12) { 205 | 206 | position <- rlang::arg_match0(position, c("left", "right")) 207 | 208 | ggplot2::scale_y_discrete( 209 | ..., 210 | labels = function(x) { 211 | logo_html(x, type = "width", size = size) 212 | }, 213 | expand = expand, 214 | guide = guide, 215 | position = position 216 | ) 217 | } 218 | -------------------------------------------------------------------------------- /R/sysdata.rda: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/camdenk/mlbplotR/28dd1d26de2b5ce4785976051a91bf260a8f4237/R/sysdata.rda -------------------------------------------------------------------------------- /R/theme_mlb.R: -------------------------------------------------------------------------------- 1 | #' Theme for MLB Team Logos 2 | #' 3 | #' @description 4 | #' `r lifecycle::badge("superseded")` 5 | #' `theme_x_mlb()` and `theme_y_mlb()` have been superceded in favor of `element_*_logo()` functions 6 | #' These functions are convenience wrappers around a theme call 7 | #' that activates markdown in x-axis and y-axis labels 8 | #' using [`ggtext::element_markdown()`]. 9 | #' @details These functions are a wrapper around the function calls 10 | #' `ggplot2::theme(axis.text.x = ggtext::element_markdown())` as well as 11 | #' `ggplot2::theme(axis.text.y = ggtext::element_markdown())`. 12 | #' They are made to be used in conjunction with [`scale_x_mlb()`] and 13 | #' [`scale_y_mlb()`] respectively. 14 | #' @name theme_mlb 15 | #' @aliases NULL 16 | #' @return A ggplot2 theme created with [ggplot2::theme()]. 17 | #' @seealso [`theme_x_mlb()`], [`theme_y_mlb()`] 18 | #' @examples 19 | #' \donttest{ 20 | #' library(mlbplotR) 21 | #' library(ggplot2) 22 | #' 23 | #' team_abbr <- valid_team_names() 24 | #' # remove conference logos from this example 25 | #' team_abbr <- team_abbr[!team_abbr %in% c("AL", "NL", "MLB")] 26 | #' 27 | #' df <- data.frame( 28 | #' random_value = runif(length(team_abbr), 0, 1), 29 | #' teams = team_abbr 30 | #' ) 31 | #' if (utils::packageVersion("gridtext") > "0.1.4"){ 32 | #' ggplot(df, aes(x = teams, y = random_value)) + 33 | #' geom_col(aes(color = teams, fill = teams), width = 0.5) + 34 | #' scale_color_mlb(type = "secondary") + 35 | #' scale_fill_mlb(alpha = 0.4) + 36 | #' scale_x_mlb() + 37 | #' theme_minimal() + 38 | #' # theme_*_mlb requires gridtext version > 0.1.4 39 | #' theme_x_mlb() 40 | #' } 41 | #' } 42 | NULL 43 | 44 | #' @rdname theme_mlb 45 | #' @export 46 | theme_x_mlb <- function(){ 47 | 48 | if (!is_installed("ggtext")) { 49 | cli::cli_abort(c( 50 | "Package {.val ggtext} required to create this scale.", 51 | 'Please install it with {.var install.packages("ggtext")}' 52 | )) 53 | } 54 | loadNamespace("gridtext", versionCheck = list(op = ">", version = "0.1.4")) 55 | ggplot2::theme(axis.text.x = ggtext::element_markdown()) 56 | } 57 | 58 | #' @rdname theme_mlb 59 | #' @export 60 | theme_y_mlb <- function(){ 61 | if (!is_installed("ggtext")) { 62 | cli::cli_abort(c( 63 | "Package {.val ggtext} required to create this scale.", 64 | 'Please install it with {.var install.packages("ggtext")}' 65 | )) 66 | } 67 | loadNamespace("gridtext", versionCheck = list(op = ">", version = "0.1.4")) 68 | ggplot2::theme(axis.text.y = ggtext::element_markdown()) 69 | } 70 | -------------------------------------------------------------------------------- /R/utils.R: -------------------------------------------------------------------------------- 1 | logo_html <- function(team_abbr, type = c("height", "width"), size = 15){ 2 | type <- rlang::arg_match(type) 3 | logo_urls <- teams_colors_logos$team_logo_espn 4 | names(logo_urls) <- teams_colors_logos$team_abbr 5 | url <- logo_urls[team_abbr] 6 | sprintf("", url, type, size) 7 | } 8 | 9 | 10 | headshot_html <- function(player_id, type = c("height", "width"), size = 25){ 11 | type <- rlang::arg_match(type) 12 | headshot_map <- load_headshots() 13 | player_id <- ifelse(player_id %in% headshot_map$savant_id, player_id, "NA_ID") 14 | headshot_map <- rbind( 15 | headshot_map, 16 | list(savant_id = "NA_ID", espn_headshot = na_headshot()) 17 | ) 18 | joined <- merge( 19 | data.frame(savant_id = player_id), 20 | headshot_map, 21 | by = "savant_id", 22 | all.x = TRUE, 23 | sort = FALSE 24 | ) 25 | url <- joined$espn_headshot 26 | url <- ifelse(grepl(".png", url), url, paste0(url, ".png")) 27 | sprintf("", url, type, size) 28 | } 29 | 30 | 31 | rds_from_url <- function(url) { 32 | con <- url(url) 33 | on.exit(close(con)) 34 | load <- try(readRDS(con), silent = TRUE) 35 | 36 | if (inherits(load, "try-error")) { 37 | warning(paste0("Failed to readRDS from <", url, ">"), call. = FALSE) 38 | return(data.table::data.table()) 39 | } 40 | 41 | data.table::setDT(load) 42 | return(load) 43 | } 44 | 45 | 46 | is_installed <- function(pkg) requireNamespace(pkg, quietly = TRUE) 47 | 48 | na_headshot <- function(mlb_logo = TRUE) if (mlb_logo) "https://a.espncdn.com/combiner/i?img=/i/teamlogos/leagues/500/mlb.png" else "https://raw.githubusercontent.com/camdenk/mlbplotR-data/main/na_gray_headshot.png" 49 | 50 | 51 | `%c%` <- function(x,y){ 52 | ifelse(!is.na(x),x,y) 53 | } 54 | -------------------------------------------------------------------------------- /README.Rmd: -------------------------------------------------------------------------------- 1 | --- 2 | output: github_document 3 | --- 4 | 5 | 6 | 7 | ```{r, include = FALSE} 8 | knitr::opts_chunk$set( 9 | collapse = TRUE, 10 | comment = "#>", 11 | fig.path = "man/figures/README-", 12 | out.width = "100%", 13 | dpi = 600 14 | ) 15 | ``` 16 | 17 | # mlbplotR 18 | 19 | 20 | [![Lifecycle: experimental](https://img.shields.io/badge/lifecycle-experimental-orange.svg?style=flat-square)](https://lifecycle.r-lib.org/articles/stages.html) 21 | [![R-CMD-check](https://github.com/camdenk/mlbplotR/actions/workflows/R-CMD-check.yaml/badge.svg)](https://github.com/camdenk/mlbplotR/actions/workflows/R-CMD-check.yaml) 22 | 23 | 24 | The code for this package was copied heavily from [nflplotR](https://nflplotr.nflverse.com/index.html) with minor changes to support Major League Baseball logos. 25 | 26 | 27 | The goal of mlbplotR is to provide functions and geoms that help with visualizations of MLB related analysis. It provides ggplot2 geoms that do the heavy lifting of plotting MLB logos in high quality, with correct aspect ratio, and possible transparency. 28 | 29 | ## Installation 30 | 31 | The easiest way to get mlbplotR is to install it from [CRAN](https://CRAN.R-project.org) with: 32 | 33 | ``` r 34 | install.packages("mlbplotR") 35 | ``` 36 | 37 | To get a bug fix or use a feature from the development version, you can install the development version from [GitHub](https://github.com/) with: 38 | 39 | ``` r 40 | # install.packages("devtools") 41 | devtools::install_github("camdenk/mlbplotR") 42 | ``` 43 | ## Usage 44 | 45 | Let's plot every team on a grid with some extra customization: 46 | 47 | ```{r every-team, message = FALSE} 48 | library(mlbplotR) 49 | library(ggplot2) 50 | library(dplyr) 51 | 52 | teams_colors_logos <- mlbplotR::load_mlb_teams() |> 53 | dplyr::filter(!team_abbr %in% c("AL", "NL", "MLB")) |> 54 | dplyr::mutate( 55 | a = rep(1:6, 5), 56 | b = sort(rep(1:5, 6), decreasing = TRUE) 57 | ) 58 | 59 | 60 | ggplot2::ggplot(teams_colors_logos, aes(x = a, y = b)) + 61 | mlbplotR::geom_mlb_logos(aes(team_abbr = team_abbr), width = 0.075) + 62 | ggplot2::geom_label(aes(label = team_abbr), nudge_y = -0.35, alpha = 0.5) + 63 | ggplot2::theme_void() 64 | ``` 65 | 66 | There is a [getting started guide](https://camdenk.github.io/mlbplotR/articles/mlbplotR.html) that will walk you through more use cases for the package. 67 | 68 | 69 | ## Contributing 70 | 71 | - [Open an issue](https://github.com/camdenk/mlbplotR/issues/new/choose) if you'd like to request specific data or report a bug/error. 72 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | # mlbplotR 5 | 6 | 7 | 8 | [![Lifecycle: 9 | experimental](https://img.shields.io/badge/lifecycle-experimental-orange.svg?style=flat-square)](https://lifecycle.r-lib.org/articles/stages.html) 10 | [![R-CMD-check](https://github.com/camdenk/mlbplotR/actions/workflows/R-CMD-check.yaml/badge.svg)](https://github.com/camdenk/mlbplotR/actions/workflows/R-CMD-check.yaml) 11 | 12 | 13 | The code for this package was copied heavily from 14 | [nflplotR](https://nflplotr.nflverse.com/index.html) with minor changes 15 | to support Major League Baseball logos. 16 | 17 | The goal of mlbplotR is to provide functions and geoms that help with 18 | visualizations of MLB related analysis. It provides ggplot2 geoms that 19 | do the heavy lifting of plotting MLB logos in high quality, with correct 20 | aspect ratio, and possible transparency. 21 | 22 | ## Installation 23 | 24 | The easiest way to get mlbplotR is to install it from 25 | [CRAN](https://CRAN.R-project.org) with: 26 | 27 | ``` r 28 | install.packages("mlbplotR") 29 | ``` 30 | 31 | To get a bug fix or use a feature from the development version, you can 32 | install the development version from [GitHub](https://github.com/) with: 33 | 34 | ``` r 35 | # install.packages("devtools") 36 | devtools::install_github("camdenk/mlbplotR") 37 | ``` 38 | 39 | ## Usage 40 | 41 | Let’s plot every team on a grid with some extra customization: 42 | 43 | ``` r 44 | library(mlbplotR) 45 | library(ggplot2) 46 | library(dplyr) 47 | 48 | teams_colors_logos <- mlbplotR::load_mlb_teams() |> 49 | dplyr::filter(!team_abbr %in% c("AL", "NL", "MLB")) |> 50 | dplyr::mutate( 51 | a = rep(1:6, 5), 52 | b = sort(rep(1:5, 6), decreasing = TRUE) 53 | ) 54 | 55 | 56 | ggplot2::ggplot(teams_colors_logos, aes(x = a, y = b)) + 57 | mlbplotR::geom_mlb_logos(aes(team_abbr = team_abbr), width = 0.075) + 58 | ggplot2::geom_label(aes(label = team_abbr), nudge_y = -0.35, alpha = 0.5) + 59 | ggplot2::theme_void() 60 | ``` 61 | 62 | 63 | 64 | There is a [getting started 65 | guide](https://camdenk.github.io/mlbplotR/articles/mlbplotR.html) that 66 | will walk you through more use cases for the package. 67 | 68 | ## Contributing 69 | 70 | - [Open an issue](https://github.com/camdenk/mlbplotR/issues/new/choose) 71 | if you’d like to request specific data or report a bug/error. 72 | -------------------------------------------------------------------------------- /_pkgdown.yml: -------------------------------------------------------------------------------- 1 | url: https://camdenk.github.io/mlbplotR/ 2 | template: 3 | bootstrap: 5 4 | 5 | 6 | authors: 7 | Sebastian Carl: 8 | href: https://twitter.com/mrcaseb 9 | Camden Kay: 10 | href: https://twitter.com/k_camden 11 | 12 | 13 | navbar: 14 | structure: 15 | left: [home, intro, reference, articles, tutorials, news] 16 | right: [twitter, github] 17 | components: 18 | home: 19 | title: mlbplotR 20 | icon: fa-home 21 | href: index.html 22 | reference: 23 | icon: "fas fa-code" 24 | text: "Functions" 25 | href: reference/index.html 26 | news: 27 | icon: "fas fa-newspaper" 28 | text: "Changelog" 29 | href: news/index.html 30 | twitter: 31 | icon: "fab fa-twitter fa-lg" 32 | href: http://twitter.com/mlbplotR 33 | github: 34 | icon: "fab fa-github fa-lg" 35 | href: https://github.com/camdenk/mlbplotR/ 36 | 37 | 38 | 39 | reference: 40 | - title: Geoms 41 | contents: starts_with("geom") 42 | - title: GT 43 | contents: starts_with("gt") 44 | - title: Theme Elements 45 | contents: starts_with("element") 46 | - title: Scales 47 | contents: 48 | - '`scale_mlb`' 49 | - title: Tiers 50 | contents: ends_with("tiers") 51 | - title: Utilities 52 | contents: 53 | - '`load_mlb_teams`' 54 | - '`load_milb_teams`' 55 | - '`load_headshots`' 56 | - '`clean_team_abbrs`' 57 | - '`valid_team_names`' 58 | - '`mlb_team_factor`' 59 | - '`ggpreview`' 60 | - title: Superceded 61 | contents: 62 | - '`theme_mlb`' 63 | - '`scale_axes_mlb`' 64 | -------------------------------------------------------------------------------- /cran-comments.md: -------------------------------------------------------------------------------- 1 | ## R CMD check results 2 | 3 | 0 errors | 0 warnings | 0 notes 4 | 5 | ## revdepcheck results 6 | 7 | There are currently no downstream dependencies for this package 8 | -------------------------------------------------------------------------------- /data-raw/.gitignore: -------------------------------------------------------------------------------- 1 | logo.svg 2 | -------------------------------------------------------------------------------- /data-raw/build_internal_data.R: -------------------------------------------------------------------------------- 1 | # Save raw logos in internal data for more speed 2 | teams_colors_logos <- readr::read_csv("./data-raw/MLB_Colors_Logos.csv") 3 | 4 | 5 | # Load in old versions and only overwrite what we want 6 | 7 | old_logo_lists <- readRDS("./data-raw/old_data/old_logo_lists.rds") 8 | logo_list <- old_logo_lists[[1]] 9 | scoreboard_logo_list <- old_logo_lists[[2]] 10 | 11 | # Correct for Oakland's shift 12 | names(logo_list)[20] <- "ATH" 13 | names(scoreboard_logo_list)[20] <- "ATH" 14 | 15 | 16 | 17 | # logo_list <- lapply(teams_colors_logos$team_abbr, function(x){ 18 | # url <- teams_colors_logos$team_logo_espn[teams_colors_logos$team_abbr == x] 19 | # curl::curl_fetch_memory(url)$content 20 | # }) 21 | # 22 | # logo_list <- rlang::set_names(logo_list, teams_colors_logos$team_abbr) 23 | 24 | # Only update Arizona because of their logo change. Otherwise, keep the old 25 | # ESPN logos 26 | az_url <- teams_colors_logos$team_logo_espn[teams_colors_logos$team_abbr == "AZ"] 27 | logo_list$AZ <- curl::curl_fetch_memory(az_url)$content 28 | 29 | 30 | 31 | primary_colors <- teams_colors_logos$team_color 32 | names(primary_colors) <- teams_colors_logos$team_abbr 33 | 34 | secondary_colors <- teams_colors_logos$team_color2 35 | names(secondary_colors) <- teams_colors_logos$team_abbr 36 | 37 | logo_urls <- teams_colors_logos$team_logo_espn 38 | names(logo_urls) <- teams_colors_logos$team_abbr 39 | 40 | scoreboard_logo_urls <- teams_colors_logos$team_scoreboard_logo_espn 41 | names(scoreboard_logo_urls) <- teams_colors_logos$team_abbr 42 | 43 | 44 | # scoreboard_logo_list <- lapply(teams_colors_logos$team_abbr, function(x){ 45 | # url <- teams_colors_logos$team_scoreboard_logo_espn[teams_colors_logos$team_abbr == x] 46 | # curl::curl_fetch_memory(url)$content 47 | # }) 48 | # 49 | # 50 | # scoreboard_logo_list <- rlang::set_names(scoreboard_logo_list, teams_colors_logos$team_abbr) 51 | 52 | az_scoreboard_url <- teams_colors_logos$team_scoreboard_logo_espn[teams_colors_logos$team_abbr == "AZ"] 53 | scoreboard_logo_list$AZ <- curl::curl_fetch_memory(az_scoreboard_url)$content 54 | 55 | 56 | light_cap_logo_list <- lapply(teams_colors_logos$team_abbr, function(x){ 57 | url <- teams_colors_logos$team_cap_logo_on_light[teams_colors_logos$team_abbr == x] 58 | #curl::curl_fetch_memory(url)$content 59 | }) 60 | 61 | 62 | 63 | light_logo_list <- rlang::set_names(light_cap_logo_list, teams_colors_logos$team_abbr) 64 | 65 | 66 | 67 | dark_cap_logo_list <- lapply(teams_colors_logos$team_abbr, function(x){ 68 | url <- teams_colors_logos$team_cap_logo_on_dark[teams_colors_logos$team_abbr == x] 69 | #curl::curl_fetch_memory(url)$content 70 | }) 71 | 72 | dark_logo_list <- rlang::set_names(dark_cap_logo_list, teams_colors_logos$team_abbr) 73 | 74 | 75 | 76 | dot_logo_list <- lapply(teams_colors_logos$team_abbr, function(x){ 77 | url <- teams_colors_logos$team_dot_logo[teams_colors_logos$team_abbr == x] 78 | # curl::curl_fetch_memory(url)$content 79 | }) 80 | 81 | dot_logo_list <- rlang::set_names(dot_logo_list, teams_colors_logos$team_abbr) 82 | 83 | 84 | # Build team name df that'll be used to clean abbreviations before plotting 85 | 86 | team_data <- tibble::tribble(~team, ~alternate, 87 | "AZ", "AZ", 88 | "AZ", "ARI", 89 | "AZ", "ARZ", 90 | "ATL", "ATL", 91 | "BAL", "BAL", 92 | "BOS", "BOS", 93 | "CHC", "CHC", 94 | "CHC", "CHI", 95 | "CWS", "CWS", 96 | "CWS", "CHW", 97 | "CIN", "CIN", 98 | "CLE", "CLE", 99 | "COL", "COL", 100 | "DET", "DET", 101 | "HOU", "HOU", 102 | "KC" , "KC", 103 | "KC" , "KCR", 104 | "LAA", "LAA", 105 | "LAA", "ANA", 106 | "LAD", "LAD", 107 | "LAD", "LA", 108 | "MIA", "MIA", 109 | "MIL", "MIL", 110 | "MIN", "MIN", 111 | "NYM", "NYM", 112 | "NYM", "NY", 113 | "NYY", "NYY", 114 | "ATH", "OAK", 115 | "ATH", "ATH", 116 | "PHI", "PHI", 117 | "PIT", "PIT", 118 | "SD" , "SD", 119 | "SD" , "SDP", 120 | "SF" , "SF", 121 | "SF" , "SFG", 122 | "SEA", "SEA", 123 | "STL", "STL", 124 | "TB" , "TB", 125 | "TB" , "TBR", 126 | "TEX", "TEX", 127 | "TOR", "TOR", 128 | "WSH", "WSH", 129 | "WSH", "WAS", 130 | "WSH", "WSN", 131 | "AL", "AL", 132 | "NL", "NL", 133 | "MLB", "MLB", 134 | "MLB", "---", 135 | "MLB", "- - -") |> 136 | dplyr::select(alternate, team) |> 137 | tibble::deframe() 138 | 139 | 140 | 141 | 142 | 143 | usethis::use_data(teams_colors_logos, logo_list, 144 | primary_colors, secondary_colors, 145 | #logo_urls, scoreboard_logo_urls, These are unnecessary to store 146 | scoreboard_logo_list, 147 | 148 | light_logo_list, dark_logo_list, 149 | dot_logo_list, 150 | team_data, 151 | internal = TRUE, overwrite = TRUE) 152 | -------------------------------------------------------------------------------- /data-raw/build_logo.R: -------------------------------------------------------------------------------- 1 | library(hexSticker) 2 | library(tidyverse) 3 | library(mlbplotR) 4 | library(ggplot2) 5 | library(svglite) 6 | 7 | team_abbr <- valid_team_names() 8 | # remove conference logos from this example 9 | team_abbr <- team_abbr[!team_abbr %in% c("AL", "NL", "MLB")] 10 | 11 | x_loc = c(3, 4, 1:6, 1, 6, rep(1:6,3), 3, 4) 12 | y_loc = c(7, 7, rep(6:6, 6), 5, 5, sort(rep(2:4, 6), decreasing = TRUE), 1, 1) 13 | 14 | df <- data.frame( 15 | a = x_loc, 16 | b = y_loc, 17 | teams = team_abbr 18 | ) 19 | 20 | p <- ggplot(df, aes(x = a, y = b)) + 21 | geom_mlb_logos(aes(team_savant_abbr = teams), width = 0.08, alpha = 0.75) + 22 | coord_cartesian(xlim = c(0.5,6.5), ylim = c(0.5,8.5)) + 23 | theme_void() + 24 | theme_transparent() 25 | 26 | sticker( 27 | p, 28 | package = "mlbplotR", 29 | p_y = 1.25, 30 | p_size = 6, 31 | p_color = "white", 32 | s_x = 1, 33 | s_y = 1.125, 34 | s_width = 1.9, 35 | s_height = 2, 36 | spotlight = TRUE, 37 | l_y = 1.25, 38 | l_alpha = 0.2, 39 | l_width = 5, 40 | l_height = 5, 41 | h_fill = "#575757", 42 | h_color = "#404040", 43 | h_size = 0.8, 44 | filename = "data-raw/logo.svg", 45 | dpi = 600 46 | ) 47 | 48 | #usethis::use_logo("./data-raw/logo.png") 49 | 50 | 51 | # Github preview logo ------------------------------------------------------------------------------ 52 | 53 | # ggplot() + 54 | # mlbplotR::geom_from_path(aes(x = 0, y = 0, path = "./data-raw/logo.png")) + 55 | # theme_void() 56 | # 57 | # 58 | # ggsave("./data-raw/preview logo.png", width = 1280, height = 640, dpi = "retina", units = "px") 59 | -------------------------------------------------------------------------------- /data-raw/generate_headshot_rds.R: -------------------------------------------------------------------------------- 1 | 2 | headshots <- readr::read_csv("https://github.com/camdenk/mlbplotR-data/raw/main/Player-IDs.csv") 3 | 4 | # saveRDS(headshots, "./data-raw/Player-IDs.rds") 5 | saveRDS(headshots, "~/Desktop/mlbplotR-data/Player-IDs.rds") 6 | 7 | -------------------------------------------------------------------------------- /data-raw/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/camdenk/mlbplotR/28dd1d26de2b5ce4785976051a91bf260a8f4237/data-raw/logo.png -------------------------------------------------------------------------------- /data-raw/old_data/old_logo_lists.rds: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/camdenk/mlbplotR/28dd1d26de2b5ce4785976051a91bf260a8f4237/data-raw/old_data/old_logo_lists.rds -------------------------------------------------------------------------------- /data-raw/old_data/saving_internal_data_from_previous_version.R: -------------------------------------------------------------------------------- 1 | # ESPN has changed the logos for MLB teams, offering a smaller variety 2 | # of logo options, mostly utilizing tertiary logos that the teams 3 | # themselves don't use. 4 | # 5 | # So this script was made to recycle older logo versions for 6 | # continued use 7 | 8 | 9 | # Only saving the internal ESPN logos that we kept their info, so not the svgs 10 | # from MLB.com 11 | 12 | 13 | old_logo_list <- mlbplotR:::logo_list 14 | 15 | old_scoreboard_logo_list <- mlbplotR:::scoreboard_logo_list 16 | 17 | 18 | old_lists <- list(old_logo_list, old_scoreboard_logo_list) 19 | 20 | 21 | saveRDS(old_lists, "./data-raw/old_data/old_logo_lists.rds") 22 | -------------------------------------------------------------------------------- /data-raw/preview logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/camdenk/mlbplotR/28dd1d26de2b5ce4785976051a91bf260a8f4237/data-raw/preview logo.png -------------------------------------------------------------------------------- /man/clean_team_abbrs.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/load_data.R 3 | \name{clean_team_abbrs} 4 | \alias{clean_team_abbrs} 5 | \title{Standardize MLB Team Abbreviations} 6 | \usage{ 7 | clean_team_abbrs(abbr, keep_non_matches = TRUE) 8 | } 9 | \arguments{ 10 | \item{abbr}{a character vector of abbreviations} 11 | 12 | \item{keep_non_matches}{will non-matches be kept in the vector?} 13 | } 14 | \value{ 15 | A character vector with the length of \code{abbr} and cleaned team abbreviations 16 | if they are included in \code{team_data}. Non matches may be replaced 17 | with \code{NA} (depending on the value of \code{keep_non_matches}). 18 | } 19 | \description{ 20 | This function standardizes MLB team abbreviations to Baseball Savant defaults. 21 | This helps for joins and plotting 22 | } 23 | \examples{ 24 | \donttest{ 25 | x <- c("PIE", "STL", "WSN", "CWS", "CHW") 26 | # use current location and keep non matches 27 | clean_team_abbrs(x) 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /man/element.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/theme_elements.R 3 | \name{element} 4 | \alias{element_mlb_logo} 5 | \alias{element_mlb_scoreboard_logo} 6 | \alias{element_mlb_dot_logo} 7 | \alias{element_mlb_dark_cap_logo} 8 | \alias{element_mlb_light_cap_logo} 9 | \alias{element_mlb_headshot} 10 | \alias{element_mlb_dot_headshot} 11 | \alias{element_path} 12 | \alias{element_milb_logo} 13 | \alias{element_milb_light_cap_logo} 14 | \alias{element_milb_dot_logo} 15 | \alias{element_milb_dot_headshot} 16 | \title{Theme Elements for Image Grobs} 17 | \usage{ 18 | element_mlb_logo( 19 | alpha = NULL, 20 | colour = NA, 21 | hjust = NULL, 22 | vjust = NULL, 23 | color = NULL, 24 | size = 0.5 25 | ) 26 | 27 | element_mlb_scoreboard_logo( 28 | alpha = NULL, 29 | colour = NA, 30 | hjust = NULL, 31 | vjust = NULL, 32 | color = NULL, 33 | size = 0.5 34 | ) 35 | 36 | element_mlb_dot_logo( 37 | alpha = NULL, 38 | colour = NA, 39 | hjust = NULL, 40 | vjust = NULL, 41 | color = NULL, 42 | size = 0.5 43 | ) 44 | 45 | element_mlb_dark_cap_logo( 46 | alpha = NULL, 47 | colour = NA, 48 | hjust = NULL, 49 | vjust = NULL, 50 | color = NULL, 51 | size = 0.5 52 | ) 53 | 54 | element_mlb_light_cap_logo( 55 | alpha = NULL, 56 | colour = NA, 57 | hjust = NULL, 58 | vjust = NULL, 59 | color = NULL, 60 | size = 0.5 61 | ) 62 | 63 | element_mlb_headshot( 64 | alpha = NULL, 65 | colour = NA, 66 | hjust = NULL, 67 | vjust = NULL, 68 | color = NULL, 69 | size = 0.5 70 | ) 71 | 72 | element_mlb_dot_headshot( 73 | alpha = NULL, 74 | colour = NA, 75 | hjust = NULL, 76 | vjust = NULL, 77 | color = NULL, 78 | size = 0.5 79 | ) 80 | 81 | element_path( 82 | alpha = NULL, 83 | colour = NA, 84 | hjust = NULL, 85 | vjust = NULL, 86 | color = NULL, 87 | size = 0.5 88 | ) 89 | 90 | element_milb_logo( 91 | alpha = NULL, 92 | colour = NA, 93 | hjust = NULL, 94 | vjust = NULL, 95 | color = NULL, 96 | size = 0.5 97 | ) 98 | 99 | element_milb_light_cap_logo( 100 | alpha = NULL, 101 | colour = NA, 102 | hjust = NULL, 103 | vjust = NULL, 104 | color = NULL, 105 | size = 0.5 106 | ) 107 | 108 | element_milb_dot_logo( 109 | alpha = NULL, 110 | colour = NA, 111 | hjust = NULL, 112 | vjust = NULL, 113 | color = NULL, 114 | size = 0.5 115 | ) 116 | 117 | element_milb_dot_headshot( 118 | alpha = NULL, 119 | colour = NA, 120 | hjust = NULL, 121 | vjust = NULL, 122 | color = NULL, 123 | size = 0.5 124 | ) 125 | } 126 | \arguments{ 127 | \item{alpha}{The alpha channel, i.e. transparency level, as a numerical value 128 | between 0 and 1.} 129 | 130 | \item{colour, color}{The image will be colorized with this color. Use the 131 | special character \code{"b/w"} to set it to black and white. For more information 132 | on valid color names in ggplot2 see 133 | \url{https://ggplot2.tidyverse.org/articles/ggplot2-specs.html?q=colour#colour-and-fill}.} 134 | 135 | \item{hjust, vjust}{The horizontal and vertical adjustment respectively. 136 | Must be a numerical value between 0 and 1.} 137 | 138 | \item{size}{The output grob size in \code{cm} (!).} 139 | } 140 | \value{ 141 | An S3 object of class \code{element}. 142 | } 143 | \description{ 144 | In conjunction with the \link[ggplot2:theme]{ggplot2::theme} system, the following \code{element_} 145 | functions enable images in non-data components of the plot, e.g. axis text. 146 | \itemize{ 147 | \item \code{element_mlb_logo()}, \code{element_mlb_scoreboard_logo()}, \code{element_mlb_dot_logo()}: draws MLB team logos instead of their abbreviations 148 | \item \code{element_milb_logo}, \code{element_milb_light_cap_logo()}, and \code{element_milb_dot_logo}: draws MiLB team logos instead of their team names 149 | \item \code{element_mlb_dark_cap_logo()} and \code{element_mlb_light_cap_logo()}: draws MLB team cap logos instead of their abbreviations 150 | \item \code{element_mlb_headshot()} and \code{element_milb_dot_headshot()}: draws MLB player headshots instead of their MLB IDs 151 | \item \code{element_milb_dot_headshot()}: draws MiLB player headshots instead of their MLB IDs 152 | \item \code{element_path()}: draws images from valid image URLs instead of the URL. 153 | } 154 | } 155 | \details{ 156 | The elements translate MLB team abbreviations or MLB player IDs 157 | into logo images or headshots, respectively. 158 | } 159 | \examples{ 160 | \donttest{ 161 | library(mlbplotR) 162 | library(ggplot2) 163 | 164 | team_abbr <- valid_team_names() 165 | # remove league logos from this example 166 | team_abbr <- team_abbr[!team_abbr \%in\% c("AL", "NL", "MLB")] 167 | 168 | df <- data.frame( 169 | random_value = runif(length(team_abbr), 0, 1), 170 | teams = team_abbr 171 | ) 172 | 173 | # use logos for x-axis 174 | ggplot(df, aes(x = teams, y = random_value)) + 175 | geom_col(aes(color = teams, fill = teams), width = 0.5) + 176 | scale_color_mlb(type = "secondary") + 177 | scale_fill_mlb(alpha = 0.4) + 178 | theme_minimal() + 179 | theme(axis.text.x = element_mlb_logo()) 180 | 181 | # use logos for y-axis 182 | ggplot(df, aes(y = teams, x = random_value)) + 183 | geom_col(aes(color = teams, fill = teams), width = 0.5) + 184 | scale_color_mlb(type = "secondary") + 185 | scale_fill_mlb(alpha = 0.4) + 186 | theme_minimal() + 187 | theme(axis.text.y = element_mlb_logo()) 188 | 189 | ############################################################################# 190 | # Headshot Examples 191 | ############################################################################# 192 | library(mlbplotR) 193 | library(ggplot2) 194 | 195 | 196 | dfh <- data.frame( 197 | random_value = runif(9, 0, 1), 198 | player_id = c("594798", 199 | "592450", 200 | "605141", 201 | "665742", 202 | "545361", 203 | "665487", 204 | "571448", 205 | "0", 206 | "543037") 207 | ) 208 | 209 | # use headshots for x-axis 210 | ggplot(dfh, aes(x = player_id, y = random_value)) + 211 | geom_col(width = 0.5) + 212 | theme_minimal() + 213 | theme(axis.text.x = element_mlb_headshot()) 214 | 215 | # use headshots for y-axis 216 | ggplot(dfh, aes(y = player_id, x = random_value)) + 217 | geom_col(width = 0.5) + 218 | theme_minimal() + 219 | theme(axis.text.y = element_mlb_headshot()) 220 | } 221 | } 222 | \seealso{ 223 | \code{\link[=geom_mlb_logos]{geom_mlb_logos()}}, \code{\link[=geom_mlb_headshots]{geom_mlb_headshots()}}, and \code{\link[=geom_from_path]{geom_from_path()}} 224 | for more information on valid team abbreviations, player ids, and other 225 | parameters. 226 | } 227 | -------------------------------------------------------------------------------- /man/figures/README-every-team-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/camdenk/mlbplotR/28dd1d26de2b5ce4785976051a91bf260a8f4237/man/figures/README-every-team-1.png -------------------------------------------------------------------------------- /man/figures/lifecycle-archived.svg: -------------------------------------------------------------------------------- 1 | lifecyclelifecyclearchivedarchived -------------------------------------------------------------------------------- /man/figures/lifecycle-defunct.svg: -------------------------------------------------------------------------------- 1 | lifecyclelifecycledefunctdefunct -------------------------------------------------------------------------------- /man/figures/lifecycle-deprecated.svg: -------------------------------------------------------------------------------- 1 | lifecyclelifecycledeprecateddeprecated -------------------------------------------------------------------------------- /man/figures/lifecycle-experimental.svg: -------------------------------------------------------------------------------- 1 | lifecyclelifecycleexperimentalexperimental -------------------------------------------------------------------------------- /man/figures/lifecycle-maturing.svg: -------------------------------------------------------------------------------- 1 | lifecyclelifecyclematuringmaturing -------------------------------------------------------------------------------- /man/figures/lifecycle-questioning.svg: -------------------------------------------------------------------------------- 1 | lifecyclelifecyclequestioningquestioning -------------------------------------------------------------------------------- /man/figures/lifecycle-stable.svg: -------------------------------------------------------------------------------- 1 | lifecyclelifecyclestablestable -------------------------------------------------------------------------------- /man/figures/lifecycle-superseded.svg: -------------------------------------------------------------------------------- 1 | lifecyclelifecyclesupersededsuperseded -------------------------------------------------------------------------------- /man/figures/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/camdenk/mlbplotR/28dd1d26de2b5ce4785976051a91bf260a8f4237/man/figures/logo.png -------------------------------------------------------------------------------- /man/geom_cap_logos.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/geom_cap_logos.R 3 | \name{geom_cap_logos} 4 | \alias{geom_cap_logos} 5 | \alias{geom_mlb_dark_cap_logos} 6 | \alias{geom_mlb_light_cap_logos} 7 | \title{ggplot2 Layer for Visualizing MLB Team Cap Logos} 8 | \usage{ 9 | geom_mlb_dark_cap_logos( 10 | mapping = NULL, 11 | data = NULL, 12 | stat = "identity", 13 | position = "identity", 14 | ..., 15 | nudge_x = 0, 16 | nudge_y = 0, 17 | na.rm = FALSE, 18 | show.legend = FALSE, 19 | inherit.aes = TRUE 20 | ) 21 | 22 | geom_mlb_light_cap_logos( 23 | mapping = NULL, 24 | data = NULL, 25 | stat = "identity", 26 | position = "identity", 27 | ..., 28 | nudge_x = 0, 29 | nudge_y = 0, 30 | na.rm = FALSE, 31 | show.legend = FALSE, 32 | inherit.aes = TRUE 33 | ) 34 | } 35 | \arguments{ 36 | \item{mapping}{Set of aesthetic mappings created by \code{\link[ggplot2:aes]{aes()}}. If specified and 37 | \code{inherit.aes = TRUE} (the default), it is combined with the default mapping 38 | at the top level of the plot. You must supply \code{mapping} if there is no plot 39 | mapping.} 40 | 41 | \item{data}{The data to be displayed in this layer. There are three 42 | options: 43 | 44 | If \code{NULL}, the default, the data is inherited from the plot 45 | data as specified in the call to \code{\link[ggplot2:ggplot]{ggplot()}}. 46 | 47 | A \code{data.frame}, or other object, will override the plot 48 | data. All objects will be fortified to produce a data frame. See 49 | \code{\link[ggplot2:fortify]{fortify()}} for which variables will be created. 50 | 51 | A \code{function} will be called with a single argument, 52 | the plot data. The return value must be a \code{data.frame}, and 53 | will be used as the layer data. A \code{function} can be created 54 | from a \code{formula} (e.g. \code{~ head(.x, 10)}).} 55 | 56 | \item{stat}{The statistical transformation to use on the data for this layer. 57 | When using a \verb{geom_*()} function to construct a layer, the \code{stat} 58 | argument can be used the override the default coupling between geoms and 59 | stats. The \code{stat} argument accepts the following: 60 | \itemize{ 61 | \item A \code{Stat} ggproto subclass, for example \code{StatCount}. 62 | \item A string naming the stat. To give the stat as a string, strip the 63 | function name of the \code{stat_} prefix. For example, to use \code{stat_count()}, 64 | give the stat as \code{"count"}. 65 | \item For more information and other ways to specify the stat, see the 66 | \link[ggplot2:layer_stats]{layer stat} documentation. 67 | }} 68 | 69 | \item{position}{A position adjustment to use on the data for this layer. This 70 | can be used in various ways, including to prevent overplotting and 71 | improving the display. The \code{position} argument accepts the following: 72 | \itemize{ 73 | \item The result of calling a position function, such as \code{position_jitter()}. 74 | This method allows for passing extra arguments to the position. 75 | \item A string naming the position adjustment. To give the position as a 76 | string, strip the function name of the \code{position_} prefix. For example, 77 | to use \code{position_jitter()}, give the position as \code{"jitter"}. 78 | \item For more information and other ways to specify the position, see the 79 | \link[ggplot2:layer_positions]{layer position} documentation. 80 | }} 81 | 82 | \item{...}{Other arguments passed on to \code{\link[ggplot2:layer]{ggplot2::layer()}}. These are 83 | often aesthetics, used to set an aesthetic to a fixed value. See the below 84 | section "Aesthetics" for a full list of possible arguments.} 85 | 86 | \item{nudge_x, nudge_y}{Horizontal and vertical adjustment to nudge labels by. 87 | Useful for offsetting text from points, particularly on discrete scales. 88 | Cannot be jointly specified with \code{position}.} 89 | 90 | \item{na.rm}{If \code{FALSE}, the default, missing values are removed with 91 | a warning. If \code{TRUE}, missing values are silently removed.} 92 | 93 | \item{show.legend}{logical. Should this layer be included in the legends? 94 | \code{NA}, the default, includes if any aesthetics are mapped. 95 | \code{FALSE} never includes, and \code{TRUE} always includes. 96 | It can also be a named logical vector to finely select the aesthetics to 97 | display.} 98 | 99 | \item{inherit.aes}{If \code{FALSE}, overrides the default aesthetics, 100 | rather than combining with them. This is most useful for helper functions 101 | that define both data and aesthetics and shouldn't inherit behaviour from 102 | the default plot specification, e.g. \code{\link[ggplot2:borders]{borders()}}.} 103 | } 104 | \value{ 105 | A ggplot2 layer (\code{\link[ggplot2:layer]{ggplot2::layer()}}) that can be added to a plot 106 | created with \code{\link[ggplot2:ggplot]{ggplot2::ggplot()}}. 107 | } 108 | \description{ 109 | \code{geom_mlb_dark_cap_logos()} and \code{geom_mlb_light_cap_logos()} 110 | are used to plot MLB team cap and league logos instead of points in a 111 | ggplot. It requires x, y aesthetics as well as a valid MLB team 112 | abbreviation. The latter can be checked with \code{\link[=valid_team_names]{valid_team_names()}} but is 113 | also cleaned before being plotted. 114 | } 115 | \section{Aesthetics}{ 116 | 117 | \code{geom_mlb_dark_cap_logos()} and \code{geom_mlb_light_cap_logos()} understand the following aesthetics: 118 | \describe{ 119 | \item{\code{x}}{ - The x-coordinate. Required.} 120 | \item{\code{y}}{ - The y-coordinate. Required.} 121 | \item{\code{team_abbr}}{ - The team abbreviation. Need to use Savant's abbreviation. Required.} 122 | \item{\code{alpha = NULL}}{ - The alpha channel, i.e. transparency level, as a numerical value between 0 and 1.} 123 | \item{\code{colour = NULL}}{ - The image will be colourized with this colour. Use the special character \code{"b/w"} to set it to black and white. For more information on valid colour names in ggplot2 see \url{https://ggplot2.tidyverse.org/articles/ggplot2-specs.html?q=colour#colour-and-fill}} 124 | \item{\code{angle = 0}}{ - The angle of the image as a numerical value between 0° and 360°.} 125 | \item{\code{hjust = 0.5}}{ - The horizontal adjustment relative to the given x coordinate. Must be a numerical value between 0 and 1.} 126 | \item{\code{vjust = 0.5}}{ - The vertical adjustment relative to the given y coordinate. Must be a numerical value between 0 and 1.} 127 | \item{\code{height = 1.0}}{ - The desired height of the image in \code{npc} (Normalised Parent Coordinates). 128 | The default value is set to 1.0 which is \emph{big} but it is necessary 129 | because all used values are computed relative to the default. 130 | A typical size is \code{height = 0.1} (see below examples). 131 | For cap logos, the scaling works better when adjusting height and not width.} 132 | \item{\code{width = 1.0}}{ - The desired width of the image in \code{npc} (Normalised Parent Coordinates). 133 | The default value is set to 1.0 which is \emph{big} but it is necessary 134 | because all used values are computed relative to the default. 135 | A typical size is \code{height = 0.075} (see below examples). 136 | For cap logos, the scaling works better when adjusting height and not width.} 137 | } 138 | } 139 | 140 | \examples{ 141 | \donttest{ 142 | library(mlbplotR) 143 | library(ggplot2) 144 | 145 | team_abbr <- valid_team_names() 146 | # remove conference logos from this example 147 | team_abbr <- team_abbr[!team_abbr \%in\% c("NL", "AL", "MLB")] 148 | 149 | df <- data.frame( 150 | a = rep(1:6, 5), 151 | b = sort(rep(1:5, 6), decreasing = TRUE), 152 | teams = team_abbr 153 | ) 154 | 155 | # keep alpha == 1 for all teams including an "A" 156 | matches <- grepl("A", team_abbr) 157 | df$alpha <- ifelse(matches, 1, 0.2) 158 | # also set a custom fill colour for the non "A" teams 159 | df$colour <- ifelse(matches, NA, "gray") 160 | 161 | # scatterplot of all logos 162 | ggplot(df, aes(x = a, y = b)) + 163 | geom_mlb_dark_cap_logos(aes(team_abbr = teams), height = 0.075) + 164 | geom_label(aes(label = teams), nudge_y = -0.35, alpha = 0.5) + 165 | theme_void() 166 | 167 | # apply alpha via an aesthetic from inside the dataset `df` 168 | # please note that you have to add scale_alpha_identity() to use the alpha 169 | # values in your dataset! 170 | ggplot(df, aes(x = a, y = b)) + 171 | geom_mlb_dark_cap_logos(aes(team_abbr = teams, alpha = alpha), height = 0.075) + 172 | geom_label(aes(label = teams), nudge_y = -0.35, alpha = 0.5) + 173 | scale_alpha_identity() + 174 | theme_void() 175 | 176 | # apply alpha and colour via an aesthetic from inside the dataset `df` 177 | # please note that you have to add scale_alpha_identity() as well as 178 | # scale_colour_identity() to use the alpha and colour values in your dataset! 179 | ggplot(df, aes(x = a, y = b)) + 180 | geom_mlb_light_cap_logos(aes(team_abbr = teams, alpha = alpha, colour = colour), height = 0.075) + 181 | geom_label(aes(label = teams), nudge_y = -0.35, alpha = 0.5) + 182 | scale_alpha_identity() + 183 | scale_colour_identity() + 184 | theme_void() 185 | 186 | # apply alpha as constant for all logos 187 | ggplot(df, aes(x = a, y = b)) + 188 | geom_mlb_light_cap_logos(aes(team_abbr = teams), height = 0.075, alpha = 0.6) + 189 | geom_label(aes(label = teams), nudge_y = -0.35, alpha = 0.5) + 190 | theme_void() 191 | 192 | # it's also possible to plot league logos 193 | league <- data.frame(a = 1:3, b = 0, teams = c("AL", "NL", "MLB")) 194 | ggplot(league, aes(x = a, y = b)) + 195 | geom_mlb_dark_cap_logos(aes(team_abbr = teams), width = 0.3) + 196 | geom_label(aes(label = teams), nudge_y = -0.4, alpha = 0.5) + 197 | coord_cartesian(xlim = c(0.5,3.5), ylim = c(-0.75,.75)) + 198 | theme_void() 199 | } 200 | } 201 | -------------------------------------------------------------------------------- /man/geom_from_path.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/geom_from_path.R 3 | \name{geom_from_path} 4 | \alias{geom_from_path} 5 | \title{ggplot2 Layer for Visualizing Images from URLs or Local Paths} 6 | \usage{ 7 | geom_from_path( 8 | mapping = NULL, 9 | data = NULL, 10 | stat = "identity", 11 | position = "identity", 12 | ..., 13 | nudge_x = 0, 14 | nudge_y = 0, 15 | na.rm = FALSE, 16 | show.legend = FALSE, 17 | inherit.aes = TRUE 18 | ) 19 | } 20 | \arguments{ 21 | \item{mapping}{Set of aesthetic mappings created by \code{\link[ggplot2:aes]{aes()}}. If specified and 22 | \code{inherit.aes = TRUE} (the default), it is combined with the default mapping 23 | at the top level of the plot. You must supply \code{mapping} if there is no plot 24 | mapping.} 25 | 26 | \item{data}{The data to be displayed in this layer. There are three 27 | options: 28 | 29 | If \code{NULL}, the default, the data is inherited from the plot 30 | data as specified in the call to \code{\link[ggplot2:ggplot]{ggplot()}}. 31 | 32 | A \code{data.frame}, or other object, will override the plot 33 | data. All objects will be fortified to produce a data frame. See 34 | \code{\link[ggplot2:fortify]{fortify()}} for which variables will be created. 35 | 36 | A \code{function} will be called with a single argument, 37 | the plot data. The return value must be a \code{data.frame}, and 38 | will be used as the layer data. A \code{function} can be created 39 | from a \code{formula} (e.g. \code{~ head(.x, 10)}).} 40 | 41 | \item{stat}{The statistical transformation to use on the data for this layer. 42 | When using a \verb{geom_*()} function to construct a layer, the \code{stat} 43 | argument can be used the override the default coupling between geoms and 44 | stats. The \code{stat} argument accepts the following: 45 | \itemize{ 46 | \item A \code{Stat} ggproto subclass, for example \code{StatCount}. 47 | \item A string naming the stat. To give the stat as a string, strip the 48 | function name of the \code{stat_} prefix. For example, to use \code{stat_count()}, 49 | give the stat as \code{"count"}. 50 | \item For more information and other ways to specify the stat, see the 51 | \link[ggplot2:layer_stats]{layer stat} documentation. 52 | }} 53 | 54 | \item{position}{A position adjustment to use on the data for this layer. This 55 | can be used in various ways, including to prevent overplotting and 56 | improving the display. The \code{position} argument accepts the following: 57 | \itemize{ 58 | \item The result of calling a position function, such as \code{position_jitter()}. 59 | This method allows for passing extra arguments to the position. 60 | \item A string naming the position adjustment. To give the position as a 61 | string, strip the function name of the \code{position_} prefix. For example, 62 | to use \code{position_jitter()}, give the position as \code{"jitter"}. 63 | \item For more information and other ways to specify the position, see the 64 | \link[ggplot2:layer_positions]{layer position} documentation. 65 | }} 66 | 67 | \item{...}{Other arguments passed on to \code{\link[ggplot2:layer]{ggplot2::layer()}}. These are 68 | often aesthetics, used to set an aesthetic to a fixed value. See the below 69 | section "Aesthetics" for a full list of possible arguments.} 70 | 71 | \item{nudge_x, nudge_y}{Horizontal and vertical adjustment to nudge labels by. 72 | Useful for offsetting text from points, particularly on discrete scales. 73 | Cannot be jointly specified with \code{position}.} 74 | 75 | \item{na.rm}{If \code{FALSE}, the default, missing values are removed with 76 | a warning. If \code{TRUE}, missing values are silently removed.} 77 | 78 | \item{show.legend}{logical. Should this layer be included in the legends? 79 | \code{NA}, the default, includes if any aesthetics are mapped. 80 | \code{FALSE} never includes, and \code{TRUE} always includes. 81 | It can also be a named logical vector to finely select the aesthetics to 82 | display.} 83 | 84 | \item{inherit.aes}{If \code{FALSE}, overrides the default aesthetics, 85 | rather than combining with them. This is most useful for helper functions 86 | that define both data and aesthetics and shouldn't inherit behaviour from 87 | the default plot specification, e.g. \code{\link[ggplot2:borders]{borders()}}.} 88 | } 89 | \value{ 90 | A ggplot2 layer (\code{\link[ggplot2:layer]{ggplot2::layer()}}) that can be added to a plot 91 | created with \code{\link[ggplot2:ggplot]{ggplot2::ggplot()}}. 92 | } 93 | \description{ 94 | This geom is used to plot MLB images instead 95 | of points in a ggplot. It requires x, y aesthetics as well as a path. 96 | } 97 | \section{Aesthetics}{ 98 | 99 | \code{geom_mlb_logos()} understands the following aesthetics: 100 | \describe{ 101 | \item{\code{x}}{ - The x-coordinate. Required.} 102 | \item{\code{y}}{ - The y-coordinate. Required.} 103 | \item{\code{path}}{ - a file path, url, raster object or bitmap array. See \code{\link[magick:editing]{magick::image_read()}} for further information. Required.} 104 | \item{\code{alpha = NULL}}{ - The alpha channel, i.e. transparency level, as a numerical value between 0 and 1.} 105 | \item{\code{colour = NULL}}{ - The image will be colorized with this colour. Use the special character \code{"b/w"} to set it to black and white. For more information on valid colour names in ggplot2 see \url{https://ggplot2.tidyverse.org/articles/ggplot2-specs.html?q=colour#colour-and-fill}} 106 | \item{\code{angle = 0}}{ - The angle of the image as a numerical value between 0° and 360°.} 107 | \item{\code{hjust = 0.5}}{ - The horizontal adjustment relative to the given x coordinate. Must be a numerical value between 0 and 1.} 108 | \item{\code{vjust = 0.5}}{ - The vertical adjustment relative to the given y coordinate. Must be a numerical value between 0 and 1.} 109 | \item{\code{width = 1.0}}{ - The desired width of the image in \code{npc} (Normalised Parent Coordinates). 110 | The default value is set to 1.0 which is \emph{big} but it is necessary 111 | because all used values are computed relative to the default. 112 | A typical size is \code{width = 0.1} (see below examples).} 113 | \item{\code{height = 1.0}}{ - The desired height of the image in \code{npc} (Normalised Parent Coordinates). 114 | The default value is set to 1.0 which is \emph{big} but it is necessary 115 | because all used values are computed relative to the default. 116 | A typical size is \code{height = 0.1} (see below examples).} 117 | } 118 | } 119 | 120 | \examples{ 121 | \donttest{ 122 | library(mlbplotR) 123 | library(ggplot2) 124 | 125 | # create x-y-coordinates of a triangle and add league logo urls 126 | df <- data.frame( 127 | a = c(sin(2 * pi * (0:4) / 5), 0), 128 | b = c(cos(2 * pi * (0:4) / 5), 0), 129 | url = c( 130 | "https://i.turner.ncaa.com/sites/default/files/images/logos/schools/bgl/virginia.svg", 131 | "https://i.turner.ncaa.com/sites/default/files/images/logos/schools/bgl/michigan-st.svg", 132 | "https://i.turner.ncaa.com/sites/default/files/images/logos/schools/bgl/lsu.svg", 133 | "https://i.turner.ncaa.com/sites/default/files/images/logos/schools/bgl/texas.svg", 134 | "https://i.turner.ncaa.com/sites/default/files/images/logos/schools/bgl/oregon.svg", 135 | "https://i.turner.ncaa.com/sites/default/files/images/logos/schools/bgl/james-madison.svg" 136 | ) 137 | ) 138 | 139 | # plot images directly from url 140 | ggplot(df, aes(x = a, y = b)) + 141 | geom_from_path(aes(path = url), width = 0.15) + 142 | coord_cartesian(xlim = c(-2, 2), ylim = c(-1.3, 1.5)) + 143 | theme_void() 144 | 145 | # plot images directly from url and apply transparency 146 | ggplot(df, aes(x = a, y = b)) + 147 | geom_from_path(aes(path = url), width = 0.15, alpha = 0.5) + 148 | coord_cartesian(xlim = c(-2, 2), ylim = c(-1.3, 1.5)) + 149 | theme_void() 150 | 151 | # It is also possible and recommended to use the underlying Geom inside a 152 | # ggplot2 annotation 153 | ggplot() + 154 | annotate( 155 | mlbplotR::GeomFromPath, 156 | x = 0, 157 | y = 0, 158 | path = "https://a.espncdn.com/combiner/i?img=/i/teamlogos/leagues/500/mlb.png", 159 | width = 0.4 160 | ) + 161 | theme_minimal() 162 | } 163 | } 164 | -------------------------------------------------------------------------------- /man/geom_lines.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/geom_lines.R 3 | \name{geom_lines} 4 | \alias{geom_median_lines} 5 | \alias{geom_mean_lines} 6 | \title{ggplot2 Layer for Horizontal and Vertical Reference Lines} 7 | \usage{ 8 | geom_median_lines( 9 | mapping = NULL, 10 | data = NULL, 11 | ..., 12 | na.rm = FALSE, 13 | show.legend = NA, 14 | inherit.aes = TRUE 15 | ) 16 | 17 | geom_mean_lines( 18 | mapping = NULL, 19 | data = NULL, 20 | ..., 21 | na.rm = FALSE, 22 | show.legend = NA, 23 | inherit.aes = TRUE 24 | ) 25 | } 26 | \arguments{ 27 | \item{mapping}{Set of aesthetic mappings created by \code{\link[ggplot2:aes]{aes()}}.} 28 | 29 | \item{data}{The data to be displayed in this layer. There are three 30 | options: 31 | 32 | If \code{NULL}, the default, the data is inherited from the plot 33 | data as specified in the call to \code{\link[ggplot2:ggplot]{ggplot()}}. 34 | 35 | A \code{data.frame}, or other object, will override the plot 36 | data. All objects will be fortified to produce a data frame. See 37 | \code{\link[ggplot2:fortify]{fortify()}} for which variables will be created. 38 | 39 | A \code{function} will be called with a single argument, 40 | the plot data. The return value must be a \code{data.frame}, and 41 | will be used as the layer data. A \code{function} can be created 42 | from a \code{formula} (e.g. \code{~ head(.x, 10)}).} 43 | 44 | \item{...}{Other arguments passed on to \code{\link[ggplot2:layer]{layer()}}'s \code{params} argument. These 45 | arguments broadly fall into one of 4 categories below. Notably, further 46 | arguments to the \code{position} argument, or aesthetics that are required 47 | can \emph{not} be passed through \code{...}. Unknown arguments that are not part 48 | of the 4 categories below are ignored. 49 | \itemize{ 50 | \item Static aesthetics that are not mapped to a scale, but are at a fixed 51 | value and apply to the layer as a whole. For example, \code{colour = "red"} 52 | or \code{linewidth = 3}. The geom's documentation has an \strong{Aesthetics} 53 | section that lists the available options. The 'required' aesthetics 54 | cannot be passed on to the \code{params}. Please note that while passing 55 | unmapped aesthetics as vectors is technically possible, the order and 56 | required length is not guaranteed to be parallel to the input data. 57 | \item When constructing a layer using 58 | a \verb{stat_*()} function, the \code{...} argument can be used to pass on 59 | parameters to the \code{geom} part of the layer. An example of this is 60 | \code{stat_density(geom = "area", outline.type = "both")}. The geom's 61 | documentation lists which parameters it can accept. 62 | \item Inversely, when constructing a layer using a 63 | \verb{geom_*()} function, the \code{...} argument can be used to pass on parameters 64 | to the \code{stat} part of the layer. An example of this is 65 | \code{geom_area(stat = "density", adjust = 0.5)}. The stat's documentation 66 | lists which parameters it can accept. 67 | \item The \code{key_glyph} argument of \code{\link[ggplot2:layer]{layer()}} may also be passed on through 68 | \code{...}. This can be one of the functions described as 69 | \link[ggplot2:draw_key]{key glyphs}, to change the display of the layer in the legend. 70 | }} 71 | 72 | \item{na.rm}{If \code{FALSE}, the default, missing values are removed with 73 | a warning. If \code{TRUE}, missing values are silently removed.} 74 | 75 | \item{show.legend}{logical. Should this layer be included in the legends? 76 | \code{NA}, the default, includes if any aesthetics are mapped. 77 | \code{FALSE} never includes, and \code{TRUE} always includes. 78 | It can also be a named logical vector to finely select the aesthetics to 79 | display.} 80 | 81 | \item{inherit.aes}{If \code{FALSE}, overrides the default aesthetics, 82 | rather than combining with them. This is most useful for helper functions 83 | that define both data and aesthetics and shouldn't inherit behavior from 84 | the default plot specification.} 85 | } 86 | \value{ 87 | A ggplot2 layer (\code{\link[ggplot2:layer]{ggplot2::layer()}}) that can be added to a plot 88 | created with \code{\link[ggplot2:ggplot]{ggplot2::ggplot()}}. 89 | } 90 | \description{ 91 | These geoms can be used to draw horizontal or vertical reference 92 | lines in a ggplot. They use the data in the aesthetics \code{v_var} and \code{h_var} 93 | to compute their \code{median} or \code{mean} and draw the as a line. 94 | } 95 | \section{Aesthetics}{ 96 | 97 | \code{geom_median_lines()} and \code{geom_mean_lines()} understand the following 98 | aesthetics (at least one of \code{v_var} and \code{h_var} are required): 99 | \describe{ 100 | \item{\code{v_var}}{ - The variable for which to compute the median/mean that is drawn as vertical line.} 101 | \item{\code{h_var}}{ - The variable for which to compute the median/mean that is drawn as horizontal line.} 102 | \item{\code{alpha = NA}}{ - The alpha channel, i.e. transparency level, as a numerical value between 0 and 1.} 103 | \item{\code{color = "black"}}{ - The color of the drawn lines.} 104 | \item{\code{linetype = 2}}{ - The linetype of the drawn lines.} 105 | \item{\code{linewidth = 0.5}}{ - The size of the drawn lines.} 106 | } 107 | } 108 | 109 | \examples{ 110 | \donttest{ 111 | library(mlbplotR) 112 | library(ggplot2) 113 | 114 | # inherit top level aesthetics 115 | ggplot(mtcars, aes(x = disp, y = mpg, h_var = mpg, v_var = disp)) + 116 | geom_point() + 117 | geom_median_lines() + 118 | geom_mean_lines(color = "blue") + 119 | theme_minimal() 120 | 121 | # draw horizontal line only 122 | ggplot(mtcars, aes(x = disp, y = mpg, h_var = mpg)) + 123 | geom_point() + 124 | geom_median_lines() + 125 | geom_mean_lines(color = "blue") + 126 | theme_minimal() 127 | 128 | # draw vertical line only 129 | ggplot(mtcars, aes(x = disp, y = mpg, v_var = disp)) + 130 | geom_point() + 131 | geom_median_lines() + 132 | geom_mean_lines(color = "blue") + 133 | theme_minimal() 134 | 135 | # choose your own value 136 | ggplot(mtcars, aes(x = disp, y = mpg)) + 137 | geom_point() + 138 | geom_median_lines(v_var = 400, h_var = 15) + 139 | geom_mean_lines(v_var = 150, h_var = 30, color = "blue") + 140 | theme_minimal() 141 | } 142 | } 143 | \seealso{ 144 | The underlying ggplot2 geoms \code{\link[=geom_hline]{geom_hline()}} and \code{\link[=geom_vline]{geom_vline()}} 145 | } 146 | -------------------------------------------------------------------------------- /man/geom_milb_logos.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/geom_milb_logos.R 3 | \name{geom_milb_logos} 4 | \alias{geom_milb_logos} 5 | \alias{geom_milb_light_cap_logos} 6 | \alias{geom_milb_dot_logos} 7 | \title{ggplot2 Layer for Visualizing MiLB Team Logos} 8 | \usage{ 9 | geom_milb_logos( 10 | mapping = NULL, 11 | data = NULL, 12 | stat = "identity", 13 | position = "identity", 14 | ..., 15 | nudge_x = 0, 16 | nudge_y = 0, 17 | na.rm = FALSE, 18 | show.legend = FALSE, 19 | inherit.aes = TRUE 20 | ) 21 | 22 | geom_milb_light_cap_logos( 23 | mapping = NULL, 24 | data = NULL, 25 | stat = "identity", 26 | position = "identity", 27 | ..., 28 | nudge_x = 0, 29 | nudge_y = 0, 30 | na.rm = FALSE, 31 | show.legend = FALSE, 32 | inherit.aes = TRUE 33 | ) 34 | 35 | geom_milb_dot_logos( 36 | mapping = NULL, 37 | data = NULL, 38 | stat = "identity", 39 | position = "identity", 40 | ..., 41 | nudge_x = 0, 42 | nudge_y = 0, 43 | na.rm = FALSE, 44 | show.legend = FALSE, 45 | inherit.aes = TRUE 46 | ) 47 | } 48 | \arguments{ 49 | \item{mapping}{Set of aesthetic mappings created by \code{\link[ggplot2:aes]{aes()}}. If specified and 50 | \code{inherit.aes = TRUE} (the default), it is combined with the default mapping 51 | at the top level of the plot. You must supply \code{mapping} if there is no plot 52 | mapping.} 53 | 54 | \item{data}{The data to be displayed in this layer. There are three 55 | options: 56 | 57 | If \code{NULL}, the default, the data is inherited from the plot 58 | data as specified in the call to \code{\link[ggplot2:ggplot]{ggplot()}}. 59 | 60 | A \code{data.frame}, or other object, will override the plot 61 | data. All objects will be fortified to produce a data frame. See 62 | \code{\link[ggplot2:fortify]{fortify()}} for which variables will be created. 63 | 64 | A \code{function} will be called with a single argument, 65 | the plot data. The return value must be a \code{data.frame}, and 66 | will be used as the layer data. A \code{function} can be created 67 | from a \code{formula} (e.g. \code{~ head(.x, 10)}).} 68 | 69 | \item{stat}{The statistical transformation to use on the data for this layer. 70 | When using a \verb{geom_*()} function to construct a layer, the \code{stat} 71 | argument can be used the override the default coupling between geoms and 72 | stats. The \code{stat} argument accepts the following: 73 | \itemize{ 74 | \item A \code{Stat} ggproto subclass, for example \code{StatCount}. 75 | \item A string naming the stat. To give the stat as a string, strip the 76 | function name of the \code{stat_} prefix. For example, to use \code{stat_count()}, 77 | give the stat as \code{"count"}. 78 | \item For more information and other ways to specify the stat, see the 79 | \link[ggplot2:layer_stats]{layer stat} documentation. 80 | }} 81 | 82 | \item{position}{A position adjustment to use on the data for this layer. This 83 | can be used in various ways, including to prevent overplotting and 84 | improving the display. The \code{position} argument accepts the following: 85 | \itemize{ 86 | \item The result of calling a position function, such as \code{position_jitter()}. 87 | This method allows for passing extra arguments to the position. 88 | \item A string naming the position adjustment. To give the position as a 89 | string, strip the function name of the \code{position_} prefix. For example, 90 | to use \code{position_jitter()}, give the position as \code{"jitter"}. 91 | \item For more information and other ways to specify the position, see the 92 | \link[ggplot2:layer_positions]{layer position} documentation. 93 | }} 94 | 95 | \item{...}{Other arguments passed on to \code{\link[ggplot2:layer]{ggplot2::layer()}}. These are 96 | often aesthetics, used to set an aesthetic to a fixed value. See the below 97 | section "Aesthetics" for a full list of possible arguments.} 98 | 99 | \item{nudge_x, nudge_y}{Horizontal and vertical adjustment to nudge labels by. 100 | Useful for offsetting text from points, particularly on discrete scales. 101 | Cannot be jointly specified with \code{position}.} 102 | 103 | \item{na.rm}{If \code{FALSE}, the default, missing values are removed with 104 | a warning. If \code{TRUE}, missing values are silently removed.} 105 | 106 | \item{show.legend}{logical. Should this layer be included in the legends? 107 | \code{NA}, the default, includes if any aesthetics are mapped. 108 | \code{FALSE} never includes, and \code{TRUE} always includes. 109 | It can also be a named logical vector to finely select the aesthetics to 110 | display.} 111 | 112 | \item{inherit.aes}{If \code{FALSE}, overrides the default aesthetics, 113 | rather than combining with them. This is most useful for helper functions 114 | that define both data and aesthetics and shouldn't inherit behaviour from 115 | the default plot specification, e.g. \code{\link[ggplot2:borders]{borders()}}.} 116 | } 117 | \value{ 118 | A ggplot2 layer (\code{\link[ggplot2:layer]{ggplot2::layer()}}) that can be added to a plot 119 | created with \code{\link[ggplot2:ggplot]{ggplot2::ggplot()}}. 120 | } 121 | \description{ 122 | \code{geom_milb_logos()}, \code{geom_milb_light_cap_logos()}, \code{geom_milb_dot_logos()} are used to 123 | plot MiLB team instead of points in a ggplot. It requires 124 | x, y aesthetics as well as a valid MiLB team name 125 | } 126 | \section{Aesthetics}{ 127 | 128 | \code{geom_milb_logos()}, \code{geom_milb_light_cap_logos()}, \code{geom_milb_dot_logos()} understand the following aesthetics: 129 | \describe{ 130 | \item{\code{x}}{ - The x-coordinate. Required.} 131 | \item{\code{y}}{ - The y-coordinate. Required.} 132 | \item{\code{team_name}}{ - The team name. Need to use the full team name. Required.} 133 | \item{\code{alpha = NULL}}{ - The alpha channel, i.e. transparency level, as a numerical value between 0 and 1.} 134 | \item{\code{colour = NULL}}{ - The image will be colourized with this colour. Use the special character \code{"b/w"} to set it to black and white. For more information on valid colour names in ggplot2 see \url{https://ggplot2.tidyverse.org/articles/ggplot2-specs.html?q=colour#colour-and-fill}} 135 | \item{\code{angle = 0}}{ - The angle of the image as a numerical value between 0° and 360°.} 136 | \item{\code{hjust = 0.5}}{ - The horizontal adjustment relative to the given x coordinate. Must be a numerical value between 0 and 1.} 137 | \item{\code{vjust = 0.5}}{ - The vertical adjustment relative to the given y coordinate. Must be a numerical value between 0 and 1.} 138 | \item{\code{height = 1.0}}{ - The desired height of the image in \code{npc} (Normalised Parent Coordinates). 139 | The default value is set to 1.0 which is \emph{big} but it is necessary 140 | because all used values are computed relative to the default. 141 | A typical size is \code{height = 0.1} (see below examples). 142 | For cap logos, the scaling works better when adjusting height and not width.} 143 | \item{\code{width = 1.0}}{ - The desired width of the image in \code{npc} (Normalised Parent Coordinates). 144 | The default value is set to 1.0 which is \emph{big} but it is necessary 145 | because all used values are computed relative to the default. 146 | A typical size is \code{height = 0.075} (see below examples). 147 | For cap logos, the scaling works better when adjusting height and not width.} 148 | } 149 | } 150 | 151 | \examples{ 152 | \donttest{ 153 | library(mlbplotR) 154 | library(ggplot2) 155 | 156 | team_names <- c("Kannapolis Cannon Ballers", "Charlotte Knights", 157 | "Chesapeake Baysox", "Durham Bulls", "Montgomery Biscuits", "Las Vegas Aviators", 158 | "Lehigh Valley IronPigs", "Richmond Flying Squirrels", "Round Rock Express", 159 | "Frisco RoughRiders", "Hub City Spartanburgers", "Hickory Crawdads") 160 | 161 | df <- data.frame( 162 | a = rep(1:4, 3), 163 | b = sort(rep(1:3, 4), decreasing = TRUE), 164 | teams = team_names 165 | ) 166 | 167 | # keep alpha == 1 for all teams including an "A" 168 | matches <- grepl("A|a", team_names) 169 | df$alpha <- ifelse(matches, 1, 0.2) 170 | # also set a custom fill colour for the non "A" teams 171 | df$colour <- ifelse(matches, NA, "gray") 172 | 173 | # scatterplot of all logos 174 | ggplot(df, aes(x = a, y = b)) + 175 | geom_milb_logos(aes(team_name = teams), height = 0.1) + 176 | geom_label(aes(label = teams), nudge_y = -0.35, alpha = 0.5) + 177 | theme_void() 178 | 179 | 180 | # apply alpha and colour via an aesthetic from inside the dataset `df` 181 | # please note that you have to add scale_alpha_identity() as well as 182 | # scale_colour_identity() to use the alpha and colour values in your dataset! 183 | ggplot(df, aes(x = a, y = b)) + 184 | geom_milb_light_cap_logos(aes(team_name = teams, alpha = alpha, colour = colour), height = 0.1) + 185 | geom_label(aes(label = teams), nudge_y = -0.35, alpha = 0.5) + 186 | scale_alpha_identity() + 187 | scale_colour_identity() + 188 | theme_void() 189 | 190 | # apply alpha as constant for all logos 191 | ggplot(df, aes(x = a, y = b)) + 192 | geom_milb_dot_logos(aes(team_name = teams), height = 0.15, alpha = 0.6) + 193 | geom_label(aes(label = teams), nudge_y = -0.35, alpha = 0.5) + 194 | theme_void() 195 | 196 | } 197 | } 198 | -------------------------------------------------------------------------------- /man/geom_mlb_headshots.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/geom_mlb_headshots.R 3 | \name{geom_mlb_headshots} 4 | \alias{geom_mlb_headshots} 5 | \alias{geom_mlb_dot_headshots} 6 | \alias{geom_milb_dot_headshots} 7 | \title{ggplot2 Layer for Visualizing MLB/MiLB Player Headshots} 8 | \usage{ 9 | geom_mlb_headshots( 10 | mapping = NULL, 11 | data = NULL, 12 | stat = "identity", 13 | position = "identity", 14 | ..., 15 | nudge_x = 0, 16 | nudge_y = 0, 17 | na.rm = FALSE, 18 | show.legend = FALSE, 19 | inherit.aes = TRUE 20 | ) 21 | 22 | geom_mlb_dot_headshots( 23 | mapping = NULL, 24 | data = NULL, 25 | stat = "identity", 26 | position = "identity", 27 | ..., 28 | nudge_x = 0, 29 | nudge_y = 0, 30 | na.rm = FALSE, 31 | show.legend = FALSE, 32 | inherit.aes = TRUE 33 | ) 34 | 35 | geom_milb_dot_headshots( 36 | mapping = NULL, 37 | data = NULL, 38 | stat = "identity", 39 | position = "identity", 40 | ..., 41 | nudge_x = 0, 42 | nudge_y = 0, 43 | na.rm = FALSE, 44 | show.legend = FALSE, 45 | inherit.aes = TRUE 46 | ) 47 | } 48 | \arguments{ 49 | \item{mapping}{Set of aesthetic mappings created by \code{\link[ggplot2:aes]{aes()}}. If specified and 50 | \code{inherit.aes = TRUE} (the default), it is combined with the default mapping 51 | at the top level of the plot. You must supply \code{mapping} if there is no plot 52 | mapping.} 53 | 54 | \item{data}{The data to be displayed in this layer. There are three 55 | options: 56 | 57 | If \code{NULL}, the default, the data is inherited from the plot 58 | data as specified in the call to \code{\link[ggplot2:ggplot]{ggplot()}}. 59 | 60 | A \code{data.frame}, or other object, will override the plot 61 | data. All objects will be fortified to produce a data frame. See 62 | \code{\link[ggplot2:fortify]{fortify()}} for which variables will be created. 63 | 64 | A \code{function} will be called with a single argument, 65 | the plot data. The return value must be a \code{data.frame}, and 66 | will be used as the layer data. A \code{function} can be created 67 | from a \code{formula} (e.g. \code{~ head(.x, 10)}).} 68 | 69 | \item{stat}{The statistical transformation to use on the data for this layer. 70 | When using a \verb{geom_*()} function to construct a layer, the \code{stat} 71 | argument can be used the override the default coupling between geoms and 72 | stats. The \code{stat} argument accepts the following: 73 | \itemize{ 74 | \item A \code{Stat} ggproto subclass, for example \code{StatCount}. 75 | \item A string naming the stat. To give the stat as a string, strip the 76 | function name of the \code{stat_} prefix. For example, to use \code{stat_count()}, 77 | give the stat as \code{"count"}. 78 | \item For more information and other ways to specify the stat, see the 79 | \link[ggplot2:layer_stats]{layer stat} documentation. 80 | }} 81 | 82 | \item{position}{A position adjustment to use on the data for this layer. This 83 | can be used in various ways, including to prevent overplotting and 84 | improving the display. The \code{position} argument accepts the following: 85 | \itemize{ 86 | \item The result of calling a position function, such as \code{position_jitter()}. 87 | This method allows for passing extra arguments to the position. 88 | \item A string naming the position adjustment. To give the position as a 89 | string, strip the function name of the \code{position_} prefix. For example, 90 | to use \code{position_jitter()}, give the position as \code{"jitter"}. 91 | \item For more information and other ways to specify the position, see the 92 | \link[ggplot2:layer_positions]{layer position} documentation. 93 | }} 94 | 95 | \item{...}{Other arguments passed on to \code{\link[ggplot2:layer]{ggplot2::layer()}}. These are 96 | often aesthetics, used to set an aesthetic to a fixed value. See the below 97 | section "Aesthetics" for a full list of possible arguments.} 98 | 99 | \item{nudge_x, nudge_y}{Horizontal and vertical adjustment to nudge labels by. 100 | Useful for offsetting text from points, particularly on discrete scales. 101 | Cannot be jointly specified with \code{position}.} 102 | 103 | \item{na.rm}{If \code{FALSE}, the default, missing values are removed with 104 | a warning. If \code{TRUE}, missing values are silently removed.} 105 | 106 | \item{show.legend}{logical. Should this layer be included in the legends? 107 | \code{NA}, the default, includes if any aesthetics are mapped. 108 | \code{FALSE} never includes, and \code{TRUE} always includes. 109 | It can also be a named logical vector to finely select the aesthetics to 110 | display.} 111 | 112 | \item{inherit.aes}{If \code{FALSE}, overrides the default aesthetics, 113 | rather than combining with them. This is most useful for helper functions 114 | that define both data and aesthetics and shouldn't inherit behaviour from 115 | the default plot specification, e.g. \code{\link[ggplot2:borders]{borders()}}.} 116 | } 117 | \value{ 118 | A ggplot2 layer (\code{\link[ggplot2:layer]{ggplot2::layer()}}) that can be added to a plot 119 | created with \code{\link[ggplot2:ggplot]{ggplot2::ggplot()}}. 120 | } 121 | \description{ 122 | This geom is used to plot MLB/MiLB player headshots instead 123 | of points in a ggplot. It requires x, y aesthetics as well as a valid MLBAM 124 | id (The same ID associated with their Baseball Savant page). 125 | } 126 | \section{Aesthetics}{ 127 | 128 | \code{geom_mlb_headshots()}, \code{geom_mlb_dot_headshots()}, \code{geom_milb_dot_headshots()}, understand the following aesthetics: 129 | \describe{ 130 | \item{\code{x}}{ - The x-coordinate. Required.} 131 | \item{\code{y}}{ - The y-coordinate. Required.} 132 | \item{\code{player_id}}{ - The players' MLBAM (Baseball Savant) id. Required.} 133 | \item{\code{na_headshot_to_logo = TRUE}}{ - Should NA/non-matches return the MLB logo 134 | instead of a grayed out blank headshot? Only used with \code{geom_mlb_headshots()}. Defaults to \code{TRUE}} 135 | \item{\code{alpha = NULL}}{ - The alpha channel, i.e. transparency level, as a numerical value between 0 and 1.} 136 | \item{\code{colour = NULL}}{ - The image will be colorized with this colour. Use the special character \code{"b/w"} to set it to black and white. For more information on valid colour names in ggplot2 see \url{https://ggplot2.tidyverse.org/articles/ggplot2-specs.html?q=colour#colour-and-fill}} 137 | \item{\code{angle = 0}}{ - The angle of the image as a numerical value between 0° and 360°.} 138 | \item{\code{hjust = 0.5}}{ - The horizontal adjustment relative to the given x coordinate. Must be a numerical value between 0 and 1.} 139 | \item{\code{vjust = 0.5}}{ - The vertical adjustment relative to the given y coordinate. Must be a numerical value between 0 and 1.} 140 | \item{\code{width = 1.0}}{ - The desired width of the image in \code{npc} (Normalised Parent Coordinates). 141 | The default value is set to 1.0 which is \emph{big} but it is necessary 142 | because all used values are computed relative to the default. 143 | A typical size is \code{width = 0.075} (see below examples).} 144 | \item{\code{height = 1.0}}{ - The desired height of the image in \code{npc} (Normalised Parent Coordinates). 145 | The default value is set to 1.0 which is \emph{big} but it is necessary 146 | because all used values are computed relative to the default. 147 | A typical size is \code{height = 0.1} (see below examples).} 148 | } 149 | } 150 | 151 | \examples{ 152 | \donttest{ 153 | library(mlbplotR) 154 | library(ggplot2) 155 | 156 | df <- data.frame( 157 | a = c(rep(1:3, 3), 1.5, 2.5), 158 | b = c(sort(rep(1:3, 3), decreasing = TRUE), 2.5, 2.5), 159 | player_id = c("660670", 160 | "545361", 161 | "605141", 162 | "571448", 163 | "594798", 164 | "518692", 165 | "0", 166 | "521692", 167 | "120074", 168 | "665487", 169 | "518934"), 170 | player_name = c("Ronald Acuña Jr.", 171 | "Mike Trout", 172 | "Mookie Betts", 173 | "Nolan Arenado", 174 | "Jacob deGrom", 175 | "Freddie Freeman", 176 | "Non Match", 177 | "Salvador Perez", 178 | "David Ortiz", 179 | "Fernando Tatis Jr.", 180 | "DJ LeMahieu") 181 | ) 182 | 183 | # set a custom fill colour for one player 184 | df$colour <- ifelse(df$a == 2 & df$b == 2, NA, "b/w") 185 | 186 | # scatterplot of the headshots 187 | ggplot(df, aes(x = a, y = b)) + 188 | geom_mlb_headshots(aes(player_id = player_id), height = 0.2) + 189 | geom_label(aes(label = player_name), nudge_y = -0.35, alpha = 0.5) + 190 | coord_cartesian(xlim = c(0.75, 3.25), ylim = c(0.7, 3.25)) + 191 | theme_void() 192 | 193 | # apply alpha as constant and use non default na replacement 194 | ggplot(df, aes(x = a, y = b)) + 195 | geom_mlb_headshots(aes(player_id = player_id), height = 0.2, alpha = 0.5, 196 | na_headshot_to_logo = FALSE) + 197 | geom_label(aes(label = player_name), nudge_y = -0.35, alpha = 0.5) + 198 | coord_cartesian(xlim = c(0.75, 3.25), ylim = c(0.7, 3.25)) + 199 | theme_void() 200 | 201 | # apply colour as an aesthetic and use the dot version 202 | ggplot(df, aes(x = a, y = b)) + 203 | geom_mlb_dot_headshots(aes(player_id = player_id, colour = colour), height = 0.2) + 204 | geom_label(aes(label = player_name), nudge_y = -0.35, alpha = 0.5) + 205 | coord_cartesian(xlim = c(0.75, 3.25), ylim = c(0.7, 3.25)) + 206 | scale_colour_identity() + 207 | theme_void() 208 | 209 | } 210 | } 211 | -------------------------------------------------------------------------------- /man/geom_mlb_logos.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/geom_mlb_logos.R 3 | \name{geom_mlb_logos} 4 | \alias{geom_mlb_logos} 5 | \alias{geom_mlb_scoreboard_logos} 6 | \alias{geom_mlb_dot_logos} 7 | \title{ggplot2 Layer for Visualizing MLB Team Logos} 8 | \usage{ 9 | geom_mlb_logos( 10 | mapping = NULL, 11 | data = NULL, 12 | stat = "identity", 13 | position = "identity", 14 | ..., 15 | nudge_x = 0, 16 | nudge_y = 0, 17 | na.rm = FALSE, 18 | show.legend = FALSE, 19 | inherit.aes = TRUE 20 | ) 21 | 22 | geom_mlb_scoreboard_logos( 23 | mapping = NULL, 24 | data = NULL, 25 | stat = "identity", 26 | position = "identity", 27 | ..., 28 | nudge_x = 0, 29 | nudge_y = 0, 30 | na.rm = FALSE, 31 | show.legend = FALSE, 32 | inherit.aes = TRUE 33 | ) 34 | 35 | geom_mlb_dot_logos( 36 | mapping = NULL, 37 | data = NULL, 38 | stat = "identity", 39 | position = "identity", 40 | ..., 41 | nudge_x = 0, 42 | nudge_y = 0, 43 | na.rm = FALSE, 44 | show.legend = FALSE, 45 | inherit.aes = TRUE 46 | ) 47 | } 48 | \arguments{ 49 | \item{mapping}{Set of aesthetic mappings created by \code{\link[ggplot2:aes]{aes()}}. If specified and 50 | \code{inherit.aes = TRUE} (the default), it is combined with the default mapping 51 | at the top level of the plot. You must supply \code{mapping} if there is no plot 52 | mapping.} 53 | 54 | \item{data}{The data to be displayed in this layer. There are three 55 | options: 56 | 57 | If \code{NULL}, the default, the data is inherited from the plot 58 | data as specified in the call to \code{\link[ggplot2:ggplot]{ggplot()}}. 59 | 60 | A \code{data.frame}, or other object, will override the plot 61 | data. All objects will be fortified to produce a data frame. See 62 | \code{\link[ggplot2:fortify]{fortify()}} for which variables will be created. 63 | 64 | A \code{function} will be called with a single argument, 65 | the plot data. The return value must be a \code{data.frame}, and 66 | will be used as the layer data. A \code{function} can be created 67 | from a \code{formula} (e.g. \code{~ head(.x, 10)}).} 68 | 69 | \item{stat}{The statistical transformation to use on the data for this layer. 70 | When using a \verb{geom_*()} function to construct a layer, the \code{stat} 71 | argument can be used the override the default coupling between geoms and 72 | stats. The \code{stat} argument accepts the following: 73 | \itemize{ 74 | \item A \code{Stat} ggproto subclass, for example \code{StatCount}. 75 | \item A string naming the stat. To give the stat as a string, strip the 76 | function name of the \code{stat_} prefix. For example, to use \code{stat_count()}, 77 | give the stat as \code{"count"}. 78 | \item For more information and other ways to specify the stat, see the 79 | \link[ggplot2:layer_stats]{layer stat} documentation. 80 | }} 81 | 82 | \item{position}{A position adjustment to use on the data for this layer. This 83 | can be used in various ways, including to prevent overplotting and 84 | improving the display. The \code{position} argument accepts the following: 85 | \itemize{ 86 | \item The result of calling a position function, such as \code{position_jitter()}. 87 | This method allows for passing extra arguments to the position. 88 | \item A string naming the position adjustment. To give the position as a 89 | string, strip the function name of the \code{position_} prefix. For example, 90 | to use \code{position_jitter()}, give the position as \code{"jitter"}. 91 | \item For more information and other ways to specify the position, see the 92 | \link[ggplot2:layer_positions]{layer position} documentation. 93 | }} 94 | 95 | \item{...}{Other arguments passed on to \code{\link[ggplot2:layer]{ggplot2::layer()}}. These are 96 | often aesthetics, used to set an aesthetic to a fixed value. See the below 97 | section "Aesthetics" for a full list of possible arguments.} 98 | 99 | \item{nudge_x, nudge_y}{Horizontal and vertical adjustment to nudge labels by. 100 | Useful for offsetting text from points, particularly on discrete scales. 101 | Cannot be jointly specified with \code{position}.} 102 | 103 | \item{na.rm}{If \code{FALSE}, the default, missing values are removed with 104 | a warning. If \code{TRUE}, missing values are silently removed.} 105 | 106 | \item{show.legend}{logical. Should this layer be included in the legends? 107 | \code{NA}, the default, includes if any aesthetics are mapped. 108 | \code{FALSE} never includes, and \code{TRUE} always includes. 109 | It can also be a named logical vector to finely select the aesthetics to 110 | display.} 111 | 112 | \item{inherit.aes}{If \code{FALSE}, overrides the default aesthetics, 113 | rather than combining with them. This is most useful for helper functions 114 | that define both data and aesthetics and shouldn't inherit behaviour from 115 | the default plot specification, e.g. \code{\link[ggplot2:borders]{borders()}}.} 116 | } 117 | \value{ 118 | A ggplot2 layer (\code{\link[ggplot2:layer]{ggplot2::layer()}}) that can be added to a plot 119 | created with \code{\link[ggplot2:ggplot]{ggplot2::ggplot()}}. 120 | } 121 | \description{ 122 | \code{geom_mlb_logos()}, \code{geom_mlb_scoreboard_logos()}, and \code{geom_mlb_dot_logos()} are used to 123 | plot MLB team and league logos instead of points in a ggplot. It requires 124 | x, y aesthetics as well as a valid MLB team abbreviation. The latter can be 125 | checked with \code{\link[=valid_team_names]{valid_team_names()}} but is also cleaned before being plotted. 126 | } 127 | \section{Aesthetics}{ 128 | 129 | \code{geom_mlb_logos()}, \code{geom_mlb_scoreboard_logos()}, and \code{geom_mlb_dot_logos()} understand the following aesthetics: 130 | \describe{ 131 | \item{\code{x}}{ - The x-coordinate. Required.} 132 | \item{\code{y}}{ - The y-coordinate. Required.} 133 | \item{\code{team_abbr}}{ - The team abbreviation. Need to use Savant's abbreviation. Required.} 134 | \item{\code{alpha = NULL}}{ - The alpha channel, i.e. transparency level, as a numerical value between 0 and 1.} 135 | \item{\code{colour = NULL}}{ - The image will be colourized with this colour. Use the special character \code{"b/w"} to set it to black and white. For more information on valid colour names in ggplot2 see \url{https://ggplot2.tidyverse.org/articles/ggplot2-specs.html?q=colour#colour-and-fill}} 136 | \item{\code{angle = 0}}{ - The angle of the image as a numerical value between 0° and 360°.} 137 | \item{\code{hjust = 0.5}}{ - The horizontal adjustment relative to the given x coordinate. Must be a numerical value between 0 and 1.} 138 | \item{\code{vjust = 0.5}}{ - The vertical adjustment relative to the given y coordinate. Must be a numerical value between 0 and 1.} 139 | \item{\code{width = 1.0}}{ - The desired width of the image in \code{npc} (Normalised Parent Coordinates). 140 | The default value is set to 1.0 which is \emph{big} but it is necessary 141 | because all used values are computed relative to the default. 142 | A typical size is \code{width = 0.075} (see below examples).} 143 | \item{\code{height = 1.0}}{ - The desired height of the image in \code{npc} (Normalised Parent Coordinates). 144 | The default value is set to 1.0 which is \emph{big} but it is necessary 145 | because all used values are computed relative to the default. 146 | A typical size is \code{height = 0.1} (see below examples).} 147 | } 148 | } 149 | 150 | \examples{ 151 | \donttest{ 152 | library(mlbplotR) 153 | library(ggplot2) 154 | 155 | team_abbr <- valid_team_names() 156 | # remove conference logos from this example 157 | team_abbr <- team_abbr[!team_abbr \%in\% c("NL", "AL", "MLB")] 158 | 159 | df <- data.frame( 160 | a = rep(1:6, 5), 161 | b = sort(rep(1:5, 6), decreasing = TRUE), 162 | teams = team_abbr 163 | ) 164 | 165 | # keep alpha == 1 for all teams including an "A" 166 | matches <- grepl("A", team_abbr) 167 | df$alpha <- ifelse(matches, 1, 0.2) 168 | # also set a custom fill colour for the non "A" teams 169 | df$colour <- ifelse(matches, NA, "gray") 170 | 171 | # scatterplot of all logos 172 | ggplot(df, aes(x = a, y = b)) + 173 | geom_mlb_logos(aes(team_abbr = teams), width = 0.075) + 174 | geom_label(aes(label = teams), nudge_y = -0.35, alpha = 0.5) + 175 | theme_void() 176 | 177 | # apply alpha via an aesthetic from inside the dataset `df` 178 | # please note that you have to add scale_alpha_identity() to use the alpha 179 | # values in your dataset! 180 | ggplot(df, aes(x = a, y = b)) + 181 | geom_mlb_scoreboard_logos(aes(team_abbr = teams, alpha = alpha), width = 0.075) + 182 | geom_label(aes(label = teams), nudge_y = -0.35, alpha = 0.5) + 183 | scale_alpha_identity() + 184 | theme_void() 185 | 186 | # apply alpha and colour via an aesthetic from inside the dataset `df` 187 | # please note that you have to add scale_alpha_identity() as well as 188 | # scale_colour_identity() to use the alpha and colour values in your dataset! 189 | ggplot(df, aes(x = a, y = b)) + 190 | geom_mlb_logos(aes(team_abbr = teams, alpha = alpha, colour = colour), width = 0.075) + 191 | geom_label(aes(label = teams), nudge_y = -0.35, alpha = 0.5) + 192 | scale_alpha_identity() + 193 | scale_colour_identity() + 194 | theme_void() 195 | 196 | # apply alpha as constant for all logos 197 | ggplot(df, aes(x = a, y = b)) + 198 | geom_mlb_dot_logos(aes(team_abbr = teams), width = 0.075, alpha = 0.6) + 199 | geom_label(aes(label = teams), nudge_y = -0.35, alpha = 0.5) + 200 | theme_void() 201 | 202 | # it's also possible to plot league logos 203 | league <- data.frame(a = 1:3, b = 0, teams = c("AL", "NL", "MLB")) 204 | ggplot(league, aes(x = a, y = b)) + 205 | geom_mlb_logos(aes(team_abbr = teams), width = 0.3) + 206 | geom_label(aes(label = teams), nudge_y = -0.4, alpha = 0.5) + 207 | coord_cartesian(xlim = c(0.5,3.5), ylim = c(-0.75,.75)) + 208 | theme_void() 209 | } 210 | } 211 | -------------------------------------------------------------------------------- /man/ggpreview.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/ggpreview.R 3 | \name{ggpreview} 4 | \alias{ggpreview} 5 | \title{Preview ggplot in Specified Dimensions} 6 | \usage{ 7 | ggpreview( 8 | plot = ggplot2::last_plot(), 9 | width = NA, 10 | height = NA, 11 | asp = NULL, 12 | dpi = 300, 13 | device = "png", 14 | units = c("in", "cm", "mm", "px"), 15 | scale = 1, 16 | limitsize = TRUE, 17 | bg = NULL, 18 | ... 19 | ) 20 | } 21 | \arguments{ 22 | \item{plot}{Plot to save, defaults to last plot displayed.} 23 | 24 | \item{width, height}{Plot size in units expressed by the \code{units} argument. 25 | If not supplied, uses the size of the current graphics device.} 26 | 27 | \item{asp}{The aspect ratio of the plot calculated as \code{width / height}. If 28 | this is a numeric value (and not \code{NULL}) the \code{height} of the plot will be 29 | recalculated to \code{height = width / asp}.} 30 | 31 | \item{dpi}{Plot resolution. Also accepts a string input: "retina" (320), 32 | "print" (300), or "screen" (72). Applies only to raster output types.} 33 | 34 | \item{device}{Device to use. Can either be a device function 35 | (e.g. \link{png}), or one of "eps", "ps", "tex" (pictex), 36 | "pdf", "jpeg", "tiff", "png", "bmp", "svg" or "wmf" (windows only). If 37 | \code{NULL} (default), the device is guessed based on the \code{filename} extension.} 38 | 39 | \item{units}{One of the following units in which the \code{width} and \code{height} 40 | arguments are expressed: \code{"in"}, \code{"cm"}, \code{"mm"} or \code{"px"}.} 41 | 42 | \item{scale}{Multiplicative scaling factor.} 43 | 44 | \item{limitsize}{When \code{TRUE} (the default), \code{ggsave()} will not 45 | save images larger than 50x50 inches, to prevent the common error of 46 | specifying dimensions in pixels.} 47 | 48 | \item{bg}{Background colour. If \code{NULL}, uses the \code{plot.background} fill value 49 | from the plot theme.} 50 | 51 | \item{...}{Other arguments passed on to the graphics device function, 52 | as specified by \code{device}.} 53 | } 54 | \value{ 55 | No return value, called for side effects. 56 | } 57 | \description{ 58 | This function previews a ggplot in its actual dimensions in order to see how 59 | it will look when saved. It is also significantly faster than the default 60 | preview in RStudio for ggplots created using mlbplotR. 61 | } 62 | \examples{ 63 | \donttest{ 64 | library(mlbplotR) 65 | library(ggplot2) 66 | 67 | team_abbr <- valid_team_names() 68 | # remove league logos from this example 69 | team_abbr <- team_abbr[!team_abbr \%in\% c("AL", "NL", "MLB")] 70 | 71 | df <- data.frame( 72 | random_value = runif(length(team_abbr), 0, 1), 73 | teams = team_abbr 74 | ) 75 | 76 | # use logos for x-axis 77 | # note that the plot is assigned to the object "p" 78 | p <- ggplot(df, aes(x = teams, y = random_value)) + 79 | geom_col(aes(color = teams, fill = teams), width = 0.5) + 80 | scale_color_mlb(type = "secondary") + 81 | scale_fill_mlb(alpha = 0.4) + 82 | theme_minimal() + 83 | theme(axis.text.x = element_mlb_logo()) 84 | 85 | # preview p with defined width and aspect ratio (only available in RStudio) 86 | if (rstudioapi::isAvailable()){ 87 | ggpreview(p, width = 5, asp = 16/9) 88 | } 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /man/gt_merge_stack_team_color.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/gt_helpers.R 3 | \name{gt_merge_stack_team_color} 4 | \alias{gt_merge_stack_team_color} 5 | \title{Merge and stack text from two columns in \code{gt} and color one with team colors} 6 | \usage{ 7 | gt_merge_stack_team_color( 8 | gt_object, 9 | col1, 10 | col2, 11 | team_col, 12 | font_sizes = c(12, 14), 13 | font_weights = c("lighter", "bold"), 14 | font_variants = c("small-caps"), 15 | color = "black" 16 | ) 17 | } 18 | \arguments{ 19 | \item{gt_object}{An existing gt table object of class \code{gt_tbl}} 20 | 21 | \item{col1}{The column to stack on top.} 22 | 23 | \item{col2}{The column to merge and place below with the text team color that corresponds to \code{team_col}.} 24 | 25 | \item{team_col}{The column of team abbreviations (cleaned with \code{clean_team_abbrs()}) that match \code{valid_team_names()} for the color of the bottom text.} 26 | 27 | \item{font_sizes}{the font size for the top and bottom text in px. Can be vector of length 1 or 2. Defaults to c(12, 14)} 28 | 29 | \item{font_weights}{the font weight of the top and bottom text. Can be vector of length 1 or 2. Defaults to c("lighter", "bold")} 30 | 31 | \item{font_variants}{the font variant of the top and bottom text. Can be vector of length 1 or 2. Defaults to "small-caps"} 32 | 33 | \item{color}{The color for the top text.} 34 | } 35 | \value{ 36 | An object of class \code{gt_tbl}. 37 | } 38 | \description{ 39 | The \code{gt_merge_stack_team_color()} function takes an existing \code{gt} table and merges 40 | column 1 and column 2, stacking column 1's text on top of column 2's. 41 | Top text is in all caps while the lower text is bigger, bolded, 42 | and colored by the team name in another column. 43 | This is a slightly modified version of \href{https://jthomasmock.github.io/gtExtras/reference/gt_merge_stack.html}{\code{gtExtras::gt_merge_stack()}} written by Tom Mock. 44 | } 45 | \examples{ 46 | \donttest{ 47 | library(gt) 48 | library(mlbplotR) 49 | 50 | gt_merge_example <- mlbplotR::load_mlb_teams() \%>\% 51 | dplyr::slice(1:5) \%>\% 52 | dplyr::select(team_abbr, team_location, team_mascot) \%>\% 53 | gt::gt() \%>\% 54 | gt_merge_stack_team_color(col1 = "team_location", 55 | col2 = "team_mascot", 56 | team_col = "team_abbr") 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /man/gt_milb.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/gt_helpers.R 3 | \name{gt_milb} 4 | \alias{gt_milb} 5 | \alias{gt_fmt_milb_logo} 6 | \alias{gt_fmt_milb_dot_logo} 7 | \title{Add MiLB team logos into rows of a \code{gt} table} 8 | \usage{ 9 | gt_fmt_milb_logo(gt_object, columns, height = 30, locations = NULL) 10 | 11 | gt_fmt_milb_dot_logo(gt_object, columns, height = 30, locations = NULL) 12 | } 13 | \arguments{ 14 | \item{gt_object}{An existing gt table object of class \code{gt_tbl}} 15 | 16 | \item{columns}{The columns wherein changes to cell data colors should occur. 17 | Argument has no effect if \code{locations} is not \code{NULL}.} 18 | 19 | \item{height}{The absolute height (px) of the image in the table cell} 20 | 21 | \item{locations}{If \code{NULL} (the default), the function will render 22 | logos in argument \code{columns}. 23 | Otherwise, the cell or set of cells to be associated with the team name 24 | transformation. Only the \code{\link[gt:cells_body]{gt::cells_body()}}, \code{\link[gt:cells_stub]{gt::cells_stub()}}, 25 | \code{\link[gt:cells_column_labels]{gt::cells_column_labels()}}, and \code{\link[gt:cells_row_groups]{gt::cells_row_groups()}} helper functions 26 | can be used here. We can enclose several of these calls within a \code{list()} 27 | if we wish to make the transformation happen at different locations.} 28 | } 29 | \value{ 30 | An object of class \code{gt_tbl}. 31 | } 32 | \description{ 33 | The \code{gt_fmt_milb_logo} and \code{gt_fmt_milb_dot_logo} functions take an existing 34 | \code{gt_tbl} object and converts MiLB team names into team logos. 35 | This is a wrapper around 36 | \href{https://jthomasmock.github.io/gtExtras/reference/gt_img_rows.html}{\code{gtExtras::gt_image_rows()}} 37 | written by Tom Mock, which is a wrapper around \code{gt::text_transform()} + \code{gt::web_image()}/ 38 | \code{gt::local_image()} with the necessary boilerplate already applied. 39 | } 40 | \examples{ 41 | \donttest{ 42 | library(gt) 43 | library(mlbplotR) 44 | gt_milb_example <- mlbplotR::load_milb_teams() \%>\% 45 | dplyr::filter(parent_org_name == "Texas Rangers") \%>\% 46 | dplyr::mutate(dot = team_name) \%>\% 47 | dplyr::select(team_name, dot, team_location, team_mascot) \%>\% 48 | gt::gt() \%>\% 49 | gt_fmt_milb_logo(columns = "team_name") \%>\% 50 | gt_fmt_milb_dot_logo(columns = "dot") 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /man/gt_mlb.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/gt_helpers.R 3 | \name{gt_mlb} 4 | \alias{gt_mlb} 5 | \alias{gt_fmt_mlb_logo} 6 | \alias{gt_fmt_mlb_scoreboard_logo} 7 | \alias{gt_fmt_mlb_dot_logo} 8 | \title{Add MLB team logos into rows of a \code{gt} table} 9 | \usage{ 10 | gt_fmt_mlb_logo(gt_object, columns, height = 30, locations = NULL) 11 | 12 | gt_fmt_mlb_scoreboard_logo(gt_object, columns, height = 30, locations = NULL) 13 | 14 | gt_fmt_mlb_dot_logo(gt_object, columns, height = 30, locations = NULL) 15 | } 16 | \arguments{ 17 | \item{gt_object}{An existing gt table object of class \code{gt_tbl}} 18 | 19 | \item{columns}{The columns wherein changes to cell data colors should occur. 20 | Argument has no effect if \code{locations} is not \code{NULL}.} 21 | 22 | \item{height}{The absolute height (px) of the image in the table cell} 23 | 24 | \item{locations}{If \code{NULL} (the default), the function will render 25 | logos in argument \code{columns}. 26 | Otherwise, the cell or set of cells to be associated with the team name 27 | transformation. Only the \code{\link[gt:cells_body]{gt::cells_body()}}, \code{\link[gt:cells_stub]{gt::cells_stub()}}, 28 | \code{\link[gt:cells_column_labels]{gt::cells_column_labels()}}, and \code{\link[gt:cells_row_groups]{gt::cells_row_groups()}} helper functions 29 | can be used here. We can enclose several of these calls within a \code{list()} 30 | if we wish to make the transformation happen at different locations.} 31 | } 32 | \value{ 33 | An object of class \code{gt_tbl}. 34 | } 35 | \description{ 36 | The \code{gt_fmt_mlb_logo}, \code{gt_fmt_mlb_scoreboard_logo}, and \code{gt_fmt_mlb_dot_logo} functions take an existing 37 | \code{gt_tbl} object and converts MLB team names from \code{valid_team_names()} into team logos. 38 | This is a wrapper around 39 | \href{https://jthomasmock.github.io/gtExtras/reference/gt_img_rows.html}{\code{gtExtras::gt_image_rows()}} 40 | written by Tom Mock, which is a wrapper around \code{gt::text_transform()} + \code{gt::web_image()}/ 41 | \code{gt::local_image()} with the necessary boilerplate already applied. 42 | } 43 | \examples{ 44 | library(gt) 45 | library(mlbplotR) 46 | 47 | df <- data.frame(team = valid_team_names()[1:5], 48 | logo = valid_team_names()[1:5], 49 | scoreboard_logo = valid_team_names()[1:5], 50 | dot_logo = valid_team_names()[1:5]) 51 | 52 | gt_logo_example <- df \%>\% 53 | gt::gt() \%>\% 54 | gt_fmt_mlb_logo(columns = "logo") \%>\% 55 | gt_fmt_mlb_scoreboard_logo(columns = "scoreboard_logo") \%>\% 56 | gt_fmt_mlb_dot_logo(columns = "dot_logo") 57 | } 58 | -------------------------------------------------------------------------------- /man/gt_mlb_column_labels.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/gt_helpers.R 3 | \name{gt_mlb_column_labels} 4 | \alias{gt_mlb_column_labels} 5 | \title{Replace Team Abbreviations/Player IDs With Images In Column Labels} 6 | \usage{ 7 | gt_mlb_column_labels( 8 | value, 9 | type = c("mlb_logo", "scoreboard_logo", "dot_logo", "headshot", "dot_headshot"), 10 | height = 30, 11 | na_headshot_to_logo = TRUE 12 | ) 13 | } 14 | \arguments{ 15 | \item{value}{What team abbreviation/player id should be replaced with an image?} 16 | 17 | \item{type}{What type of image is replacing the value?} 18 | 19 | \item{height}{The absolute height (px) of the image} 20 | 21 | \item{na_headshot_to_logo}{should NA/non player id matches return the MLB logo instead 22 | of a grayed out blank headshot? Ignored unless \code{value} is equal to \code{"headshot"}. Defaults to \code{TRUE}} 23 | } 24 | \value{ 25 | HTML tag for image 26 | } 27 | \description{ 28 | \code{gt_mlb_column_labels} takes in a value of a team abbreviation or player id and 29 | converts the designated column to the corresponding image. 30 | } 31 | \examples{ 32 | \donttest{ 33 | library(gt) 34 | library(mlbplotR) 35 | 36 | df <- data.frame(BAL = 1, 37 | TEX = 1, 38 | LAD = 1, 39 | "Mike_Trout" = 1, 40 | "Shohei_Ohtani" = 1 41 | ) 42 | 43 | gt_column_example <- df \%>\% 44 | gt::gt() \%>\% 45 | gt::cols_label(BAL = gt_mlb_column_labels("BAL", "mlb_logo"), 46 | TEX = gt_mlb_column_labels("TEX", "scoreboard_logo"), 47 | LAD = gt_mlb_column_labels("LAD", "dot_logo"), 48 | "Mike_Trout" = gt_mlb_column_labels(545361, "dot_headshot"), 49 | "Shohei_Ohtani" = gt_mlb_column_labels(660271, "headshot")) 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /man/gt_mlb_headshots.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/gt_helpers.R 3 | \name{gt_mlb_headshots} 4 | \alias{gt_mlb_headshots} 5 | \alias{gt_fmt_mlb_headshot} 6 | \alias{gt_fmt_mlb_dot_headshot} 7 | \alias{gt_fmt_milb_dot_headshot} 8 | \title{Render Player Headshots in 'gt' Tables} 9 | \usage{ 10 | gt_fmt_mlb_headshot( 11 | gt_object, 12 | columns, 13 | height = 30, 14 | na_headshot_to_logo = TRUE, 15 | locations = NULL 16 | ) 17 | 18 | gt_fmt_mlb_dot_headshot( 19 | gt_object, 20 | columns, 21 | height = 30, 22 | na_headshot_to_logo = TRUE, 23 | locations = NULL 24 | ) 25 | 26 | gt_fmt_milb_dot_headshot( 27 | gt_object, 28 | columns, 29 | height = 30, 30 | na_headshot_to_logo = TRUE, 31 | locations = NULL 32 | ) 33 | } 34 | \arguments{ 35 | \item{gt_object}{An existing gt table object of class \code{gt_tbl}} 36 | 37 | \item{columns}{The columns wherein changes to cell data colors should occur. 38 | Has no effect if \code{locations} is not \code{NULL}} 39 | 40 | \item{height}{The absolute height (px) of the image in the table cell} 41 | 42 | \item{na_headshot_to_logo}{should NA/non matches return the MLB logo instead 43 | of a grayed out blank headshot? Only has an effect with \code{gt_fmt_mlb_headshot}. Defaults to \code{TRUE}} 44 | 45 | \item{locations}{If \code{NULL} (the default), the function will render 46 | logos in argument \code{columns}. 47 | Otherwise, the cell or set of cells to be associated with the team name 48 | transformation. Only the \code{\link[gt:cells_body]{gt::cells_body()}}, \code{\link[gt:cells_stub]{gt::cells_stub()}}, 49 | \code{\link[gt:cells_column_labels]{gt::cells_column_labels()}}, and \code{\link[gt:cells_row_groups]{gt::cells_row_groups()}} helper functions 50 | can be used here. We can enclose several of these calls within a \code{list()} 51 | if we wish to make the transformation happen at different locations.} 52 | } 53 | \value{ 54 | An object of class \code{gt_tbl}. 55 | } 56 | \description{ 57 | \code{gt_fmt_mlb_headshot}, \code{gt_fmt_mlb_dot_headshot}, and \code{gt_fmt_milb_dot_headshot} take an existing \code{gt_tbl} object and converts player ids into headshots. 58 | This is a wrapper around 59 | \href{https://jthomasmock.github.io/gtExtras/reference/gt_img_rows.html}{\code{gtExtras::gt_image_rows()}} 60 | written by Tom Mock, which is a wrapper around \code{gt::text_transform()} + \code{gt::web_image()}/ 61 | \code{gt::local_image()} with the necessary boilerplate already applied. 62 | } 63 | \examples{ 64 | \donttest{ 65 | library(gt) 66 | library(mlbplotR) 67 | gt_headshot_example <- mlbplotR::load_headshots() \%>\% 68 | head(5) \%>\% 69 | dplyr::select(player_name, savant_id1 = savant_id, savant_id2 = savant_id) \%>\% 70 | gt::gt() \%>\% 71 | gt_fmt_mlb_headshot(columns = "savant_id1") \%>\% 72 | gt_fmt_mlb_dot_headshot(columns = "savant_id2") 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /man/load_headshots.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/load_data.R 3 | \name{load_headshots} 4 | \alias{load_headshots} 5 | \title{Output MLB Team Abbreviations} 6 | \usage{ 7 | load_headshots() 8 | } 9 | \value{ 10 | A tibble of player names and ids from various sources. 11 | } 12 | \description{ 13 | Output MLB Team Abbreviations 14 | } 15 | \examples{ 16 | \donttest{ 17 | load_headshots() 18 | } 19 | 20 | } 21 | -------------------------------------------------------------------------------- /man/load_milb_teams.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/load_data.R 3 | \name{load_milb_teams} 4 | \alias{load_milb_teams} 5 | \title{Load MiLB Team Colors, and Logos} 6 | \usage{ 7 | load_milb_teams() 8 | } 9 | \value{ 10 | A tibble of team-level abbreviations, image URLs, and league info for Minor League Baseball Teams. 11 | } 12 | \description{ 13 | Loads team information and logos - useful for plots! 14 | } 15 | \examples{ 16 | \donttest{ 17 | load_milb_teams() 18 | } 19 | 20 | } 21 | \seealso{ 22 | Issues with this data should be filed here: \url{https://github.com/camdenk/mlbplotR} 23 | } 24 | -------------------------------------------------------------------------------- /man/load_mlb_teams.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/load_data.R 3 | \name{load_mlb_teams} 4 | \alias{load_mlb_teams} 5 | \title{Load MLB Team Colors, and Logos} 6 | \usage{ 7 | load_mlb_teams() 8 | } 9 | \value{ 10 | A tibble of team-level abbreviations, image URLs, and hex color codes. 11 | } 12 | \description{ 13 | Loads team colors, and logos - useful for plots! 14 | } 15 | \examples{ 16 | \donttest{ 17 | load_mlb_teams() 18 | } 19 | 20 | } 21 | \seealso{ 22 | Issues with this data should be filed here: \url{https://github.com/camdenk/mlbplotR} 23 | } 24 | -------------------------------------------------------------------------------- /man/mlb_player_tiers.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/mlb_tier_maker.R 3 | \name{mlb_player_tiers} 4 | \alias{mlb_player_tiers} 5 | \title{Create MLB Player Tiers} 6 | \usage{ 7 | mlb_player_tiers( 8 | data, 9 | title = "MLB Player Tiers", 10 | subtitle = "Created with the #mlbplotR Tiermaker", 11 | caption = NULL, 12 | tier_desc = c(`1` = "MVP Candidates", `2` = "Very Good", `3` = "Medium", `4` = "Bad", 13 | `5` = "Negative WAR", `6` = "", `7` = ""), 14 | presort = FALSE, 15 | alpha = 1, 16 | width = 0.1, 17 | no_line_below_tier = NULL, 18 | devel = FALSE, 19 | background_color = "#1e1e1e", 20 | line_color = "#e0e0e0", 21 | title_color = "white", 22 | subtitle_color = "#8e8e93", 23 | caption_color = subtitle_color, 24 | tier_label_color = title_color, 25 | headshot_type = "main", 26 | na_headshot_to_logo = TRUE 27 | ) 28 | } 29 | \arguments{ 30 | \item{data}{A data frame that has to include the variables \code{tier_no} (the 31 | number of the tier starting from the top tier no. 1) and \code{player_id} (the 32 | player's MLBAM/Savant ID). If data includes the variable \code{tier_rank}, 33 | these ranks will be used within each tier. Otherwise, if \code{presort = FALSE}, 34 | the function will assume that data is already sorted and if \code{presort = TRUE}, 35 | teams will be sorted alphabetically within tiers.} 36 | 37 | \item{title}{The title of the plot. If \code{NULL}, it will be omitted.} 38 | 39 | \item{subtitle}{The subtitle of the plot. If \code{NULL}, it will be omitted.} 40 | 41 | \item{caption}{The caption of the plot. If \code{NULL}, it will be omitted.} 42 | 43 | \item{tier_desc}{A named vector consisting of the tier descriptions. The names 44 | must equal the tier numbers from \code{tier_no}} 45 | 46 | \item{presort}{If \code{FALSE} (the default) the function assumes that the teams 47 | are already sorted within the tiers. Will otherwise sort alphabetically.} 48 | 49 | \item{alpha}{The alpha channel of the logos, i.e. transparency level, as a 50 | numerical value between 0 and 1. Defaults to 1} 51 | 52 | \item{width}{The desired width of the logo in \code{npc} (Normalised Parent Coordinates). A typical size is 0.1.} 53 | 54 | \item{no_line_below_tier}{Vector of tier numbers. The function won't draw tier 55 | separation lines below these tiers. This is intended to be used for tiers 56 | that shall be combined (see examples).} 57 | 58 | \item{devel}{Determines if headshots shall be rendered. If \code{FALSE} (the default), 59 | headshots will be rendered on each run. If \code{TRUE} the player ids will be 60 | plotted instead of the logos. This is much faster and helps with the plot 61 | development.} 62 | 63 | \item{background_color}{Background color for the plot. Defaults to "#1e1e1e"} 64 | 65 | \item{line_color}{Line color for the plot. Defaults to "#e0e0e0"} 66 | 67 | \item{title_color}{Text color for the title. Defaults to "white"} 68 | 69 | \item{subtitle_color}{Text color the the subtitle. Defaults to "#8e8e93"} 70 | 71 | \item{caption_color}{Text color the the caption. Defaults to be equal to the subtitle} 72 | 73 | \item{tier_label_color}{Text color for the tier labels. Defaults to be equal to the title} 74 | 75 | \item{headshot_type}{"main" or "dot" headshots? Defaults to "main"} 76 | 77 | \item{na_headshot_to_logo}{Should NA/non-matches return the MLB logo instead of a grayed out blank headshot? Defaults to \code{TRUE}} 78 | } 79 | \value{ 80 | A plot object created with \code{\link[ggplot2:ggplot]{ggplot2::ggplot()}}. 81 | } 82 | \description{ 83 | This function sets up a ggplot to visualize MLB player tiers. 84 | Adapted from \href{https://nflplotr.nflverse.com/reference/nfl_team_tiers.html}{\code{nflplotR}} 85 | } 86 | \examples{ 87 | \donttest{ 88 | library(ggplot2) 89 | library(dplyr, warn.conflicts = FALSE) 90 | player_ids <- load_headshots() |> 91 | head(35) |> 92 | pull(savant_id) 93 | 94 | # Build the player tiers data frame 95 | # This is completely random! 96 | df <- data.frame( 97 | tier_no = sample(1:5, length(player_ids), replace = TRUE), 98 | player_id = player_ids 99 | ) \%>\% 100 | dplyr::group_by(tier_no) \%>\% 101 | dplyr::mutate(tier_rank = sample(1:n(), n())) 102 | 103 | # Plot player tiers 104 | mlb_player_tiers(df) 105 | 106 | # Create a combined tier which is useful for tiers with lots of players that 107 | # should be split up in two or more rows. This is done by setting an empty 108 | # string for the tier 5 description and removing the tier separation line 109 | # below tier number 4. 110 | # This example also shows how to turn off the subtitle and add a caption 111 | mlb_player_tiers(df, 112 | subtitle = NULL, 113 | caption = "This is the caption", 114 | tier_desc = c("1" = "MVP Candidates", 115 | "2" = "Very Good", 116 | "3" = "Medium", 117 | "4" = "A Combined Tier", 118 | "5" = ""), 119 | no_line_below_tier = 4) 120 | 121 | # For the development of the tiers, it can be useful to turn off image 122 | # rendering as this can take quite a long time. By setting `devel = TRUE`, the 123 | # headshots are replaced by player ids which is much faster 124 | mlb_player_tiers(df, 125 | tier_desc = c("1" = "MVP Candidates", 126 | "2" = "Very Good", 127 | "3" = "", 128 | "4" = "A Combined Tier", 129 | "5" = ""), 130 | no_line_below_tier = c(2, 4), 131 | devel = TRUE) 132 | } 133 | } 134 | -------------------------------------------------------------------------------- /man/mlb_team_factor.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/mlb_team_factors.R 3 | \name{mlb_team_factor} 4 | \alias{mlb_team_factor} 5 | \title{Create Ordered MLB Team Factor} 6 | \usage{ 7 | mlb_team_factor(teams) 8 | } 9 | \arguments{ 10 | \item{teams}{A vector of MLB team abbreviations that should be included in 11 | \code{\link[=valid_team_names]{valid_team_names()}}. The function tries to clean team names internally 12 | by calling \code{\link[=clean_team_abbrs]{clean_team_abbrs()}}.} 13 | } 14 | \value{ 15 | Object of class \code{"factor"} 16 | } 17 | \description{ 18 | Convert a vector of MLB team abbreviations to an ordered factor 19 | by division and team name. Intended to be used for faceted plots where team 20 | logos are used in strip texts. 21 | } 22 | \examples{ 23 | \donttest{ 24 | # unsorted vector including NFL team abbreviations 25 | teams <- c("ATL", "WSH", "MIA", "BAL", "NYY", "BOS", "PHI", "NYM", "TB", "TOR") 26 | 27 | # defaults to sort by division and nick name in ascending order 28 | mlb_team_factor(teams) 29 | 30 | 31 | ######### HOW TO USE IN PRACTICE ######### 32 | 33 | library(ggplot2) 34 | library(magrittr) 35 | # load some sample data from the ggplot2 package 36 | plot_data <- mpg 37 | # add a new column by randomly sampling the above defined teams vector 38 | plot_data$team <- sample(teams, nrow(mpg), replace = TRUE) 39 | 40 | # Now we plot the data and facet by team abbreviation. ggplot automatically 41 | # converts the team names to a factor and sorts it alphabetically 42 | ggplot(plot_data, aes(displ, hwy)) + 43 | geom_point() + 44 | facet_wrap(~team, ncol = 5) + 45 | theme_minimal() 46 | 47 | # We'll change the order of facets by making another team name column and 48 | # converting it to an ordered factor. Again, this defaults to sort by division, 49 | # league, and location in ascending order. 50 | plot_data$ordered_team <- sample(teams, nrow(mpg), replace = TRUE) \%>\% 51 | mlb_team_factor() 52 | 53 | # Let's check how the facets are ordered now. 54 | ggplot(plot_data, aes(displ, hwy)) + 55 | geom_point() + 56 | facet_wrap(~ordered_team, ncol = 5) + 57 | theme_minimal() 58 | 59 | # The facet order looks weird because the defaults is meant to be used with 60 | # MLB team logos. So let's use the actual logos and look at the result. 61 | ggplot(plot_data, aes(displ, hwy)) + 62 | geom_point() + 63 | facet_wrap(~ordered_team, ncol = 5) + 64 | theme_minimal() + 65 | theme(strip.text = element_mlb_logo(size = .85)) 66 | 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /man/mlb_team_tiers.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/mlb_tier_maker.R 3 | \name{mlb_team_tiers} 4 | \alias{mlb_team_tiers} 5 | \title{Create MLB Team Tiers} 6 | \usage{ 7 | mlb_team_tiers( 8 | data, 9 | title = "MLB Team Tiers", 10 | subtitle = "Created with the #mlbplotR Tiermaker", 11 | caption = NULL, 12 | tier_desc = c(`1` = "World Series", `2` = "Very Good", `3` = "Medium", `4` = "Bad", `5` 13 | = "Tankathon", `6` = "", `7` = ""), 14 | presort = FALSE, 15 | alpha = 1, 16 | width = 0.075, 17 | no_line_below_tier = NULL, 18 | devel = FALSE, 19 | background_color = "#1e1e1e", 20 | line_color = "#e0e0e0", 21 | title_color = "white", 22 | subtitle_color = "#8e8e93", 23 | caption_color = subtitle_color, 24 | tier_label_color = title_color, 25 | logo_type = "main" 26 | ) 27 | } 28 | \arguments{ 29 | \item{data}{A data frame that has to include the variables \code{tier_no} (the 30 | number of the tier starting from the top tier no. 1) and \code{team_abbr} (the 31 | team abbreviation). \code{team_abbr} should be one of \code{\link[=valid_team_names]{valid_team_names()}} and 32 | the function tries to clean team names internally by calling 33 | \code{\link[=clean_team_abbrs]{clean_team_abbrs()}}. If data includes the variable \code{tier_rank}, 34 | these ranks will be used within each tier. Otherwise, if \code{presort = FALSE}, 35 | the function will assume that data is already sorted and if \code{presort = TRUE}, 36 | teams will be sorted alphabetically within tiers.} 37 | 38 | \item{title}{The title of the plot. If \code{NULL}, it will be omitted.} 39 | 40 | \item{subtitle}{The subtitle of the plot. If \code{NULL}, it will be omitted.} 41 | 42 | \item{caption}{The caption of the plot. If \code{NULL}, it will be omitted.} 43 | 44 | \item{tier_desc}{A named vector consisting of the tier descriptions. The names 45 | must equal the tier numbers from \code{tier_no}} 46 | 47 | \item{presort}{If \code{FALSE} (the default) the function assumes that the teams 48 | are already sorted within the tiers. Will otherwise sort alphabetically.} 49 | 50 | \item{alpha}{The alpha channel of the logos, i.e. transparency level, as a 51 | numerical value between 0 and 1. Defaults to 1} 52 | 53 | \item{width}{The desired width of the logo in \code{npc} (Normalised Parent Coordinates). A typical size is 0.075.} 54 | 55 | \item{no_line_below_tier}{Vector of tier numbers. The function won't draw tier 56 | separation lines below these tiers. This is intended to be used for tiers 57 | that shall be combined (see examples).} 58 | 59 | \item{devel}{Determines if logos shall be rendered. If \code{FALSE} (the default), 60 | logos will be rendered on each run. If \code{TRUE} the team abbreviations will be 61 | plotted instead of the logos. This is much faster and helps with the plot 62 | development.} 63 | 64 | \item{background_color}{Background color for the plot. Defaults to "#1e1e1e"} 65 | 66 | \item{line_color}{Line color for the plot. Defaults to "#e0e0e0"} 67 | 68 | \item{title_color}{Text color for the title. Defaults to "white"} 69 | 70 | \item{subtitle_color}{Text color the the subtitle. Defaults to "#8e8e93"} 71 | 72 | \item{caption_color}{Text color the the caption. Defaults to be equal to the subtitle} 73 | 74 | \item{tier_label_color}{Text color for the tier labels. Defaults to be equal to the title} 75 | 76 | \item{logo_type}{What logo should be used for each team ("main", "scoreboard", or "dot")? Defaults to "main"} 77 | } 78 | \value{ 79 | A plot object created with \code{\link[ggplot2:ggplot]{ggplot2::ggplot()}}. 80 | } 81 | \description{ 82 | This function sets up a ggplot to visualize MLB team tiers. 83 | Adapted from \href{https://nflplotr.nflverse.com/reference/nfl_team_tiers.html}{\code{nflplotR}} 84 | } 85 | \examples{ 86 | \donttest{ 87 | library(ggplot2) 88 | library(dplyr, warn.conflicts = FALSE) 89 | teams <- valid_team_names() 90 | # remove conference logos from this example 91 | teams <- teams[!teams \%in\% c("AL", "NL", "MLB")] 92 | 93 | # Build the team tiers data frame 94 | # This is completely random! 95 | df <- data.frame( 96 | tier_no = sample(1:5, length(teams), replace = TRUE), 97 | team_abbr = teams 98 | ) \%>\% 99 | dplyr::group_by(tier_no) \%>\% 100 | dplyr::mutate(tier_rank = sample(1:n(), n())) 101 | 102 | # Plot team tiers 103 | mlb_team_tiers(df) 104 | 105 | # Create a combined tier which is useful for tiers with lots of teams that 106 | # should be split up in two or more rows. This is done by setting an empty 107 | # string for the tier 5 description and removing the tier separation line 108 | # below tier number 4. 109 | # This example also shows how to turn off the subtitle and add a caption 110 | mlb_team_tiers(df, 111 | subtitle = NULL, 112 | caption = "This is the caption", 113 | tier_desc = c("1" = "World Series", 114 | "2" = "Very Good", 115 | "3" = "Medium", 116 | "4" = "A Combined Tier", 117 | "5" = ""), 118 | no_line_below_tier = 4) 119 | 120 | # For the development of the tiers, it can be useful to turn off logo image 121 | # rendering as this can take quite a long time. By setting `devel = TRUE`, the 122 | # logo images are replaced by team abbreviations which is much faster 123 | mlb_team_tiers(df, 124 | tier_desc = c("1" = "World Series", 125 | "2" = "Very Good", 126 | "3" = "", 127 | "4" = "A Combined Tier", 128 | "5" = ""), 129 | no_line_below_tier = c(2, 4), 130 | devel = TRUE) 131 | } 132 | } 133 | -------------------------------------------------------------------------------- /man/mlbplotR-package.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/geom_cap_logos.R, R/geom_from_path.R, 3 | % R/geom_lines.R, R/geom_milb_logos.R, R/geom_mlb_headshots.R, 4 | % R/geom_mlb_logos.R, R/mlbplotR-package.R 5 | \docType{data} 6 | \name{GeomMLBdarkcaplogo} 7 | \alias{GeomMLBdarkcaplogo} 8 | \alias{GeomMLBlightcaplogo} 9 | \alias{GeomFromPath} 10 | \alias{GeomRefLines} 11 | \alias{GeomMiLBlogo} 12 | \alias{GeomMiLBlightcaplogo} 13 | \alias{GeomMiLBdotlogo} 14 | \alias{GeomMLBheads} 15 | \alias{GeomMLBdotheads} 16 | \alias{GeomMiLBdotheads} 17 | \alias{GeomMLBlogo} 18 | \alias{GeomMLBscoreboardlogo} 19 | \alias{GeomMLBdotlogo} 20 | \alias{mlbplotR-package} 21 | \title{mlbplotR: Create 'ggplot2' and 'gt' Visuals with Major League Baseball Logos} 22 | \format{ 23 | An object of class \code{GeomMLBdarkcaplogo} (inherits from \code{Geom}, \code{ggproto}, \code{gg}) of length 5. 24 | 25 | An object of class \code{GeomMLBlightcaplogo} (inherits from \code{Geom}, \code{ggproto}, \code{gg}) of length 5. 26 | 27 | An object of class \code{GeomFromPath} (inherits from \code{Geom}, \code{ggproto}, \code{gg}) of length 5. 28 | 29 | An object of class \code{GeomRefLines} (inherits from \code{Geom}, \code{ggproto}, \code{gg}) of length 6. 30 | 31 | An object of class \code{GeomMiLBlogo} (inherits from \code{Geom}, \code{ggproto}, \code{gg}) of length 5. 32 | 33 | An object of class \code{GeomMiLBlightcaplogo} (inherits from \code{Geom}, \code{ggproto}, \code{gg}) of length 5. 34 | 35 | An object of class \code{GeomMiLBdotlogo} (inherits from \code{Geom}, \code{ggproto}, \code{gg}) of length 5. 36 | 37 | An object of class \code{GeomMLBheads} (inherits from \code{Geom}, \code{ggproto}, \code{gg}) of length 5. 38 | 39 | An object of class \code{GeomMLBdotheads} (inherits from \code{Geom}, \code{ggproto}, \code{gg}) of length 5. 40 | 41 | An object of class \code{GeomMiLBdotheads} (inherits from \code{Geom}, \code{ggproto}, \code{gg}) of length 5. 42 | 43 | An object of class \code{GeomMLBlogo} (inherits from \code{Geom}, \code{ggproto}, \code{gg}) of length 5. 44 | 45 | An object of class \code{GeomMLBscoreboardlogo} (inherits from \code{Geom}, \code{ggproto}, \code{gg}) of length 5. 46 | 47 | An object of class \code{GeomMLBdotlogo} (inherits from \code{Geom}, \code{ggproto}, \code{gg}) of length 5. 48 | } 49 | \usage{ 50 | GeomMLBdarkcaplogo 51 | 52 | GeomMLBlightcaplogo 53 | 54 | GeomFromPath 55 | 56 | GeomRefLines 57 | 58 | GeomMiLBlogo 59 | 60 | GeomMiLBlightcaplogo 61 | 62 | GeomMiLBdotlogo 63 | 64 | GeomMLBheads 65 | 66 | GeomMLBdotheads 67 | 68 | GeomMiLBdotheads 69 | 70 | GeomMLBlogo 71 | 72 | GeomMLBscoreboardlogo 73 | 74 | GeomMLBdotlogo 75 | } 76 | \description{ 77 | \if{html}{\figure{logo.png}{options: style='float: right' alt='logo' width='120'}} 78 | 79 | Tools to help visualize Major League Baseball analysis in 'ggplot2' and 'gt'. You provide team/player information and 'mlbplotR' will transform that information into team colors, logos, or player headshots for graphics. 80 | } 81 | \seealso{ 82 | Useful links: 83 | \itemize{ 84 | \item \url{https://github.com/camdenk/mlbplotR} 85 | \item \url{https://camdenk.github.io/mlbplotR/} 86 | \item Report bugs at \url{https://github.com/camdenk/mlbplotR/issues} 87 | } 88 | 89 | } 90 | \author{ 91 | \strong{Maintainer}: Camden Kay \email{camden.kay23@gmail.com} [copyright holder] 92 | 93 | Authors: 94 | \itemize{ 95 | \item Sebastian Carl \email{mrcaseb@gmail.com} 96 | } 97 | 98 | } 99 | \keyword{datasets} 100 | \keyword{internal} 101 | -------------------------------------------------------------------------------- /man/scale_axes_mlb.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/scale_mlb.R 3 | \name{scale_axes_mlb} 4 | \alias{scale_x_mlb} 5 | \alias{scale_y_mlb} 6 | \title{Axis Scales for MLB Team Logos} 7 | \usage{ 8 | scale_x_mlb( 9 | ..., 10 | expand = ggplot2::waiver(), 11 | guide = ggplot2::waiver(), 12 | position = "bottom", 13 | size = 12 14 | ) 15 | 16 | scale_y_mlb( 17 | ..., 18 | expand = ggplot2::waiver(), 19 | guide = ggplot2::waiver(), 20 | position = "left", 21 | size = 12 22 | ) 23 | } 24 | \arguments{ 25 | \item{...}{ 26 | Arguments passed on to \code{\link[ggplot2:discrete_scale]{discrete_scale}} 27 | \describe{ 28 | \item{\code{palette}}{A palette function that when called with a single integer 29 | argument (the number of levels in the scale) returns the values that 30 | they should take (e.g., \code{\link[scales:pal_hue]{scales::pal_hue()}}).} 31 | \item{\code{breaks}}{One of: 32 | \itemize{ 33 | \item \code{NULL} for no breaks 34 | \item \code{waiver()} for the default breaks (the scale limits) 35 | \item A character vector of breaks 36 | \item A function that takes the limits as input and returns breaks 37 | as output. Also accepts rlang \link[rlang:as_function]{lambda} function 38 | notation. 39 | }} 40 | \item{\code{limits}}{One of: 41 | \itemize{ 42 | \item \code{NULL} to use the default scale values 43 | \item A character vector that defines possible values of the scale and their 44 | order 45 | \item A function that accepts the existing (automatic) values and returns 46 | new ones. Also accepts rlang \link[rlang:as_function]{lambda} function 47 | notation. 48 | }} 49 | \item{\code{drop}}{Should unused factor levels be omitted from the scale? 50 | The default, \code{TRUE}, uses the levels that appear in the data; 51 | \code{FALSE} includes the levels in the factor. Please note that to display 52 | every level in a legend, the layer should use \code{show.legend = TRUE}.} 53 | \item{\code{na.translate}}{Unlike continuous scales, discrete scales can easily show 54 | missing values, and do so by default. If you want to remove missing values 55 | from a discrete scale, specify \code{na.translate = FALSE}.} 56 | \item{\code{na.value}}{If \code{na.translate = TRUE}, what aesthetic value should the 57 | missing values be displayed as? Does not apply to position scales 58 | where \code{NA} is always placed at the far right.} 59 | \item{\code{aesthetics}}{The names of the aesthetics that this scale works with.} 60 | \item{\code{labels}}{One of: 61 | \itemize{ 62 | \item \code{NULL} for no labels 63 | \item \code{waiver()} for the default labels computed by the 64 | transformation object 65 | \item A character vector giving labels (must be same length as \code{breaks}) 66 | \item An expression vector (must be the same length as breaks). See ?plotmath for details. 67 | \item A function that takes the breaks as input and returns labels 68 | as output. Also accepts rlang \link[rlang:as_function]{lambda} function 69 | notation. 70 | }} 71 | \item{\code{call}}{The \code{call} used to construct the scale for reporting messages.} 72 | \item{\code{super}}{The super class to use for the constructed scale} 73 | }} 74 | 75 | \item{expand}{For position scales, a vector of range expansion constants used to add some 76 | padding around the data to ensure that they are placed some distance 77 | away from the axes. Use the convenience function \code{\link[ggplot2:expansion]{expansion()}} 78 | to generate the values for the \code{expand} argument. The defaults are to 79 | expand the scale by 5\% on each side for continuous variables, and by 80 | 0.6 units on each side for discrete variables.} 81 | 82 | \item{guide}{A function used to create a guide or its name. See 83 | \code{\link[ggplot2:guides]{guides()}} for more information.} 84 | 85 | \item{position}{For position scales, The position of the axis. 86 | \code{left} or \code{right} for y axes, \code{top} or \code{bottom} for x axes.} 87 | 88 | \item{size}{The logo size in pixels. It is applied as height for an x-scale 89 | and as width for an y-scale.} 90 | } 91 | \value{ 92 | A discrete ggplot2 scale created with \code{\link[ggplot2:scale_discrete]{ggplot2::scale_x_discrete()}} or 93 | \code{\link[ggplot2:scale_discrete]{ggplot2::scale_y_discrete()}}. 94 | } 95 | \description{ 96 | \ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#superseded}{\figure{lifecycle-superseded.svg}{options: alt='[Superseded]'}}}{\strong{[Superseded]}} 97 | \code{scale_x_mlb()} and \code{scale_y_mlb()} have been superceded in favor of \verb{element_*_logo()} functions 98 | These functions map MLB team names to their team logos and make 99 | them available as axis labels 100 | } 101 | \details{ 102 | The scale translates MLB team abbreviations into raw image 103 | html and places the html as axis labels. Because of the way ggplots are 104 | constructed, it is necessary to adjust the \code{\link[=theme]{theme()}} after calling this 105 | scale. This can be done by calling \code{\link[=theme_x_mlb]{theme_x_mlb()}} or \code{\link[=theme_y_mlb]{theme_y_mlb()}} 106 | or alternatively by manually changing the relevant \code{axis.text} to 107 | \code{\link[ggtext:element_markdown]{ggtext::element_markdown()}}. However, this will only work if an underlying 108 | dependency, "gridtext", is installed with a newer version than 0.1.4 109 | } 110 | \examples{ 111 | \donttest{ 112 | library(mlbplotR) 113 | library(ggplot2) 114 | 115 | team_abbr <- valid_team_names() 116 | # remove league logos from this example 117 | team_abbr <- team_abbr[!team_abbr \%in\% c("AL", "NL", "MLB")] 118 | 119 | df <- data.frame( 120 | random_value = runif(length(team_abbr), 0, 1), 121 | teams = team_abbr 122 | ) 123 | 124 | if (utils::packageVersion("gridtext") > "0.1.4"){ 125 | # use logos for x-axis 126 | ggplot(df, aes(x = teams, y = random_value)) + 127 | geom_col(aes(color = teams, fill = teams), width = 0.5) + 128 | scale_color_mlb(type = "secondary") + 129 | scale_fill_mlb(alpha = 0.4) + 130 | scale_x_mlb() + 131 | theme_minimal() + 132 | # theme_*_mlb requires gridtext version > 0.1.4 133 | theme_x_mlb() 134 | 135 | # use logos for y-axis 136 | ggplot(df, aes(y = teams, x = random_value)) + 137 | geom_col(aes(color = teams, fill = teams), width = 0.5) + 138 | scale_color_mlb(type = "secondary") + 139 | scale_fill_mlb(alpha = 0.4) + 140 | scale_y_mlb() + 141 | theme_minimal() + 142 | # theme_*_mlb requires gridtext version > 0.1.4 143 | theme_y_mlb() 144 | } 145 | } 146 | } 147 | -------------------------------------------------------------------------------- /man/scale_mlb.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/scale_mlb.R 3 | \name{scale_mlb} 4 | \alias{scale_color_mlb} 5 | \alias{scale_colour_mlb} 6 | \alias{scale_fill_mlb} 7 | \title{Scales for MLB Team Colors} 8 | \usage{ 9 | scale_color_mlb( 10 | type = c("primary", "secondary"), 11 | values = NULL, 12 | ..., 13 | aesthetics = "colour", 14 | breaks = ggplot2::waiver(), 15 | na.value = "grey50", 16 | guide = NULL, 17 | alpha = NA 18 | ) 19 | 20 | scale_colour_mlb( 21 | type = c("primary", "secondary"), 22 | values = NULL, 23 | ..., 24 | aesthetics = "colour", 25 | breaks = ggplot2::waiver(), 26 | na.value = "grey50", 27 | guide = NULL, 28 | alpha = NA 29 | ) 30 | 31 | scale_fill_mlb( 32 | type = c("primary", "secondary"), 33 | values = NULL, 34 | ..., 35 | aesthetics = "fill", 36 | breaks = ggplot2::waiver(), 37 | na.value = "grey50", 38 | guide = NULL, 39 | alpha = NA 40 | ) 41 | } 42 | \arguments{ 43 | \item{type}{One of \code{"primary"} or \code{"secondary"} to decide which colortype to use.} 44 | 45 | \item{values}{If \code{NULL} (the default) use the internal team color vectors. Otherwise 46 | a set of aesthetic values to map data values to. The values 47 | will be matched in order (usually alphabetical) with the limits of the 48 | scale, or with \code{breaks} if provided. If this is a named vector, then the 49 | values will be matched based on the names instead. Data values that don't 50 | match will be given \code{na.value}.} 51 | 52 | \item{...}{ 53 | Arguments passed on to \code{\link[ggplot2:discrete_scale]{discrete_scale}} 54 | \describe{ 55 | \item{\code{limits}}{One of: 56 | \itemize{ 57 | \item \code{NULL} to use the default scale values 58 | \item A character vector that defines possible values of the scale and their 59 | order 60 | \item A function that accepts the existing (automatic) values and returns 61 | new ones. Also accepts rlang \link[rlang:as_function]{lambda} function 62 | notation. 63 | }} 64 | \item{\code{drop}}{Should unused factor levels be omitted from the scale? 65 | The default, \code{TRUE}, uses the levels that appear in the data; 66 | \code{FALSE} includes the levels in the factor. Please note that to display 67 | every level in a legend, the layer should use \code{show.legend = TRUE}.} 68 | \item{\code{na.translate}}{Unlike continuous scales, discrete scales can easily show 69 | missing values, and do so by default. If you want to remove missing values 70 | from a discrete scale, specify \code{na.translate = FALSE}.} 71 | \item{\code{name}}{The name of the scale. Used as the axis or legend title. If 72 | \code{waiver()}, the default, the name of the scale is taken from the first 73 | mapping used for that aesthetic. If \code{NULL}, the legend title will be 74 | omitted.} 75 | \item{\code{labels}}{One of: 76 | \itemize{ 77 | \item \code{NULL} for no labels 78 | \item \code{waiver()} for the default labels computed by the 79 | transformation object 80 | \item A character vector giving labels (must be same length as \code{breaks}) 81 | \item An expression vector (must be the same length as breaks). See ?plotmath for details. 82 | \item A function that takes the breaks as input and returns labels 83 | as output. Also accepts rlang \link[rlang:as_function]{lambda} function 84 | notation. 85 | }} 86 | \item{\code{guide}}{A function used to create a guide or its name. See 87 | \code{\link[ggplot2:guides]{guides()}} for more information.} 88 | \item{\code{call}}{The \code{call} used to construct the scale for reporting messages.} 89 | \item{\code{super}}{The super class to use for the constructed scale} 90 | }} 91 | 92 | \item{aesthetics}{Character string or vector of character strings listing the 93 | name(s) of the aesthetic(s) that this scale works with. This can be useful, for 94 | example, to apply colour settings to the \code{colour} and \code{fill} aesthetics at the 95 | same time, via \code{aesthetics = c("colour", "fill")}.} 96 | 97 | \item{breaks}{One of: 98 | \itemize{ 99 | \item \code{NULL} for no breaks 100 | \item \code{waiver()} for the default breaks (the scale limits) 101 | \item A character vector of breaks 102 | \item A function that takes the limits as input and returns breaks 103 | as output 104 | }} 105 | 106 | \item{na.value}{The aesthetic value to use for missing (\code{NA}) values} 107 | 108 | \item{guide}{A function used to create a guide or its name. If \code{NULL} (the default) 109 | no guide will be plotted for this scale. See \code{\link[ggplot2:guides]{ggplot2::guides()}} for more information.} 110 | 111 | \item{alpha}{Factor to modify color transparency via a call to \code{\link[scales:alpha]{scales::alpha()}}. 112 | If \code{NA} (the default) no transparency will be applied. Can also be a vector of 113 | alphas. All alpha levels must be in range \verb{[0,1]}.} 114 | } 115 | \value{ 116 | A discrete ggplot2 scale created with \code{\link[ggplot2:scale_manual]{ggplot2::scale_color_manual()}} or 117 | \code{\link[ggplot2:scale_manual]{ggplot2::scale_fill_manual()}}. 118 | } 119 | \description{ 120 | These functions map MLB team names to their team colors in 121 | color and fill aesthetics 122 | } 123 | \examples{ 124 | \donttest{ 125 | library(mlbplotR) 126 | library(ggplot2) 127 | 128 | team_abbr <- valid_team_names() 129 | # remove league logos from this example 130 | team_abbr <- team_abbr[!team_abbr \%in\% c("AL", "NL", "MLB")] 131 | 132 | df <- data.frame( 133 | random_value = runif(length(team_abbr), 0, 1), 134 | teams = team_abbr 135 | ) 136 | ggplot(df, aes(x = teams, y = random_value)) + 137 | geom_col(aes(color = teams, fill = teams), width = 0.5) + 138 | scale_color_mlb(type = "secondary") + 139 | scale_fill_mlb(alpha = 0.4) + 140 | theme_minimal() + 141 | theme(axis.text.x = element_text(angle = 45, hjust = 1)) 142 | } 143 | } 144 | -------------------------------------------------------------------------------- /man/theme_mlb.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/theme_mlb.R 3 | \name{theme_mlb} 4 | \alias{theme_x_mlb} 5 | \alias{theme_y_mlb} 6 | \title{Theme for MLB Team Logos} 7 | \usage{ 8 | theme_x_mlb() 9 | 10 | theme_y_mlb() 11 | } 12 | \value{ 13 | A ggplot2 theme created with \code{\link[ggplot2:theme]{ggplot2::theme()}}. 14 | } 15 | \description{ 16 | \ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#superseded}{\figure{lifecycle-superseded.svg}{options: alt='[Superseded]'}}}{\strong{[Superseded]}} 17 | \code{theme_x_mlb()} and \code{theme_y_mlb()} have been superceded in favor of \verb{element_*_logo()} functions 18 | These functions are convenience wrappers around a theme call 19 | that activates markdown in x-axis and y-axis labels 20 | using \code{\link[ggtext:element_markdown]{ggtext::element_markdown()}}. 21 | } 22 | \details{ 23 | These functions are a wrapper around the function calls 24 | \code{ggplot2::theme(axis.text.x = ggtext::element_markdown())} as well as 25 | \code{ggplot2::theme(axis.text.y = ggtext::element_markdown())}. 26 | They are made to be used in conjunction with \code{\link[=scale_x_mlb]{scale_x_mlb()}} and 27 | \code{\link[=scale_y_mlb]{scale_y_mlb()}} respectively. 28 | } 29 | \examples{ 30 | \donttest{ 31 | library(mlbplotR) 32 | library(ggplot2) 33 | 34 | team_abbr <- valid_team_names() 35 | # remove conference logos from this example 36 | team_abbr <- team_abbr[!team_abbr \%in\% c("AL", "NL", "MLB")] 37 | 38 | df <- data.frame( 39 | random_value = runif(length(team_abbr), 0, 1), 40 | teams = team_abbr 41 | ) 42 | if (utils::packageVersion("gridtext") > "0.1.4"){ 43 | ggplot(df, aes(x = teams, y = random_value)) + 44 | geom_col(aes(color = teams, fill = teams), width = 0.5) + 45 | scale_color_mlb(type = "secondary") + 46 | scale_fill_mlb(alpha = 0.4) + 47 | scale_x_mlb() + 48 | theme_minimal() + 49 | # theme_*_mlb requires gridtext version > 0.1.4 50 | theme_x_mlb() 51 | } 52 | } 53 | } 54 | \seealso{ 55 | \code{\link[=theme_x_mlb]{theme_x_mlb()}}, \code{\link[=theme_y_mlb]{theme_y_mlb()}} 56 | } 57 | -------------------------------------------------------------------------------- /man/valid_team_names.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/load_data.R 3 | \name{valid_team_names} 4 | \alias{valid_team_names} 5 | \title{Output Valid MLB Team Abbreviations} 6 | \usage{ 7 | valid_team_names(remove_league_info = FALSE) 8 | } 9 | \arguments{ 10 | \item{remove_league_info}{Should "AL", "NL", and "MLB" be removed from the returned vector? Defaults to \code{FALSE}.} 11 | } 12 | \value{ 13 | A vector of type \code{"character"}. 14 | } 15 | \description{ 16 | Output Valid MLB Team Abbreviations 17 | } 18 | \examples{ 19 | \donttest{ 20 | # List valid team abbreviations excluding duplicates 21 | valid_team_names() 22 | valid_team_names(TRUE) 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /mlbplotR.Rproj: -------------------------------------------------------------------------------- 1 | Version: 1.0 2 | 3 | RestoreWorkspace: Default 4 | SaveWorkspace: Default 5 | AlwaysSaveHistory: Default 6 | 7 | EnableCodeIndexing: Yes 8 | UseSpacesForTab: Yes 9 | NumSpacesForTab: 2 10 | Encoding: UTF-8 11 | 12 | RnwWeave: Sweave 13 | LaTeX: pdfLaTeX 14 | 15 | AutoAppendNewline: Yes 16 | StripTrailingWhitespace: Yes 17 | 18 | BuildType: Package 19 | PackageUseDevtools: Yes 20 | PackageInstallArgs: --no-multiarch --with-keep.source 21 | -------------------------------------------------------------------------------- /pkgdown/favicon/apple-touch-icon-120x120.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/camdenk/mlbplotR/28dd1d26de2b5ce4785976051a91bf260a8f4237/pkgdown/favicon/apple-touch-icon-120x120.png -------------------------------------------------------------------------------- /pkgdown/favicon/apple-touch-icon-152x152.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/camdenk/mlbplotR/28dd1d26de2b5ce4785976051a91bf260a8f4237/pkgdown/favicon/apple-touch-icon-152x152.png -------------------------------------------------------------------------------- /pkgdown/favicon/apple-touch-icon-180x180.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/camdenk/mlbplotR/28dd1d26de2b5ce4785976051a91bf260a8f4237/pkgdown/favicon/apple-touch-icon-180x180.png -------------------------------------------------------------------------------- /pkgdown/favicon/apple-touch-icon-60x60.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/camdenk/mlbplotR/28dd1d26de2b5ce4785976051a91bf260a8f4237/pkgdown/favicon/apple-touch-icon-60x60.png -------------------------------------------------------------------------------- /pkgdown/favicon/apple-touch-icon-76x76.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/camdenk/mlbplotR/28dd1d26de2b5ce4785976051a91bf260a8f4237/pkgdown/favicon/apple-touch-icon-76x76.png -------------------------------------------------------------------------------- /pkgdown/favicon/apple-touch-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/camdenk/mlbplotR/28dd1d26de2b5ce4785976051a91bf260a8f4237/pkgdown/favicon/apple-touch-icon.png -------------------------------------------------------------------------------- /pkgdown/favicon/favicon-16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/camdenk/mlbplotR/28dd1d26de2b5ce4785976051a91bf260a8f4237/pkgdown/favicon/favicon-16x16.png -------------------------------------------------------------------------------- /pkgdown/favicon/favicon-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/camdenk/mlbplotR/28dd1d26de2b5ce4785976051a91bf260a8f4237/pkgdown/favicon/favicon-32x32.png -------------------------------------------------------------------------------- /pkgdown/favicon/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/camdenk/mlbplotR/28dd1d26de2b5ce4785976051a91bf260a8f4237/pkgdown/favicon/favicon.ico -------------------------------------------------------------------------------- /revdep/.gitignore: -------------------------------------------------------------------------------- 1 | checks 2 | library 3 | checks.noindex 4 | library.noindex 5 | cloud.noindex 6 | data.sqlite 7 | *.html 8 | -------------------------------------------------------------------------------- /revdep/README.md: -------------------------------------------------------------------------------- 1 | # Platform 2 | 3 | |field |value | 4 | |:--------|:------------------------------------------------| 5 | |version |R version 4.2.0 (2022-04-22) | 6 | |os |macOS 13.4 | 7 | |system |x86_64, darwin17.0 | 8 | |ui |RStudio | 9 | |language |(EN) | 10 | |collate |en_US.UTF-8 | 11 | |ctype |en_US.UTF-8 | 12 | |tz |America/Chicago | 13 | |date |2023-06-19 | 14 | |rstudio |2023.06.0+421 Mountain Hydrangea (desktop) | 15 | |pandoc |2.12 @ /Users/camdenkay/opt/anaconda3/bin/pandoc | 16 | 17 | # Dependencies 18 | 19 | |package |old |new |Δ | 20 | |:-----------|:-----|:----------|:--| 21 | |mlbplotR |1.0.1 |1.0.1.9003 |* | 22 | |bslib |NA |0.5.0 |* | 23 | |commonmark |NA |1.9.0 |* | 24 | |dplyr |NA |1.1.2 |* | 25 | |fontawesome |NA |0.5.1 |* | 26 | |ggplot2 |NA |3.4.2 |* | 27 | |gt |NA |0.9.0 |* | 28 | |gtable |NA |0.3.3 |* | 29 | |htmltools |NA |0.5.5 |* | 30 | |htmlwidgets |NA |1.6.2 |* | 31 | |magick |NA |2.7.4 |* | 32 | |markdown |NA |1.7 |* | 33 | |rmarkdown |NA |2.22 |* | 34 | |sass |NA |0.4.6 |* | 35 | |tinytex |NA |0.45 |* | 36 | |V8 |NA |4.3.0 |* | 37 | |viridisLite |NA |0.4.2 |* | 38 | |xml2 |NA |1.3.4 |* | 39 | 40 | # Revdeps 41 | 42 | -------------------------------------------------------------------------------- /revdep/cran.md: -------------------------------------------------------------------------------- 1 | ## revdepcheck results 2 | 3 | We checked 0 reverse dependencies, comparing R CMD check results across CRAN and dev versions of this package. 4 | 5 | * We saw 0 new problems 6 | * We failed to check 0 packages 7 | 8 | -------------------------------------------------------------------------------- /revdep/email.yml: -------------------------------------------------------------------------------- 1 | release_date: ??? 2 | rel_release_date: ??? 3 | my_news_url: ??? 4 | release_version: ??? 5 | release_details: ??? 6 | -------------------------------------------------------------------------------- /revdep/failures.md: -------------------------------------------------------------------------------- 1 | *Wow, no problems at all. :)* -------------------------------------------------------------------------------- /revdep/problems.md: -------------------------------------------------------------------------------- 1 | *Wow, no problems at all. :)* -------------------------------------------------------------------------------- /vignettes/articles/man/figures/README-axis-example-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/camdenk/mlbplotR/28dd1d26de2b5ce4785976051a91bf260a8f4237/vignettes/articles/man/figures/README-axis-example-1.png -------------------------------------------------------------------------------- /vignettes/articles/man/figures/README-bar-example-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/camdenk/mlbplotR/28dd1d26de2b5ce4785976051a91bf260a8f4237/vignettes/articles/man/figures/README-bar-example-1.png -------------------------------------------------------------------------------- /vignettes/articles/man/figures/README-every-team-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/camdenk/mlbplotR/28dd1d26de2b5ce4785976051a91bf260a8f4237/vignettes/articles/man/figures/README-every-team-1.png -------------------------------------------------------------------------------- /vignettes/articles/man/figures/README-headshot-example-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/camdenk/mlbplotR/28dd1d26de2b5ce4785976051a91bf260a8f4237/vignettes/articles/man/figures/README-headshot-example-1.png -------------------------------------------------------------------------------- /vignettes/articles/man/figures/README-scatter-example-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/camdenk/mlbplotR/28dd1d26de2b5ce4785976051a91bf260a8f4237/vignettes/articles/man/figures/README-scatter-example-1.png -------------------------------------------------------------------------------- /vignettes/articles/mlbplotR.Rmd: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Getting Started with mlbplotR" 3 | description: "A brief introduction to the ggplot2 extension." 4 | author: "Camden Kay" 5 | output: rmarkdown::html_vignette 6 | vignette: > 7 | %\VignetteIndexEntry{Getting Started with mlbplotR} 8 | %\VignetteEngine{knitr::rmarkdown} 9 | %\VignetteEncoding{UTF-8} 10 | --- 11 | 12 | ```{r, include = FALSE} 13 | knitr::opts_chunk$set( 14 | collapse = TRUE, 15 | comment = "#>", 16 | out.width = "100%", 17 | dpi = 600 18 | ) 19 | 20 | 21 | # Preset dataframes 22 | library(dplyr) 23 | 24 | filtered_df <- tibble::tribble( 25 | ~Team, ~ERA, ~FIP, ~HR, 26 | "ARI", 4.3, 4.25, 19, 27 | "ATL", 3.04, 3.31, 15, 28 | "BAL", 3.62, 4.62, 30, 29 | "BOS", 3.75, 2.79, 15, 30 | "CHC", 4.77, 4.89, 31, 31 | "CHW", 2.37, 2.65, 13, 32 | "CIN", 3.37, 3.97, 17, 33 | "CLE", 3.12, 4.05, 14, 34 | "COL", 4.33, 4.63, 20, 35 | "DET", 3.71, 4.71, 24, 36 | "HOU", 3.14, 4.01, 12, 37 | "KCR", 4.77, 5.6, 22, 38 | "LAA", 3.18, 3.52, 15, 39 | "LAD", 2.47, 3.16, 19, 40 | "MIA", 2.64, 2.55, 6, 41 | "MIL", 2.43, 1.63, 7, 42 | "MIN", 3.72, 4.27, 17, 43 | "NYM", 3.02, 3.49, 17, 44 | "NYY", 3.23, 2.92, 24, 45 | "OAK", 3.15, 3.34, 15, 46 | "PHI", 2.78, 2.59, 16, 47 | "PIT", 5.36, 5.16, 28, 48 | "SDP", 3.27, 3.73, 22, 49 | "SEA", 3.61, 3.89, 19, 50 | "SFG", 2.81, 3, 20, 51 | "STL", 3.05, 3.66, 21, 52 | "TBR", 3.43, 3.31, 14, 53 | "TEX", 4.55, 3.94, 12, 54 | "TOR", 2.84, 3.69, 33, 55 | "WSN", 4.02, 4.43, 17 56 | ) 57 | 58 | top_12 <- tibble::tribble( 59 | ~playerid, ~ERA, ~FIP, 60 | 16137, 2.37, 2.65, 61 | 19361, 2.43, 1.63, 62 | 3137, 2.46, 2.97, 63 | 19374, 2.47, 3.16, 64 | 16162, 2.56, 2.96, 65 | 12703, 2.59, 4.03, 66 | 22286, 2.64, 2.55, 67 | 2520, 2.69, 3.32, 68 | 10310, 2.78, 2.59, 69 | 14107, 2.81, 3, 70 | 11486, 2.84, 3.69, 71 | 18679, 2.85, 3.14 72 | ) 73 | 74 | ``` 75 | 76 | ## Installation 77 | 78 | The easiest way to get mlbplotR is to install it from [CRAN](https://CRAN.R-project.org) with: 79 | 80 | ``` r 81 | install.packages("mlbplotR") 82 | ``` 83 | 84 | To get a bug fix or use a feature from the development version, you can install the development version from [GitHub](https://github.com/) with: 85 | 86 | ``` r 87 | # install.packages("devtools") 88 | devtools::install_github("camdenk/mlbplotR") 89 | ``` 90 | 91 | ## Examples 92 | 93 | Let's plot every team on a grid with some extra customization: 94 | 95 | ```{r every-team, message = FALSE} 96 | library(mlbplotR) 97 | library(ggplot2) 98 | library(dplyr) 99 | 100 | teams_colors_logos <- mlbplotR::load_mlb_teams() |> 101 | dplyr::filter(!team_abbr %in% c("AL", "NL", "MLB")) |> 102 | dplyr::mutate( 103 | a = rep(1:6, 5), 104 | b = sort(rep(1:5, 6), decreasing = TRUE), 105 | # Keep alpha == 1 for teams that have an "A" 106 | alpha = ifelse(grepl("A", team_abbr), 1, 0.75), 107 | # Set teams that have an "E" to black & white 108 | color = ifelse(grepl("E", team_abbr), "b/w", NA) 109 | ) 110 | 111 | 112 | ggplot2::ggplot(teams_colors_logos, aes(x = a, y = b)) + 113 | mlbplotR::geom_mlb_logos(aes(team_abbr = team_abbr, 114 | color = color, alpha = alpha), 115 | width = 0.075) + 116 | ggplot2::geom_label(aes(label = team_abbr), nudge_y = -0.35, alpha = 0.5) + 117 | ggplot2::scale_color_identity() + 118 | ggplot2::scale_alpha_identity() + 119 | ggplot2::theme_void() 120 | ``` 121 | 122 | This is a basic example with [FanGraphs](https://fangraphs.com) data (pulled using baseballr) which compares ERA to FIP for each team's top starting pitcher by ERA: 123 | 124 | ```{r scatter-example, message = FALSE} 125 | # Uncomment this to pull data, currently commented out to save 126 | # a dependency on baseballr 127 | # 128 | # library(baseballr) 129 | # 130 | # df <- baseballr::fg_pitcher_leaders(x = 2021, y = 2021, 131 | # q = 100, pitcher_type = "sta") 132 | # 133 | # filtered_df <- df |> 134 | # dplyr::filter(Team != "- - -") |> 135 | # # FanGraphs Team abbreviations aren't the standard 136 | # # for what's used in the plotting functions so 137 | # # you could clean them with the following line, 138 | # # but the geom_*_logos() functions should all 139 | # # clean the abbreviations before plotting 140 | # # 141 | # # dplyr::mutate(Team = clean_team_abbrs(Team)) |> 142 | # dplyr::group_by(Team) |> 143 | # dplyr::slice_min(ERA, n = 1) |> 144 | # dplyr::ungroup() 145 | 146 | library(scales) 147 | 148 | filtered_df |> 149 | ggplot2::ggplot(aes(x = ERA, y = FIP)) + 150 | mlbplotR::geom_mlb_logos(aes(team_abbr = Team), width = 0.075, alpha = 0.7) + 151 | ggplot2::labs(title = "2021: ERA vs. FIP", 152 | subtitle = "Each Team's Top Starter By ERA | Min. 100 IP", 153 | caption = "Data: FanGraphs via baseballr") + 154 | ggplot2::theme_minimal() + 155 | ggplot2::theme(plot.title = ggplot2::element_text(face = "bold")) + 156 | ggplot2::scale_x_reverse(breaks = scales::pretty_breaks(), 157 | labels = scales::number_format(accuracy = 0.01), 158 | expand = c(.1, .1)) + 159 | ggplot2::scale_y_reverse(breaks = scales::pretty_breaks(), 160 | labels = scales::number_format(accuracy = 0.01), 161 | expand = c(.1, .1)) 162 | ``` 163 | 164 | Here's another that looks at Home Runs Allowed by top pitchers: 165 | 166 | ```{r bar-example, message = FALSE} 167 | filtered_df |> 168 | # The scale_*_mlb() functions don't auto-clean abbreviations 169 | dplyr::mutate(Team = clean_team_abbrs(Team)) |> 170 | ggplot2::ggplot(aes(x = Team, y = HR)) + 171 | ggplot2::geom_col(aes(color = Team, fill = Team), width = 0.5) + 172 | mlbplotR::geom_mlb_logos(aes(team_abbr = Team), width = 0.07, alpha = 0.9) + 173 | mlbplotR::scale_color_mlb(type = "secondary") + 174 | mlbplotR::scale_fill_mlb(alpha = 0.4) + 175 | ggplot2::labs(title = "2021: Home Runs Allowed For Top Pitchers", 176 | subtitle = "HRs Allowed By Each Team's Top Starter By ERA | Min. 100 IP", 177 | caption = "Data: FanGraphs via baseballr") + 178 | ggplot2::theme_minimal() + 179 | ggplot2::theme(plot.title = ggplot2::element_text(face = "bold"), 180 | axis.title.x = ggplot2::element_blank(), 181 | axis.text.x = ggplot2::element_blank(), 182 | panel.grid.major.x = element_blank()) + 183 | ggplot2::scale_x_discrete(expand = c(0.05, 0.075)) 184 | ``` 185 | 186 | Instead of putting the logos in the plot, we can have them be the axis labels: 187 | 188 | ```{r axis-example, message = FALSE} 189 | filtered_df |> 190 | # The scale_*_mlb() functions don't auto-clean abbreviations 191 | dplyr::mutate(Team = clean_team_abbrs(Team)) |> 192 | ggplot2::ggplot(aes(x = Team, y = HR)) + 193 | ggplot2::geom_col(aes(color = Team, fill = Team), width = 0.5) + 194 | #mlbplotR::geom_mlb_logos(aes(team_abbr = Team), width = 0.07, alpha = 0.9) + 195 | mlbplotR::scale_color_mlb(type = "secondary") + 196 | mlbplotR::scale_fill_mlb(alpha = 0.4) + 197 | ggplot2::labs(title = "2021: Home Runs Allowed", 198 | subtitle = "HRs Allowed By Each Team's Top Starter By ERA | Min. 100 IP", 199 | caption = "Data: FanGraphs via baseballr") + 200 | ggplot2::theme_minimal() + 201 | ggplot2::theme(plot.title = ggplot2::element_text(face = "bold"), 202 | axis.title.x = ggplot2::element_blank(), 203 | panel.grid.major.x = ggplot2::element_blank(), 204 | # this line triggers the replacement of team abbreviations with logos 205 | axis.text.x = mlbplotR::element_mlb_logo()) + 206 | ggplot2::scale_x_discrete(expand = c(0.05, 0.075)) + 207 | ggplot2::scale_y_continuous(expand = c(0, 0, 0.05, 0)) 208 | ``` 209 | 210 | 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. 211 | 212 | 213 | 214 | Lastly, here's an example using headshots: 215 | 216 | ```{r headshot-example, message = FALSE} 217 | # top_12 <- df |> 218 | # dplyr::mutate(playerid = as.double(playerid)) |> 219 | # dplyr::slice_min(ERA, n = 12) 220 | 221 | top_12 |> 222 | dplyr::left_join(mlbplotR::load_headshots(), 223 | by = c("playerid" = "fangraphs_id")) |> 224 | ggplot(aes(x = ERA, y = FIP)) + 225 | mlbplotR::geom_mlb_headshots(aes(player_id = savant_id), height = 0.15) + 226 | ggplot2::scale_x_reverse(breaks = scales::pretty_breaks(), 227 | labels = scales::number_format(accuracy = 0.01), 228 | expand = c(.1, .1)) + 229 | ggplot2::scale_y_reverse(breaks = scales::pretty_breaks(), 230 | labels = scales::number_format(accuracy = 0.01), 231 | expand = c(.1, .1)) + 232 | ggplot2::labs(title = "2021 SP ERA Leaders", 233 | subtitle = "Minimum 100 IP", 234 | caption = "Data: FanGraphs via baseballr") + 235 | ggplot2::theme_minimal() + 236 | ggplot2::theme(plot.title = ggplot2::element_text(face = "bold")) 237 | 238 | ``` 239 | 240 | Note: If a player's headshot data can't be found, their headshot will be replaced with the MLB logo by default. 241 | --------------------------------------------------------------------------------