mlbgameday: Plotting Pitches

Kris Eberwein

2017-12-01

The package is primarily a data package, and has no native plotting tools. However, there are several plotting options available by leveraging one of the R language’s excellent plotting libraries.

Example Data

For all of the following examples, we will use The pitch data for Jake Arrieta’s no-hitter, which occurred on April 21, 2016.

library(mlbgameday)
library(dplyr)
## 
## Attaching package: 'dplyr'
## The following objects are masked from 'package:stats':
## 
##     filter, lag
## The following objects are masked from 'package:base':
## 
##     intersect, setdiff, setequal, union
# Grap some Gameday data. We're specifically looking for Jake Arrieta's no-hitter.
gamedat <- get_payload(start = "2016-04-21", end = "2016-04-21")
## Gathering Gameday data, please be patient...
## Warning: executing %dopar% sequentially: no parallel backend registered
# Subset that atbat table to only Arrieta's pitches and join it with the pitch table.
pitches <- inner_join(gamedat$pitch, gamedat$atbat, by = c("num", "url")) %>%
    subset(pitcher_name == "Jake Arrieta")

Ggplot2

The ggplot2 package can be used stand-alone, or in conjunction with Carson Silvert’s pitchRx package, which has additional visualization offerings that are based on ggplot2.

library(ggplot2)

# basic example
ggplot() +
    geom_point(data=pitches, aes(x=px, y=pz, shape=type, col=pitch_type)) +
    coord_equal() + geom_path(aes(x, y), data = mlbgameday::kzone)

Batting Stance

Using the same simple ggplot example, we can use facet_grid(. ~ stand) to segment the pitches thrown to right-handers from those thrown to left-handers.

# basic example with stand.
ggplot() +
    geom_point(data=pitches, aes(x=px, y=pz, shape=type, col=pitch_type)) +
    facet_grid(. ~ stand) + coord_equal() +
    geom_path(aes(x, y), data =  mlbgameday::kzone)

PitchRx and ggplot2

For this visualization, we will subset the data to only pitches that the umpire called a strike. This will give us location densities of all called strikes in that game with a view from the umpire’s prospective.

# Subset the data to only called strikes.
strikes <- subset(pitches, des.x == "Called Strike")

library(pitchRx)
## 
## Attaching package: 'pitchRx'
## The following object is masked _by_ '.GlobalEnv':
## 
##     pitches
library(viridis)
## Loading required package: viridisLite
pitchRx::strikeFX(pitches, geom = "tile") + 
    facet_grid(pitcher_name ~ stand) +
    coord_equal() +
    theme_bw() +
    scale_fill_viridis()
## Warning: Removed 14 rows containing non-finite values (stat_density2d).

Plotly

The plotly package is the “go-to” package for many who wish to create interactive visualizations or Shiny applications.

library(plotly)
## 
## Attaching package: 'plotly'
## The following object is masked from 'package:pitchRx':
## 
##     export
## The following object is masked from 'package:ggplot2':
## 
##     last_plot
## The following object is masked from 'package:stats':
## 
##     filter
## The following object is masked from 'package:graphics':
## 
##     layout
plot_ly(pitches, x = ~px, y = ~pz, mode = 'markers', 
        color = ~pitch_type, marker = list(size = 7, line = list(color = ~pitch_type, width = 1)),
        text = ~paste("Pitch Type: ", pitch_type)) %>% 
    layout(title = "Anatomy of a No-Hitter", xaxis = list(zeroline=F), yaxis = list(zeroline=F)) %>%
    # Draw a box for the strikezone. 
    layout(shapes = list(type = "rect", fillcolor = "blue", 
                         line = list(color = "blue"), opacity = 0.2,
                         x0 = -0.95, x1 = 0.95, xref = "x",
                         y0 = 3.5, y1 = 1.6, yref = "y"))
## No trace type specified:
##   Based on info supplied, a 'scatter' trace seems appropriate.
##   Read more about this trace type -> https://plot.ly/r/reference/#scatter