https://github.com/sportsdataverse/sportyR

R package for drawing regulation playing surfaces for several sports

https://github.com/sportsdataverse/sportyR

Science Score: 26.0%

This score indicates how likely this project is to be science-related based on various indicators:

  • CITATION.cff file
  • codemeta.json file
    Found codemeta.json file
  • .zenodo.json file
    Found .zenodo.json file
  • DOI references
  • Academic publication links
  • Committers with academic emails
  • Institutional organization owner
  • JOSS paper metadata
  • Scientific vocabulary similarity
    Low similarity (17.7%) to scientific vocabulary

Keywords

football ggplot2 playing-surfaces r r-package rstats sport sports-analytics sports-data sports-tracking-data sportsdataverse visualization
Last synced: 5 months ago · JSON representation

Repository

R package for drawing regulation playing surfaces for several sports

Basic Info
Statistics
  • Stars: 110
  • Watchers: 5
  • Forks: 10
  • Open Issues: 9
  • Releases: 8
Topics
football ggplot2 playing-surfaces r r-package rstats sport sports-analytics sports-data sports-tracking-data sportsdataverse visualization
Created almost 5 years ago · Last pushed 7 months ago
Metadata Files
Readme Changelog Contributing Code of conduct

README.Rmd

---
output: github_document
editor_options: 
  markdown: 
    wrap: 72
---



```{r, include = FALSE}
knitr::opts_chunk$set(
  collapse = TRUE,
  cache = TRUE,
  comment = "#>",
  fig.path = "man/figures/README-",
  out.width = "100%",
  dpi = 600
)
```

# sportyR 


[![CRAN
version](https://img.shields.io/badge/dynamic/json?style=flat&color=ff552e&label=CRAN version&prefix=v&query=%24.Version&url=https%3A%2F%2Fcrandb.r-pkg.org%2FsportyR)](https://CRAN.R-project.org/package=sportyR)
[![CRAN
downloads](https://img.shields.io/badge/dynamic/json?style=flat&color=ff552e&label=Downloads&query=%24[0].downloads&url=https%3A%2F%2Fcranlogs.r-pkg.org%2Fdownloads%2Ftotal%2F2021-10-26%3Alast-day%2FsportyR)](https://CRAN.R-project.org/package=sportyR)
[![Version-Number](https://img.shields.io/github/r-package/v/sportsdataverse/sportyR?label=sportyR&logo=R&style=flat&color=ff552e&logoColor=1d9bf0)](https://github.com/sportsdataverse/sportyR/)
[![R-CMD-check](https://img.shields.io/github/workflow/status/sportsdataverse/sportyR/R-CMD-check?label=R-CMD-Check&logo=R&&style=flat&logoColor=1d9bf0)](https://github.com/sportsdataverse/sportyR/actions/workflows/R-CMD-check.yaml)
[![codecov](https://img.shields.io/codecov/c/github/sportsdataverse/sportyR?color=ff552e&label=codecov&logo=codecov)](https://codecov.io/gh/sportsdataverse/sportyR)
[![Lifecycle:maturing](https://img.shields.io/badge/lifecycle-maturing-blue.svg?style=flat&logo=github&color=ff552e)](https://github.com/sportsdataverse/sportyR/)
[![Twitter
Follow](https://img.shields.io/twitter/follow/sportyR_pkg?&label=%40sportyR_pkg&logo=twitter&style=flat&color=ff552e)](https://twitter.com/sportyR_pkg)
[![Twitter
Follow](https://img.shields.io/twitter/follow/sportsdataverse?&label=%40sportsdataverse&logo=twitter&style=flat&color=ff552e)](https://twitter.com/sportsdataverse)



As the field of sports analytics evolve, there's a growing need for
methods to both track and visualize players throughout the game. This
package aims to make this easy regardless of sport needed to be plotted.

This repository contains code necessary to draw scale versions of playing surfaces to visualize play-by-play data for baseball, basketball, curling, football, hockey, soccer, and tennis in **R**. For the **Python** version of this package, click [here](https://github.com/sportsdataverse/sportypy).


## Installation

The most recent release of `sportyR` is available on
[CRAN](https://cran.r-project.org/web/packages/sportyR/index.html), and
it can be installed directly via:

```{r readme-install-package-cran, eval = FALSE}
# Install released version from CRAN
install.packages("sportyR")
```

The development version of `sportyR` can be installed from
[GitHub](https://github.com/sportsdataverse/sportyR) with:

```{r readme-install-package-github, eval = FALSE}
# Install development version from GitHub
devtools::install_github("sportsdataverse/sportyR")
```

Once the library is installed, be sure to load it into the working
environment.

```{r readme-load-sportyR}
# Required to use package
library(sportyR)
```

## Plotting Functions {#plotting-functions}

All plotting functions in this library are named as `geom_{sport}()`,
and take the following arguments:

-   `league`: the league code for the sport. In all functions, this will
    ***NOT*** have a default value. The supplied league is
    **case-insensitive**. Future iterations of this package may allow
    the full league name to be supplied if desired (e.g.
    `league = 'National Basketball Associaton'` instead of
    `league = 'NBA'`), but this feature is not currently available.

-   `display_range`: This automatically "zooms" in on the area of the
    plot you're interested in. Valid ranges here vary by sport, but can
    be found by calling `?geom_{sport}` and reading about the display
    ranges

-   `x_trans` and `y_trans`: By default, the origin of the coordinate
    system *always* lies at the center of the plot. For example,
    `(0, 0)` on a basketball court lies along the division line and on
    the line that connects the center of each basket. If you want to
    shift the origin (and therefore the entire plot), use `x_trans` and
    `y_trans` to do so

-   `{surface_type}_updates`: A list of updates to the parameters that
    define the surface. I'll demo how to use this to change a hockey
    rink in a different vignette, but I'll call this out here

-   `color_updates`: A list that contains updates to the features'
    colors on the plot. These are named by what the feature is, using
    `snake_case` to specify the names. To get the list of color names
    you can change, try running `cani_color_league_features()` with your
    desired league

-   `rotation`: An angle (in degrees) that you'd like to rotate the plot
    by, where +\theta is counterclockwise

-   `xlims` and `ylims`: Any limits you'd like to put on the plot in the
    x and y direction. These will overwrite anything set by the
    `display_range` parameter

-   `{surface}_units`: If your data is in units that are different than
    how the rule book of the league specifies the units (e.g. you've got
    NHL data in inches, but the rule book describes the rink in feet),
    change this parameter to match the units you've got your data in.
    You're welcome to change the units of the data as well, but this is
    provided for convenience

## TV View and Display Ranges

### TV View

All of the `geom_{sport}()` functions, by default, will draw the surface
in what can be considered "TV view", or the way that the surface would
typically be displayed on a television broadcast. This typically means
the action moves from left to right across the screen (a basketball game
that has the baskets on the left and right end of the court). As
mentioned above, it is possible to change this to be in any orientation
through the `rotation` parameter to each `geom_{sport}()` function.

There are a few exceptions to this:

-   `geom_baseball()` is displayed from the high-home view by default,
    as baseball coordinates typically have the `+y` axis extending from
    the back tip of home plate towards center field

-   `geom_tennis()` is displayed with the court diagrammed from the
    perspective of the chair umpire

### Display Ranges

Related to the idea of custom displays of the plot is the concept of the
`display_range` parameter in the `geom_{sport}()` function. This is
unique to each sport, but globally supported across the package. This
parameter allows the specification of a designated region of the surface
to display. As an example, if you're trying to limit the analysis of NFL
data to being inside of the red zone, you may want to do something
similar to the following:

```{r readme-display-range-demo, dev = "png"}
# Display only the red zone of the football field
geom_football("nfl", display_range = "red zone")
```


Another use case would be to make the data you're viewing easier to see. Say you wanted to look at curling data, but only cared about stone positions in the house (and not the path as to how the stones got there). You might do this:

```{r readme-display-range-curling-demo, dev = "png"}
# Display only the house on a curling sheet
geom_curling("wcf", display_range = "house")
```

## Plot Units

Each plot function has a standardized unit of measure in which the plot
is created, and is standardized by the primary units specified in their
respective rule books. They are as follows (and any explanation is in
parentheses):

```{r readme-plot-units-table, echo = FALSE}
units_df <- data.frame(
  sport = c(
    rep("Baseball", 6),
    rep("Basketball", 6),
    rep("Curling", 1),
    rep("Football", 7),
    rep("Hockey", 11),
    rep("Lacrosse", 7),
    rep("Soccer", 5),
    rep("Tennis", 6),
    rep("Volleyball", 3)
  ),
  league = c(
    # Baseball
    "Little League",
    "MiLB",
    "MLB",
    "NCAA",
    "NFHS (High School)",
    "Pony",
    # Basketball
    "FIBA",
    "NBA",
    "NBA G League",
    "NCAA",
    "NFHS",
    "WNBA",
    # Curling
    "WCF (World Curling Federation)",
    # Football
    "CFL",
    "NCAA",
    "NFHS11 (High School, 11 players)",
    "NFHS6 (High School, 6 players)",
    "NFHS8 (High School, 8 players)",
    "NFHS9 (High School, 9 players)",
    "NFL",
    # Hockey
    "AHL",
    "ECHL",
    "IIHF",
    "NCAA",
    "NHL",
    "NWHL",
    "OHL",
    "PHF",
    "PWHL",
    "QMJHL",
    "USHL",
    # Lacrosse
    "NCAAM",
    "NCAAW",
    "NLL",
    "PLL",
    "USA Men's",
    "USA Women's",
    "World Lacrosse",
    # Soccer
    "EPL",
    "FIFA",
    "MLS",
    "NCAA",
    "NWSL",
    # Tennis
    "ATP",
    "ITA",
    "ITF",
    "NCAA",
    "USTA",
    "WTA",
    # Volleyball
    "FIVB",
    "NCAA",
    "USA Volleyball"
  ),
  primary_unit = c(
    rep("`ft`", 6),
    rep("`m`", 1),
    rep("`ft`", 5),
    rep("`ft`", 1),
    rep("`yd`", 7),
    rep("`ft`", 2),
    rep("`m`", 1),
    rep("`ft`", 8),
    rep("`yd`", 1),
    rep("`m`", 1),
    rep("`ft`", 1),
    rep("`yd`", 2),
    rep("`m`", 1),
    rep("`ft`", 1),
    rep("`m`", 2),
    rep("`yd`", 3),
    rep("`ft`", 6),
    rep("`m`", 3)
  )
)

names(units_df) <- c("Sport", "League", "Primary Plotting Unit")

knitr::kable(units_df, align = "c")
```

However, since the data that is supplied may come in various units of
measure, the plots are able to be generated in the data's units. This is
done via the `unit` argument in `geom_{sport}()`. The features
themselves will look visually identical, but the underlying coordinate
grid will change.

Additionally, the `convert_units()` function can be called on a data
frame to convert from the data's arguments to the plot's. For example,
if soccer data is given in yards, but is desirable to be plotted in
meters, calling
`convert_units(tracking_data, 'yd', 'm', conversion_columns = c('x', 'y'))`
will convert the x and y coordinates from yards to meters.

As mentioned [above](#plotting-functions), the `geom_{sport}()` family
of functions allow for rotations of surfaces via the `rotation`
argument. To make this easy, `sportyR` also allows for the rotation of
data frames' coordinates ***so long as they contain an*** `x` ***and***
`y` ***column*** via the `rotate_coords()` function. Reflection is also
possible through `reflect()`.

## Surface Examples

Most playing surfaces are standard in size, so they can be rendered via
a call to the proper `geom_{sport}()` function like so:

```{r readme-mlb-example}
# Draw a basic MLB infield plot
geom_baseball("mlb", display_range = "infield")
```

```{r readme-fifa-example}
# Create a 100m by 75m FIFA pitch
geom_soccer(
  "fifa",
  pitch_updates = list(
    pitch_length = 100,
    pitch_width = 75
  )
)
```

It's also possible to plot partial surfaces and rotated surfaces:

```{r readme-nhl-example}
# Draw half of a rotated NBA court
geom_basketball("nba", display_range = "offense", rotation = 270)
```

## License

This package is released under the [GPL 3.0
License](https://github.com/sportsdataverse/sportyR/blob/master/LICENSE.md).

## Contributions

### League Office

The package maintainers and functional engineers

-   [Ross Drucker](https://github.com/rossdrucker) - `sportyR`
    Commissioner

### General Managers

Contribute by adding a new sport and become its general manager. Current
general managers (and their sports) are:

-   [Ross Drucker](https://github.com/rossdrucker) - Baseball
-   [Ross Drucker](https://github.com/rossdrucker) - Basketball
-   [Ross Drucker](https://github.com/rossdrucker) - Curling
-   [Ross Drucker](https://github.com/rossdrucker) - Football
-   [Ross Drucker](https://github.com/rossdrucker) - Hockey
-   [Ross Drucker](https://github.com/rossdrucker) - Soccer
-   [Ross Drucker](https://github.com/rossdrucker) - Tennis
-   [Ross Drucker](https://github.com/rossdrucker) - Volleyball

### Coaching Staffs

Notice something for a sport that already exists, but isn't quite right?
Join that sport's coaching staff!

### Scout Team

By regularly reporting issues, making very slight modifications, fixing
typos, or just helping others navigate their own issues, you're able to
join the Scout Team!

### Acknowledgements

Much of the underling code structure in `sportyR`, beginning with
`v2.0.0`, was influenced by [The
Bucketless](https://github.com/the-bucketless)'s work on the
[hockey_rink](https://github.com/the-bucketless/hockey_rink) package for
Python.

### `sportyR`tist

The `sportyR` logo was created by Lindsey Kelso. Check her out on
[Instagram](http://Instagram.com/kelsokreationsbylindsey) or her [online
shop](http://kelsokreationsbylindsey.bigcartel.com)!

Owner

  • Name: SportsDataverse
  • Login: sportsdataverse
  • Kind: organization
  • Email: sportsdataverse@gmail.com

GitHub Events

Total
  • Issues event: 7
  • Watch event: 6
  • Delete event: 2
  • Issue comment event: 18
  • Push event: 19
  • Pull request review event: 13
  • Pull request review comment event: 25
  • Pull request event: 6
  • Fork event: 4
  • Create event: 2
Last Year
  • Issues event: 7
  • Watch event: 6
  • Delete event: 2
  • Issue comment event: 18
  • Push event: 19
  • Pull request review event: 13
  • Pull request review comment event: 25
  • Pull request event: 6
  • Fork event: 4
  • Create event: 2

Committers

Last synced: 9 months ago

All Time
  • Total Commits: 413
  • Total Committers: 4
  • Avg Commits per committer: 103.25
  • Development Distribution Score (DDS): 0.022
Past Year
  • Commits: 11
  • Committers: 1
  • Avg Commits per committer: 11.0
  • Development Distribution Score (DDS): 0.0
Top Committers
Name Email Commits
Ross Drucker r****r@g****m 404
olivroy 5****y 6
mrcaseb m****b@g****m 2
Saiem Gilani s****i@g****m 1

Issues and Pull Requests

Last synced: 6 months ago

All Time
  • Total issues: 26
  • Total pull requests: 20
  • Average time to close issues: 2 months
  • Average time to close pull requests: 6 days
  • Total issue authors: 18
  • Total pull request authors: 5
  • Average comments per issue: 1.73
  • Average comments per pull request: 1.95
  • Merged pull requests: 18
  • Bot issues: 0
  • Bot pull requests: 0
Past Year
  • Issues: 5
  • Pull requests: 5
  • Average time to close issues: about 1 month
  • Average time to close pull requests: about 1 hour
  • Issue authors: 5
  • Pull request authors: 2
  • Average comments per issue: 0.8
  • Average comments per pull request: 2.4
  • Merged pull requests: 4
  • Bot issues: 0
  • Bot pull requests: 0
Top Authors
Issue Authors
  • rossdrucker (8)
  • philly1993 (2)
  • jcforaker (1)
  • nguyenank (1)
  • AimanFariz (1)
  • kwartler (1)
  • AndrewUr (1)
  • alanryder (1)
  • Julieblas (1)
  • walinchus (1)
  • errolkaylor (1)
  • guga31bb (1)
  • mileskee (1)
  • Gravypan (1)
  • christophermclement (1)
Pull Request Authors
  • rossdrucker (16)
  • olivroy (3)
  • mrcaseb (1)
  • gpilgrim2670 (1)
  • AimanFariz (1)
Top Labels
Issue Labels
bug (6) new sport request (5) feature request (4) new league request (3) good first issue (2) duplicate (1) dimension correction (1)
Pull Request Labels
bug (3) feature request (2) documentation (2) new sport request (2) new league request (2)

Packages

  • Total packages: 1
  • Total downloads:
    • cran 681 last-month
  • Total docker downloads: 41,971
  • Total dependent packages: 1
  • Total dependent repositories: 2
  • Total versions: 8
  • Total maintainers: 1
cran.r-project.org: sportyR

Plot Scaled 'ggplot' Representations of Sports Playing Surfaces

  • Versions: 8
  • Dependent Packages: 1
  • Dependent Repositories: 2
  • Downloads: 681 Last month
  • Docker Downloads: 41,971
Rankings
Docker downloads count: 0.6%
Stargazers count: 4.0%
Forks count: 8.0%
Average: 11.5%
Dependent packages count: 18.1%
Dependent repos count: 19.2%
Downloads: 19.2%
Maintainers (1)
Last synced: 6 months ago

Dependencies

DESCRIPTION cran
  • R >= 3.3 depends
  • dplyr * imports
  • ggplot2 * imports
  • glue * imports
  • rjson * imports
  • roxygen2 * suggests
  • testthat >= 3.0.0 suggests
  • vdiffr >= 0.3.3 suggests
.github/workflows/R-CMD-check.yaml actions
  • actions/checkout v2 composite
  • r-lib/actions/check-r-package v1 composite
  • r-lib/actions/setup-pandoc v1 composite
  • r-lib/actions/setup-r v1 composite
  • r-lib/actions/setup-r-dependencies v1 composite
.github/workflows/lint.yaml actions
  • actions/checkout v2 composite
  • r-lib/actions/setup-r v2 composite
  • r-lib/actions/setup-r-dependencies v2 composite
.github/workflows/pkgdown.yaml actions
  • JamesIves/github-pages-deploy-action 4.1.4 composite
  • actions/checkout v2 composite
  • r-lib/actions/setup-pandoc v2 composite
  • r-lib/actions/setup-r v2 composite
  • r-lib/actions/setup-r-dependencies v2 composite
.github/workflows/test-coverage.yaml actions
  • actions/checkout v2 composite
  • r-lib/actions/setup-r v2 composite
  • r-lib/actions/setup-r-dependencies v2 composite