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.3.tar.gz (8.5 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.3-py3-none-any.whl (8.7 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: baseball_field_viz-0.2.3.tar.gz
  • Upload date:
  • Size: 8.5 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.3.tar.gz
Algorithm Hash digest
SHA256 a093c24ec85f707d9e52d79592e2fe4b015837f93cab331018ab62519efa0784
MD5 dd3b0052158977384f6e92609b4869bc
BLAKE2b-256 20355e901a9654692681817520169d7d14350c469aefc4b40d639b3a342ddafa

See more details on using hashes here.

Provenance

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

File metadata

File hashes

Hashes for baseball_field_viz-0.2.3-py3-none-any.whl
Algorithm Hash digest
SHA256 17b5f27bc9ce17d8b086386496c69570aa0e070ca4ac9faa12a0ea0513982ed9
MD5 32c049dbf015cbd6496a9e18c8878138
BLAKE2b-256 b7a97a5e25fb7ef0b59f44099dcd3ee289cce521f1e09416a3555cffac6738eb

See more details on using hashes here.

Provenance

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