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.0.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.0-py3-none-any.whl (8.5 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: baseball_field_viz-0.2.0.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.0.tar.gz
Algorithm Hash digest
SHA256 87f46517dd2cb703b523d789f179ad37301ea9617a96bedccf289787f955b458
MD5 6dad3a7d2ea64631f5c0af297b8654da
BLAKE2b-256 f33be31d0155c487e96f02773a83c429bb4427372daef57056f749aaa815f8f0

See more details on using hashes here.

Provenance

The following attestation bundles were made for baseball_field_viz-0.2.0.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.0-py3-none-any.whl.

File metadata

File hashes

Hashes for baseball_field_viz-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 e0a6b111c80aa34a48e828d181030f56e558728fba5a5663bfb13caaa2fc57f4
MD5 37e9b6c5529d3e38da110154856a2155
BLAKE2b-256 b04ad6882d78057ccdb54b6f4ec685d5f0506ddf5d3b0e65b3605a2626b58f90

See more details on using hashes here.

Provenance

The following attestation bundles were made for baseball_field_viz-0.2.0-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