Skip to main content

Matplotlib baseball field drawing and Statcast spray chart for MLB analysis

Project description

baseball-field-viz

A Python library for drawing baseball fields and spray charts from Statcast data.

Companion to savant-extras — together they provide a seamless MLB analysis pipeline.

Installation

pip install baseball-field-viz

Why this library?

pybaseball's built-in spraychart() doesn't support overlaying heatmaps (e.g. seaborn kdeplot). This library gives you a matplotlib Axes object directly, so you can layer any plot on top.

from baseball_field_viz import draw_field
import seaborn as sns

fig, ax = plt.subplots(figsize=(10, 10))
draw_field(ax)
sns.kdeplot(data=df_t, x="x", y="y", ax=ax, cmap="Reds", fill=True, alpha=0.6)

Quick Start

import matplotlib.pyplot as plt
from baseball_field_viz import draw_field, spraychart, transform_coords

# Spray chart (one-liner)
fig, ax = plt.subplots(figsize=(10, 10))
spraychart(ax, df, color_by="events", title="Ohtani 2025 - Batted Balls")
plt.show()

Functions

transform_coords(df)

Convert Statcast hc_x/hc_y to feet coordinates (home plate at origin).

from baseball_field_viz import transform_coords

df_t = transform_coords(df)
# Adds 'x' and 'y' columns in feet
# x = 2.5 * (hc_x - 125.42)
# y = 2.5 * (198.27 - hc_y)

draw_field(ax, foul_distance=330, outfield_distance=340)

Draw a baseball field on a matplotlib Axes.

from baseball_field_viz import draw_field

fig, ax = plt.subplots(figsize=(10, 10))
draw_field(ax)
# Now overlay any plot: scatter, kdeplot, histplot, etc.

spraychart(ax, df, color_by="events", title=None)

Draw a spray chart in one call. Internally calls transform_coords and draw_field.

from baseball_field_viz import spraychart

fig, ax = plt.subplots(figsize=(10, 10))
spraychart(ax, df, color_by="events", title="Player - Season")
plt.show()

color_by options:

Value Effect
"events" (default) home_run=red, triple=orange, double=blue, single=green, other=gray
Any column name Categorical coloring with auto palette

Full Example with Heatmap

from pybaseball import statcast
import duckdb
import matplotlib.pyplot as plt
import seaborn as sns
from baseball_field_viz import draw_field, transform_coords

# Fetch data
df_raw = statcast(start_dt="2025-03-01", end_dt="2025-10-31")
con = duckdb.connect()
df = con.execute("""
    SELECT * FROM df_raw
    WHERE batter = 660271
      AND hc_x IS NOT NULL AND hc_y IS NOT NULL
      AND game_type = 'R'
""").df()

df_t = transform_coords(df)

# Hits vs outs heatmap
fig, axs = plt.subplots(1, 2, figsize=(16, 8))

hits = df_t[df_t["events"].isin(["home_run", "double", "triple", "single"])]
outs = df_t[~df_t["events"].isin(["home_run", "double", "triple", "single"])]

draw_field(axs[0])
sns.kdeplot(data=hits, x="x", y="y", ax=axs[0], cmap="Reds", fill=True, alpha=0.6)
axs[0].set_xlim(-350, 350); axs[0].set_ylim(-50, 400)
axs[0].set_title("Hits Heatmap")

draw_field(axs[1])
sns.kdeplot(data=outs, x="x", y="y", ax=axs[1], cmap="Blues", fill=True, alpha=0.6)
axs[1].set_xlim(-350, 350); axs[1].set_ylim(-50, 400)
axs[1].set_title("Outs Heatmap")

plt.tight_layout()
plt.show()

Strike Zone (v0.2.0)

draw_strike_zone(ax, sz_top=3.5, sz_bot=1.5, color="black", lw=2)

Draw a strike zone rectangle on a matplotlib Axes (plate_x / plate_z coordinate system).

from baseball_field_viz import draw_strike_zone

fig, ax = plt.subplots(figsize=(6, 6))
draw_strike_zone(ax, sz_top=3.5, sz_bot=1.5)

pitch_zone_chart(ax, df, color_by="pitch_type", sz_top=None, sz_bot=None, title=None)

Plot pitch locations with strike zone overlay. Uses plate_x / plate_z columns (Statcast standard). If sz_top/sz_bot are not provided, the mean of df["sz_top"]/df["sz_bot"] is used automatically.

from pybaseball import statcast
from baseball_field_viz import pitch_zone_chart

df = statcast(start_dt="2025-03-01", end_dt="2025-10-31")
df_pitcher = df[df["pitcher"] == 592789]  # e.g. Yoshinobu Yamamoto

fig, ax = plt.subplots(figsize=(6, 6))
pitch_zone_chart(ax, df_pitcher, color_by="pitch_type", title="Yamamoto 2025 - Pitch Locations")
plt.show()

The strike zone is automatically sized from per-pitch Hawk-Eye measurements (sz_top/sz_bot) in the Statcast data, reflecting each batter's actual stance.

Requirements

  • Python 3.9+
  • matplotlib >= 3.5
  • numpy >= 1.21
  • pandas >= 1.3

Related

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

baseball_field_viz-0.2.4.tar.gz (8.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

baseball_field_viz-0.2.4-py3-none-any.whl (8.4 kB view details)

Uploaded Python 3

File details

Details for the file baseball_field_viz-0.2.4.tar.gz.

File metadata

  • Download URL: baseball_field_viz-0.2.4.tar.gz
  • Upload date:
  • Size: 8.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for baseball_field_viz-0.2.4.tar.gz
Algorithm Hash digest
SHA256 9304803f14b4447215a9b1937243169e8c4c5846058da9f8f4e4043a9364d48e
MD5 b7963383a2b39de0591338a443078bb8
BLAKE2b-256 a9ee85bbea41ef8e2d0eb8daf4ddffe5e4a9ab22823110c0422b38800c841b62

See more details on using hashes here.

Provenance

The following attestation bundles were made for baseball_field_viz-0.2.4.tar.gz:

Publisher: publish.yml on yasumorishima/baseball-field-viz

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file baseball_field_viz-0.2.4-py3-none-any.whl.

File metadata

File hashes

Hashes for baseball_field_viz-0.2.4-py3-none-any.whl
Algorithm Hash digest
SHA256 52c80d3e7c6c2ca1e967011a12a9ba39f5b091aeb299d5911c7f0e8f1a6dbd38
MD5 d2da5c1af6a3d16a1ce4c87cd3e0779b
BLAKE2b-256 1e5c1c1de5c43ea7450b7f52a4773cfa63bdfde146510e849ef9c815c928ee55

See more details on using hashes here.

Provenance

The following attestation bundles were made for baseball_field_viz-0.2.4-py3-none-any.whl:

Publisher: publish.yml on yasumorishima/baseball-field-viz

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page