By metric
The same pick-one-see-what-it-does reference By set piece gives set pieces and By value model gives value models, for the base metrics layer – counts, delivery locations, shot/goal linking, the all-in-one summary, and pitch zones.
Team and player counts
- What it returns
Attempts, successful attempts, and a success rate per
(team, set_piece_type)or(player, set_piece_type). “Success” follows Opta’s ownoutcomeflag on the restart event as reported by the provider – this package doesn’t re-derive success from subsequent possession. Don’t confuse this withdelivery_outcome(see By phase and outcome), a separately classified result column.- Requirements
Just an events frame – works on any set-piece type, no model needed.
Compute it
from wa_setpieces import team_set_piece_counts, player_set_piece_counts
team_set_piece_counts(events)
player_set_piece_counts(events)
- Where it’s used
The team-count rows feed
set_piece_summary()below; both are the base of every per-category breakdown in By set piece.
Delivery locations
- What it returns
Start/end pitch coordinates for one pass-based set-piece type –
eventId,contestantId,playerId,playerName,x,y,end_x,end_y,outcome. What a delivery map or heatmap is built from.- Requirements
A pass-based type:
corner,free_kick,throw_in,goal_kickorkick_off– notpenalty(a shot, no delivery coordinates; see By routine’s penalty-placement entry instead).
Compute it
from wa_setpieces import delivery_locations
corners = delivery_locations(events, "corner")
- Where it’s used
plot_delivery_map()and every other pitch plot in the Gallery; the zone functions below.
Linking to shots and goals
- What it returns
Every shot (including goals) traced back to the set piece that created it, via Opta’s own assist-chain qualifier – not a positional guess.
- Requirements
Just an events frame.
Compute it
from wa_setpieces import link_set_piece_shots, set_piece_goal_summary
link_set_piece_shots(events) # every shot, tagged with its originating set piece
set_piece_goal_summary(events) # goals per team per set-piece type
Important
The feed’s eventId is only unique within one team’s own event stream –
both teams number their events 1, 2, 3, … independently. This
function scopes its lookup to a team first; an unscoped
events[events["eventId"] == x] on the raw feed is not safe.
- Where it’s used
set_piece_added_value()(By value model) resolves “did this delivery produce a shot” the same way.
The all-in-one summary
- What it returns
One headline table: attempts, success rate, shots and goals, per team, for every set-piece type at once – usually the first call on a new match.
- Requirements
Just an events frame.
Compute it
from wa_setpieces import set_piece_summary
set_piece_summary(events)
- Where it’s used
The Quickstart’s first real call;
wa-setpieces match.jsonon the command line runs this directly.
Zones, thirds and channels
- What it returns
Pitch-location labels added to any frame with
x/ycolumns: thirds (defensive/middle/attacking), channels (wide/half-space/central, or a coarser left/central/right), an 18-cell zone grid, and heatmap-ready per-zone counts.- Requirements
Any frame with
x/y(orend_x/end_y, via thex_col/y_colargs) – raw events ordelivery_locations()output both work.
Compute it
from wa_setpieces import add_thirds, add_channels, add_zone_grid, zone_counts, delivery_locations
tagged = add_thirds(events) # "defensive_third" / "middle_third" / "attacking_third"
tagged = add_channels(tagged, n=5) # wide / half-space / central
tagged = add_zone_grid(tagged) # 6x3 = 18-zone grid label, e.g. "R1C4"
zone_counts(events, group_cols=["contestantId"]) # per-zone counts per team
corners = add_channels(delivery_locations(events, "corner"), y_col="end_y", n=5)
corners["channel"].value_counts() # which channel corners are delivered *into*
- Where it’s used
plot_zone_heatmap()in the Gallery; the free-kick/corner origin-zone features in By routine.