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

Uploaded Python 3

File details

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

File metadata

  • Download URL: baseball_field_viz-0.2.2.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.2.tar.gz
Algorithm Hash digest
SHA256 440af3d0d9b8ffcefddf4d362b52630845634135fa704fe37ed522c5d21ba8d2
MD5 be53b9250298f0acebcf34b96b145703
BLAKE2b-256 4eb80f45f118fa3f94579b83d2feb3444736a84382253e1c764cd1ff791e16d2

See more details on using hashes here.

Provenance

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

File metadata

File hashes

Hashes for baseball_field_viz-0.2.2-py3-none-any.whl
Algorithm Hash digest
SHA256 ff98cdddc30cc36593057e009f451ea292533f32755a1fd50e5a9e13cf4b88b8
MD5 aa450cc04f7bb82a2e3ee830f5573253
BLAKE2b-256 ec5526e8a2a22346b453e195cd70716788640ffc6357dabc2bae3f19e41dbea6

See more details on using hashes here.

Provenance

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