Skip to content

agv117/nba

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Court Vision — NBA Shot Charts & Statistical Twins

Live: https://anandvaghasia.com/nba/

An interactive NBA analytics desk holding two tools behind one UI:

  1. Shot Chart Explorer — pick any scorer and see a hex-binned, league-relative shot chart: hex size is shot frequency, hex color is points-per-shot versus the league average from that exact spot that season (warm beats the league, cool trails it). Compare two players side by side. Each player gets a scouting blurb whose every number is drawn from the baked stats, plus rim / mid / three efficiency bars against league marks.
  2. Statistical Twins — every player-season is a point in a 13-dimensional, standardized box-score space; the nearest points are the twins, and they cross eras freely. Cross-era matches are flagged.

Project 03 in a series of interactive sports-analytics builds (sibling to the NFL 4th-Down Decision Model).

Architecture (zero live cost for visitors)

  • pipeline/build.py — pulls shots (shotchartdetail) and per-100 box stats (leaguedashplayerstats) LOCALLY via nba_api (stats.nba.com blocks cloud IPs). It bins shots into hexagons, colors each hex by the player's points-per-shot minus the league's from the same zone (the zone league averages ride along in the same API response), standardizes 13 features and builds the nearest-neighbor similarity matrix, assigns a rule-based archetype, and writes a deterministic scouting paragraph. Bakes:
    • web/data/players.json — slim per-season meta, per-100 line, zone summary, top-8 twins, scouting
    • web/data/shots/<id>-<season>.json — the hexbins for one player-season
  • web/ — a static page (no framework, no build step). It draws the halfcourt and hexbins on <canvas>, does every lookup client-side, and lazy-loads a player's shot file only when picked. The scroll-swish hero is a scroll-scrubbed canvas animation (prefers-reduced-motion → static frame).
  • deploy.py — FTPS mirror of web/ into the /nba/ slug only (asserts the slug is the working directory before any upload; never touches other slugs).
  • pipeline/verify.mjs — headless-Chrome CDP check of the live page.

Honesty

  • Shot value is league-relative and location-based; it rewards taking and making high-value shots and says nothing about defense.
  • Similarity is box-score only — no defense, spacing, role, or shot creation context, and short seasons are noisier.
  • The pool is the league's top scorers across eight seasons (2009-10 → 2024-25), so a "twin" is the closest match inside this set.
  • No made-up numbers: scouting text is generated from the baked stats, so every figure it cites is exact.

Rebuild

cd nba
python3 -m venv .venv && .venv/bin/pip install nba_api pandas numpy
.venv/bin/python pipeline/build.py      # local NBA pull -> bakes web/data
python3 deploy.py                        # FTPS -> anandvaghasia.com/nba/
node pipeline/verify.mjs                  # headless verify of the live page

Built end to end with Claude Code — pipeline, hexbin + similarity math, and the interface. Data: nba_api / stats.nba.com (no scraping of Sports-Reference).

— Anand G. Vaghasia · 2026 · Powered by NetRyse

About

Court Vision: interactive NBA shot charts (league-relative hexbins) + statistical twins. Built with Claude Code.

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages