
Measuring how much pass quality predicts attack success in MLV
Don't know how many volleyball fans are in this sub, but I wanted to share an analysis I've been working on!
The question: in Major League Volleyball (MLV, or formerly PVF), given the quality of the preceding pass, how often does the attacking team actually get to attack, and how often does that attack end in a kill?
The data and the pipeline: the raw play-by-play data (via the pyvolleydata package) is action+outcome graded (VolleyStation notation, single letter codes for contact types and single symbol codes for contact evaluations). Reconstructing each contact sequence within each rally seemed easy; just track each contact and forward-fill each pass grade (within each rally) until the next pass or until the point ends, right? But it also required accounting for overpass kills (which don't have a preceding pass) and block recycles, where the ball stays alive off a block touch.
That last part ended up being quite the quirk of the data: for block recycles, the pass involved is rarely tagged in the data; it's just implicitly included in the block touch tag. This made tracking the passes off of blocks quite the annoying task (because how the hell do you validate your logic on something that doesn't explicitly exist in the data?). So my solution was to only track the blocks where the next touch was from the attacking team, not the blocking team - if the next touch after the block was from the attacking team, then there inherently was a block recycle pass.
However, one fact that made this worth mentioning was that, based on the quality grade of the block touch, the ball would go back to the attacking team at varying rates:
- Actual block recycle grade (!): ~99.8% of the time, the attacking team gets the next touch (this is the only grade that VolleyStation's public criteria says block recycles exist)
- Hard-contact grade (+): ~99% of the time, it's the blocking team's recovery (assumed to be hard contact; VolleyStation doesn't have public criteria for this grade)
- Soft-contact grade (-): split almost evenly, ~50% of the time is goes back to the attacking team, and vice versa
This made reporting our first number (probability of an attack happening, given the pass quality) unreliable for the hard and soft contact block grades based on my attacking team conditional logic: the denominator wouldn't end up being "block recycle passes that go to attacking team", it would be "general blocks that may go to the defending team". As such, I only calculated the attack rate for the confirmed block-recycle grade, and did the kill rate (which is calculated from passes that attacks happen) for all three.
The results (full tables in my writeup):
- Bad serve receives still get attacked ~92% of the time; bad digs only convert to an attack ~73% of the time - implying that the "transition between defense to offense" has a quantifiable penalty on setters/attackers in the face of bad passes.
- Kill rate spread from perfect -> bad pass: 18 points for serve receive (45.9% -> 27.9%), narrower and generally lower for digs (29.9% -> 22.5%).
- Confirmed the trend is statistically monotonic (not just "different") with a Cochran-Armitage test per pass type. Showed the trend is strongest for receives, weakest for freeballs.
Limitations: Obviously, MLV is a relatively new and small league; the data points across three seasons are magnitudes smaller than something like NCAA data. Additionally, I found and removed 9 rows of data corrupted by mid-rally stoppages (injuries or challenges, which messed with the logic of my pipeline), all video-confirmed (but I can't rule out similar issues elsewhere that I didn't detect).
Full writeup with more tables on Medium (or Substack if medium tries to paywall you)
Open to any and all feedback in the comments! Let me know if anything doesn't make sense and I'll do my best to explain everything!