Home

Awesome

<!-- README.md is generated from README.Rmd. Please edit that file -->

sportyR <img src="https://raw.githubusercontent.com/sportsdataverse/sportyR/main/logos/sportyr-logo-hex.png" align="right" width="120"/>

<!-- badges: start -->

CRAN
version CRAN
downloads Version-Number R-CMD-check codecov Lifecycle:maturing Twitter
Follow Twitter
Follow

<!-- badges: end -->

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.

Installation

The most recent release of sportyR is available on CRAN, and it can be installed directly via:

# Install released version from CRAN
install.packages("sportyR")

The development version of sportyR can be installed from GitHub with:

# Install development version from GitHub
devtools::install_github("sportsdataverse/sportyR")

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

# Required to use package
library(sportyR)

Plotting Functions

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

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:

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:

# Display only the red zone of the football field
geom_football("nfl", display_range = "red zone")
<img src="man/figures/README-readme-display-range-demo-1.png" width="100%" />

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:

# Display only the house on a curling sheet
geom_curling("wcf", display_range = "house")
<img src="man/figures/README-readme-display-range-curling-demo-1.png" width="100%" />

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):

SportLeaguePrimary Plotting Unit
BaseballLittle Leagueft
BaseballMiLBft
BaseballMLBft
BaseballNCAAft
BaseballNFHS (High School)ft
BaseballPonyft
BasketballFIBAm
BasketballNBAft
BasketballNBA G Leagueft
BasketballNCAAft
BasketballNFHSft
BasketballWNBAft
CurlingWCF (World Curling Federation)ft
FootballCFLyd
FootballNCAAyd
FootballNFHS11 (High School, 11 players)yd
FootballNFHS6 (High School, 6 players)yd
FootballNFHS8 (High School, 8 players)yd
FootballNFHS9 (High School, 9 players)yd
FootballNFLyd
HockeyAHLft
HockeyECHLft
HockeyIIHFm
HockeyNCAAft
HockeyNHLft
HockeyNWHLft
HockeyOHLft
HockeyPHFft
HockeyQMJHLft
HockeyUSHLft
LacrosseNCAAMyd
LacrosseNCAAWm
LacrosseNLLft
LacrossePLLyd
LacrosseUSA Men’syd
LacrosseUSA Women’sm
LacrosseWorld Lacrosseft
SoccerEPLm
SoccerFIFAm
SoccerMLSyd
SoccerNCAAyd
SoccerNWSLyd
TennisATPft
TennisITAft
TennisITFft
TennisNCAAft
TennisUSTAft
TennisWTAft
VolleyballFIVBm
VolleyballNCAAm
VolleyballUSA Volleyballm

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, 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:

# Draw a basic MLB infield plot
geom_baseball("mlb", display_range = "infield")
<img src="man/figures/README-readme-mlb-example-1.png" width="100%" />
# Create a 100m by 75m FIFA pitch
geom_soccer(
  "fifa",
  pitch_updates = list(
    pitch_length = 100,
    pitch_width = 75
  )
)
<img src="man/figures/README-readme-fifa-example-1.png" width="100%" />

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

# Draw half of a rotated NBA court
geom_basketball("nba", display_range = "offense", rotation = 270)
<img src="man/figures/README-readme-nhl-example-1.png" width="100%" />

License

This package is released under the GPL 3.0 License.

Contributions

League Office

The package maintainers and functional engineers

General Managers

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

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’s work on the hockey_rink package for Python.

sportyRtist

The sportyR logo was created by Lindsey Kelso. Check her out on Instagram or her online shop!