Skip to main content
Version: 0.1.5

NFL — additional Python functions — Models and calculators: calculate_wpa

calculate_wpa​

calculate_wpa(df: 'pl.DataFrame') -> 'pl.DataFrame'

Derive win probability added (WPA) from pre-scored WP point estimates.

This is the derivation half of NFLPlayProcess.__process_wpa lifted into a shared, model-free function so the same nflfastR-faithful WPA logic can be reused by the streaming enrich_nfl_pbp pipeline and by process_wpa itself. It performs **no** model inference — the caller must already have scored the per-play WP point estimates (wp_spread.ubj) for the start / touchback / end feature views and attached them as wp_before/wp_touchback/wp_after. This mirrors calculate_epa`, which likewise consumes pre-scored EP point estimates and leaves prediction to the orchestrator.

Derivation rules (mirror the original process_wpa`):

  • Leading overlay (do not drop): on a kickoff (type.text in kickoff_vec) wp_before is replaced by wp_touchback — the win-probability scored from the touchback feature view — before any other column derives. This is the WP analogue of the EPA 0.92 scoring-attempt overlay and must fire first.
  • Try rows: a standalone try row (Extra Point Good, Two Point Pass, Defensive 2pt Conversion, ...) takes the wp_after of the touchdown before it (the last play that is not a clock stoppage) as its wp_before when the try is the touchdown's end team's, so the touchdown hands over to the try. A clock stoppage just before the try inherits too, restated for the team ESPN credits it to, and the try still hands over from the touchdown. The model cannot score the try's own start state (ESPN's down-0 placeholder). A return or defensive touchdown (a scoringPlay whose end team is the scorer, not its start team) hands over only a wp_after scored for the scorer, as NFLPlayProcess scores it.
  • def_wp_before = 1 - wp_before; home_wp_before / away_wp_before are the posteam->home perspective columns (the offense's wp_before flows to home when the start possession team is the home team, otherwise to the defense def_wp_before).
  • wp_after is rewritten by the end-of-half / end-of-game / OT two-path: timeouts hold wp_before; a completed final play resolves to 1.0 / 0.0 by the winner; end-of-half and End Period / End of Half lead plays take lead_wp_before (or 1 - lead_wp_before on a possession change); a possession change otherwise flips the lead; everything else keeps the model wp_after.
  • def_wp_after = 1 - wp_after; home_wp_after / away_wp_after use the end possession team for the perspective flip.
  • wpa = wp_after - wp_before.

Every shift / forward reference is grouped .over("game_id") so a concatenated multi-game frame never leaks WP across game boundaries — the lead_wp_before / lead_wp_before2 shifts and the end-of-game game_play_number == max() lookup are all per-game. This differs from process_wpa` (which runs one game per instance and therefore needs no grouping).

Parameters

ParameterTypeDefaultDescription
dfDataFramePlay-by-play DataFrame that already carries the WP point estimates wp_before (start feature view), wp_touchback (touchback feature view) and wp_after (end feature view), plus the play-classification / perspective columns game_id, type.text, homeTeamId, start.pos_team.id, end.pos_team.id, start.pos_team_receives_2H_kickoff, change_of_pos_team, scoringPlay, kickoff_onside, end_of_half, status_type_completed, pos_score_diff_end, lead_play_type, lead_pos_team and game_play_number. See WPA_REQUIRED_COLUMNS. This function does **not** score WP itself — score it first via calculate_win_probability/ thewp_spread` feature pipeline.

Returns

The input frame with the WPA derivation applied: wp_before rewritten by the kickoff-touchback overlay; def_wp_before, home_wp_before, away_wp_before, lead_wp_before, lead_wp_before2, the rewritten wp_after, def_wp_after, home_wp_after, away_wp_after and wpa added; plus first-class lowercase aliases wp (= wp_before), def_wp (= def_wp_before), home_wp (= home_wp_before) and away_wp (= away_wp_before) for downstream contract parity (the per-play offense win probability is the pre-snap wp_before, matching nflfastR's wp semantics).

col_nametypedescription
game_play_numberinteger
idintegerID of the player in the 'name' column.
sequenceNumberinteger
textcharacter
awayScoreinteger
homeScoreinteger
scoringPlaylogicalESPN flag marking the play as a scoring play.
prioritylogical
modifiedcharacter
wallclockcharacter
teamParticipantsintegerRaw ESPN team-level participants payload carried through from the plays feed (stringified).
isPenaltylogicalESPN's per-play flag that a penalty occurred on the play.
statYardageintegerYardage ESPN credits to the play for statistical purposes.
isTurnoverlogicalESPN's per-play turnover flag as shipped in the plays feed (broader than the giveaway-based is_turnover derivation).
type.idcharacterESPN's numeric identifier for the play type.
type.textcharacterESPN's text label for the play type.
period.numberintegerPeriod (quarter) number in which the play occurred.
clock.displayValuecharacterGame clock at the play, as the displayed mm:ss string.
start.downintegerESPN's down value for the play state at the start of the play.
start.distanceintegerESPN's distance value for the play state at the start of the play.
start.yardLineintegerESPN's yardLine value for the play state at the start of the play.
start.yardsToEndzoneintegerESPN's yardsToEndzone value for the play state at the start of the play.
start.team.idintegerESPN's team.id value for the play state at the start of the play.
end.downintegerESPN's down value for the play state at the end of the play.
end.distanceintegerESPN's distance value for the play state at the end of the play.
end.yardLineintegerESPN's yardLine value for the play state at the end of the play.
end.yardsToEndzoneintegerESPN's yardsToEndzone value for the play state at the end of the play.
end.team.idintegerESPN's team.id value for the play state at the end of the play.
type.abbreviationcharacterESPN's abbreviation for the play type.
start.downDistanceTextcharacterESPN's downDistanceText value for the play state at the start of the play.
start.shortDownDistanceTextcharacterESPN's shortDownDistanceText value for the play state at the start of the play.
start.possessionTextcharacterESPN's possessionText value for the play state at the start of the play.
end.downDistanceTextcharacterESPN's downDistanceText value for the play state at the end of the play.
end.shortDownDistanceTextcharacterESPN's shortDownDistanceText value for the play state at the end of the play.
end.possessionTextcharacterESPN's possessionText value for the play state at the end of the play.
scoringType.namecharacterESPN's name for the scoring type (e.g. touchdown, field goal).
scoringType.displayNamecharacterESPN's display label for the scoring type.
scoringType.abbreviationcharacterESPN's abbreviation for the scoring type.
pointAfterAttempt.iddoubleESPN identifier for the point-after attempt type on the scoring play.
pointAfterAttempt.textcharacterESPN description of the point-after attempt and its result.
pointAfterAttempt.abbreviationcharacterESPN abbreviation of the point-after attempt type; drives the extra-point / two-point result derivation.
pointAfterAttempt.valuedoublePoints ESPN credits for the point-after attempt (1.0 made extra point, 2.0 made two-point try).
drive.idcharacterESPN's id field for the drive containing this play.
drive.displayResultcharacterESPN's displayResult field for the drive containing this play.
drive.isScorelogicalESPN's isScore field for the drive containing this play.
drive.team.shortDisplayNamecharacterESPN's team.shortDisplayName field for the drive containing this play.
drive.team.displayNamecharacterESPN's team.displayName field for the drive containing this play.
drive.team.namecharacterESPN's team.name field for the drive containing this play.
drive.team.abbreviationcharacterESPN's team.abbreviation field for the drive containing this play.
drive.yardsintegerESPN's yards field for the drive containing this play.
drive.offensivePlaysintegerESPN's offensivePlays field for the drive containing this play.
drive.resultcharacterESPN's result field for the drive containing this play.
drive.descriptioncharacterESPN's description field for the drive containing this play.
drive.shortDisplayResultcharacterESPN's shortDisplayResult field for the drive containing this play.
drive.timeElapsed.displayValuecharacterESPN's timeElapsed.displayValue field for the drive containing this play.
drive.start.period.numberintegerESPN's start.period.number field for the drive containing this play.
drive.start.period.typecharacterESPN's start.period.type field for the drive containing this play.
drive.start.yardLineintegerESPN's start.yardLine field for the drive containing this play.
drive.start.clock.displayValuecharacterESPN's start.clock.displayValue field for the drive containing this play.
drive.start.textcharacterESPN's start.text field for the drive containing this play.
drive.end.period.numberintegerESPN's end.period.number field for the drive containing this play.
drive.end.period.typecharacterESPN's end.period.type field for the drive containing this play.
drive.end.yardLineintegerESPN's end.yardLine field for the drive containing this play.
drive.end.clock.displayValuecharacterESPN's end.clock.displayValue field for the drive containing this play.
game_idintegerTen digit identifier for NFL game.
seasoninteger4 digit number indicating to which season(s) the specified timeframe belongs to.
seasonTypeintegerESPN season type for the game (2 = regular season, 3 = postseason).
weekintegerSeason week.
status_type_completedlogical
homeTeamIdintegerESPN's home-team Id for the game, stamped on every play.
awayTeamIdintegerESPN's away-team Id for the game, stamped on every play.
homeTeamNamecharacterESPN's home-team Name for the game, stamped on every play.
awayTeamNamecharacterESPN's away-team Name for the game, stamped on every play.
homeTeamMascotcharacterESPN's home-team Mascot for the game, stamped on every play.
awayTeamMascotcharacterESPN's away-team Mascot for the game, stamped on every play.
homeTeamAbbrevcharacterESPN's home-team Abbrev for the game, stamped on every play.
awayTeamAbbrevcharacterESPN's away-team Abbrev for the game, stamped on every play.
homeTeamNameAltcharacterESPN's home-team NameAlt for the game, stamped on every play.
awayTeamNameAltcharacterESPN's away-team NameAlt for the game, stamped on every play.
gameSpreaddoublePoint spread used as an input to the win-probability model.
homeFavoritelogicalTrue when the home team was favoured by the spread.
gameSpreadAvailablelogicalTrue when a spread was available for the game.
overUnderdoubleOver/under total used as a model input.
roofcharacterOne of 'dome', 'outdoors', 'closed', 'open' indicating indicating the roof status of the stadium the game was played in. (Source: Pro-Football-Reference)
homeTeamSpreaddoubleESPN's home-team Spread for the game, stamped on every play.
clock.minutesintegerMinutes remaining on the game clock at the play.
clock.secondsintegerSeconds component of the game clock at the play.
halfinteger
lag_halfintegerValue of half on the previous play, used for sequence-aware derivations.
lead_halfintegerValue of half on the next play, used for sequence-aware derivations.
start.TimeSecsRemintegerSeconds remaining in the half from ESPN's clock stamp for this play, which is the end-of-play time in 2005 and 2007+ (the snap time in 2004 and most of 2006); tops out at 1800.
start.adj_TimeSecsRemintegerESPN's adj_TimeSecsRem value for the play state at the start of the play.
orig_play_typecharacter
lead_textcharacterValue of text on the next play, used for sequence-aware derivations.
lead_start_teamcharacterValue of start_team on the next play, used for sequence-aware derivations.
lead_start_yardsToEndzoneintegerValue of start_yardsToEndzone on the next play, used for sequence-aware derivations.
lead_start_downintegerValue of start_down on the next play, used for sequence-aware derivations.
lead_start_distanceintegerValue of start_distance on the next play, used for sequence-aware derivations.
lead_scoringPlaylogicalValue of scoringPlay on the next play, used for sequence-aware derivations.
text_dupelogicalAlways False in the emitted frame -- the duplicate-row filter it gates runs before the column is returned, so it marks nothing and is retained only for schema stability.
start.pos_team.idintegerESPN's pos_team.id value for the play state at the start of the play.
start.def_pos_team.idintegerESPN's def_pos_team.id value for the play state at the start of the play.
end.def_pos_team.idintegerESPN's def_pos_team.id value for the play state at the end of the play.
end.pos_team.idintegerESPN's pos_team.id value for the play state at the end of the play.
start.pos_team.namecharacterESPN's pos_team.name value for the play state at the start of the play.
start.def_pos_team.namecharacterESPN's def_pos_team.name value for the play state at the start of the play.
end.pos_team.namecharacterESPN's pos_team.name value for the play state at the end of the play.
end.def_pos_team.namecharacterESPN's def_pos_team.name value for the play state at the end of the play.
start.is_homelogicalESPN's is_home value for the play state at the start of the play.
end.is_homelogicalESPN's is_home value for the play state at the end of the play.
homeTimeoutCalledlogicalTrue when the home team called a timeout on the play.
awayTimeoutCalledlogicalTrue when the away team called a timeout on the play.
end.homeTeamTimeoutsintegerESPN's homeTeamTimeouts value for the play state at the end of the play.
end.awayTeamTimeoutsintegerESPN's awayTeamTimeouts value for the play state at the end of the play.
start.homeTeamTimeoutsintegerESPN's homeTeamTimeouts value for the play state at the start of the play.
start.awayTeamTimeoutsintegerESPN's awayTeamTimeouts value for the play state at the start of the play.
end.TimeSecsRemintegerSeconds remaining in the half carried as this play's end state; currently the preceding row's clock stamp.
end.adj_TimeSecsRemintegerESPN's adj_TimeSecsRem value for the play state at the end of the play.
start.posTeamTimeoutsintegerESPN's posTeamTimeouts value for the play state at the start of the play.
start.defPosTeamTimeoutsintegerESPN's defPosTeamTimeouts value for the play state at the start of the play.
end.posTeamTimeoutsintegerESPN's posTeamTimeouts value for the play state at the end of the play.
end.defPosTeamTimeoutsintegerESPN's defPosTeamTimeouts value for the play state at the end of the play.
firstHalfKickoffTeamIdintegerESPN id of the team that received the opening kickoff.
periodinteger
start.yardintegerESPN's yard value for the play state at the start of the play.
end.yardintegerESPN's yard value for the play state at the end of the play.
lag_scoringPlaylogicalValue of scoringPlay on the previous play, used for sequence-aware derivations.
end_of_halflogical
down_1logicalTrue when it is 1st down at the start of the play.
down_2logicalTrue when it is 2nd down at the start of the play.
down_3logicalTrue when it is 3rd down at the start of the play.
down_4logicalTrue when it is 4th down at the start of the play.
down_1_endlogicalTrue when it is 1st down at the end of the play.
down_2_endlogicalTrue when it is 2nd down at the end of the play.
down_3_endlogicalTrue when it is 3rd down at the end of the play.
down_4_endlogicalTrue when it is 4th down at the end of the play.
scoring_playlogical
td_playlogical
touchdownlogicalBinary indicator for if the play resulted in a TD.
td_checklogicalInternal flag used while reconciling whether the play produced a touchdown.
safetylogicalBinary indicator for whether or not a safety occurred.
fumble_veclogical
forced_fumblelogicalTrue when the defense forced a fumble on the play.
kickoff_playlogical
kickoff_tblogical
kickoff_onsidelogical
kickoff_ooblogical
kickoff_fair_catchlogicalBinary indicator for if the kickoff was caught with a fair catch.
kickoff_downedlogicalBinary indicator for if the kickoff was downed.
kick_playlogical
kickoff_safetylogical
puntlogical
punt_playlogical
punt_tblogical
punt_ooblogical
punt_fair_catchlogicalBinary indicator for if the punt was caught with a fair catch.
punt_downedlogicalBinary indicator for if the punt was downed.
punt_safetylogical
punt_blockedlogicalBinary indicator for if the punt was blocked.
penalty_safetylogical
rushlogicalBinary indicator if the play was a rushing play.
passlogicalBinary indicator if the play was a pass play (sacks and scrambles included).
sack_veclogical
pos_teaminteger
def_pos_teaminteger
is_homelogical
lag_HA_score_diffintegerValue of HA_score_diff on the previous play, used for sequence-aware derivations.
HA_score_diffintegerHome score minus away score for the play.
net_HA_score_ptsintegerNet points the play added to the home-minus-away score margin.
H_score_diffintegerHome team's score minus the away team's, from the home perspective.
A_score_diffintegerAway team's score minus the home team's, from the away perspective.
lag_homeScoreintegerValue of homeScore on the previous play, used for sequence-aware derivations.
lag_awayScoreintegerValue of awayScore on the previous play, used for sequence-aware derivations.
start.homeScoreintegerESPN's homeScore value for the play state at the start of the play.
start.awayScoreintegerESPN's awayScore value for the play state at the start of the play.
end.homeScoreintegerESPN's homeScore value for the play state at the end of the play.
end.awayScoreintegerESPN's awayScore value for the play state at the end of the play.
pos_team_scoreinteger
def_pos_team_scoreinteger
start.pos_team_scoreintegerESPN's pos_team_score value for the play state at the start of the play.
start.def_pos_team_scoreintegerESPN's def_pos_team_score value for the play state at the start of the play.
start.pos_score_diffintegerESPN's pos_score_diff value for the play state at the start of the play.
end.pos_team_scoreintegerESPN's pos_team_score value for the play state at the end of the play.
end.def_pos_team_scoreintegerESPN's def_pos_team_score value for the play state at the end of the play.
end.pos_score_diffintegerESPN's pos_score_diff value for the play state at the end of the play.
lag_pos_teaminteger
lead_pos_teaminteger
lead_pos_team2integerValue of pos_team 2 plays ahead, used for sequence-aware derivations.
pos_score_diffinteger
lag_pos_score_diffinteger
pos_score_ptsinteger
pos_score_diff_startinteger
start.pos_team_receives_2H_kickofflogicalESPN's pos_team_receives_2H_kickoff value for the play state at the start of the play.
end.pos_team_receives_2H_kickofflogicalESPN's pos_team_receives_2H_kickoff value for the play state at the end of the play.
change_of_posslogical
penalty_flaglogical
penalty_declinedlogical
penalty_no_playlogical
penalty_offsetlogical
penalty_1st_convlogical
penalty_in_textlogicalTrue when the play description mentions a penalty.
penalty_detailcharacter
penalty_textcharacter
yds_penaltycharacter
penalty_countintegerNumber of penalties flagged on the play (0-4 observed).
penalty_declined_countintegerNumber of the flagged penalties that were declined.
penalty_all_declinedlogicalWhether every penalty flagged on the play was declined.
penalty_enforcementcharacterHow the penalty was resolved: one of no_play, declined, offsetting, negating_foul, play_stands, unknown.
penalty_negated_playlogicalWhether the penalty negated the play's result.
sacklogicalBinary indicator for if the play ended in a sack.
intlogical
int_tdlogical
completionlogical
pass_attemptlogicalBinary indicator for if the play was a pass attempt (includes sacks).
targetlogical
pass_breakuplogicalTrue when a defender broke up the pass.
pass_tdlogical
rush_tdlogical
pass_depthcharacterThrown-pass depth parsed from ESPN play text ("short" or "deep"); null when the text omits it (sacks, screens, pre-2025 text).
pass_directioncharacterPass direction parsed from ESPN play text ("left", "middle", or "right"); null when the text omits it.
rush_directioncharacterRush direction parsed from ESPN play text ("left", "middle", or "right"); null when the text omits it.
turnover_veclogical
offense_score_playlogical
defense_score_playlogical
downs_turnoverlogical
yds_puntedinteger
yds_punt_gainedinteger
fg_attemptlogicalTrue when the play was a field-goal attempt.
fg_madelogical
yds_fginteger
pos_unitcharacter
def_pos_unitcharacter
lead_play_typecharacter
splogicalBinary indicator for whether or not a score occurred on the play.
playlogicalBinary indicator: 1 if the play was a 'normal' play (including penalties), 0 otherwise.
scrimmage_playlogicalTrue when the play is a play from scrimmage rather than a special-teams or administrative row.
change_of_pos_teamlogical
pos_score_diff_endintegerScore differential from the possessing team's perspective at the end of the play.
fumble_lostlogicalBinary indicator for if the fumble was lost.
fumble_recoveredlogicalTrue when a fumble on the play was recovered.
field_goal_resultcharacterString indicator for result of field goal attempt: made, missed, or blocked.
extra_point_resultcharacterString indicator for the result of the extra point attempt: good, failed, blocked, safety (touchback in defensive endzone is 1 point apparently), or aborted.
two_point_conv_resultcharacterString result of the two-point conversion attempt: success, failure, or safety (touchback in the defensive end zone).
kneel_downlogicalWhether the play is an offensive kneel, from explicit kneel text plus an end-of-half TEAM-rush heuristic.
qb_hurrylogicalWhether ESPN's play text says the quarterback was hurried into the throw ("hurried by ...").
xp_attemptlogicalWhether an extra-point kick was attempted on the play.
xp_madelogicalWhether the extra-point kick was successful.
two_point_attemptlogicalBinary indicator for two point conversion attempt.
defensive_two_point_attemptlogicalBinary indicator whether or not the defense was able to have an attempt on a two point conversion, this results following a turnover.
defensive_two_point_convlogicalBinary indicator whether or not the defense successfully scored on the two point conversion.
two_point_passlogical
two_point_rushlogical
yds_rushedinteger
yds_receivinginteger
yds_int_returncharacter
yds_kickoffinteger
yds_kickoff_returninteger
yds_punt_returninteger
yds_fumble_returncharacter
yds_sackedinteger
sack_playerscharacter
xp_kicker_player_namecharacterName of the kicker attempting the extra point.
passer_player_namecharacterString name for the player that attempted the pass.
rusher_player_namecharacterString name for the player that attempted the run.
receiver_player_namecharacterString name for the targeted receiver.
sack_player_namecharacterString name of the player who recorded a solo sack.
sack_player_name2character
pass_breakup_player_namecharacter
interception_player_namecharacterString name for the player that intercepted the pass.
fg_kicker_player_namecharacter
fg_block_player_namecharacter
fg_return_player_namecharacter
kickoff_player_namecharacter
kickoff_return_player_namecharacterName of the player returning the kickoff, when the play was returned.
punter_player_namecharacterString name for the punter.
punt_block_player_namecharacter
punt_return_player_namecharacterName of the player returning the punt, when the punt was returned.
punt_block_return_player_namecharacter
fumble_player_namecharacter
fumble_forced_player_namecharacter
fumble_recovered_player_namecharacter
kicking_teamintegerTeam id of the kicking team on kickoff, punt, and field-goal plays.
return_teamintegerTeam id of the returning side; set on interception, fumble, kickoff, punt, and blocked-kick returns.
fumble_or_mufflogicalWhether the play includes a fumble or a muffed kick or punt (widened beyond ESPN's fumble play types).
recovery_teamcharacterTeam id parsed from the play text as recovering the fumble or muff.
recovery_team_2characterTeam id of the second recovery in a multi-recovery scramble, parsed from the play text.
penalty_spot_yardlineintegerYard line (0-50) at which the penalty was spotted.
penalty_spot_sidecharacterSide of the field the penalty was spotted on: 'home', 'away' or 'mid' (midfield).
penalty_spot_yardsToEndzoneintegerYards from the penalty spot to the end zone (0-100).
fumbling_teamcharacterTeam id of the side that fumbled or muffed the ball, parsed from the play text.
int_turnoverlogicalWhether the play is an interception giveaway.
pos_fumble_lostlogicalWhether the possession team fumbled and lost the ball.
def_fumble_lostlogicalWhether the defending team (e.g. a returner after a takeaway) fumbled and lost the ball back.
is_pos_team_turnoverlogicalWhether the possession team committed a giveaway (interception or fumble lost).
is_def_pos_team_turnoverlogicalWhether the defending team gave the ball back via a lost fumble.
is_turnoverlogicalTrue when the play is a giveaway-based turnover (interception thrown or fumble lost); blocked kicks recovered by the defense are carried by the blocked-kick fields instead.
turnover_teamcharacterTeam id charged with the giveaway on the play.
is_st_turnoverlogicalWhether the giveaway happened on a special-teams play (kick or punt snap, or a return).
is_blocked_punt_turnoverlogicalBlocked-punt possession loss (blocked-punt TD, or the defense recovered); kept out of is_turnover to match ESPN's giveaway-only box.
is_blocked_fg_turnoverlogicalBlocked-field-goal possession loss (blocked-FG TD, or the defense recovered); kept out of is_turnover to match ESPN's giveaway-only box.
sack_teamintegerTeam id credited with the sack (the defense).
interception_teamintegerTeam id credited with the interception (the defense).
pass_breakup_teamintegerTeam id credited with the pass breakup (the defense).
forced_fumble_teamintegerTeam id credited with forcing the fumble -- the side opposite the fumbling player (the covering team on returns).
fumble_recovery_teamcharacterTeam id that recovered the fumble or muff, from parsed text with a giveaway / own-recovery fallback.
punt_return_teamintegerTeam id of the punt-returning side.
kick_return_teamintegerTeam id of the kick-returning side.
fg_teamintegerTeam id attempting the field goal (the kicking team).
punt_teamintegerTeam id punting the ball (the kicking team).
penalized_teamintegerTeam id the penalty was assessed against, from the home/away text resolver with a foul-direction fallback.
penalty_yards_signedintegerPenalty yardage parsed from the play text with era-aware bounds; the printed sign is retained but is not a reliable enforcement direction.
penalty_sidecharacterWhich side committed the penalty -- 'off' (offense) or 'def' (defense).
penalty_yards_netintegerNet yardage assessed for the penalty, signed relative to the possession team (observed -25 to 25).
penalty_team_idintegerTeam id of the side that committed the penalty.
lateral_player_namecharacter
yds_lateralcharacter
yards_after_catchcharacterNumeric value for distance in yards perpendicular to the yard line where the receiver made the reception to where the play ended.
air_yardscharacterNumeric value for distance in yards perpendicular to the line of scrimmage at where the targeted receiver either caught or didn't catch the ball.
air_yardsToEndzonecharacterYards to the endzone at the catch spot, parsed from the 2025+ vendor catch-spot text; null before 2025 or when unresolvable.
new_downintegerDown after the play, including any penalty enforcement.
new_distanceintegerDistance to go after the play, including any penalty enforcement.
middle_8logical
rz_playlogical
under_2logicalWhether the play began with two minutes or less remaining in the half.
goal_to_gologicalBinary indicator for whether or not the posteam is in a goal down situation.
scoring_opplogical
stuffed_runlogical
stopped_runlogicalTrue when the rush was stopped at or behind the line of scrimmage.
opportunity_runlogical
highlight_runlogicalTrue when the rush gained 8 or more yards.
adj_rush_yardageintegerRushing yards capped at 8, the input to the line-yards decomposition.
line_yardsdoubleYards credited to the offensive line on a rush, using the standard sliding scale: 1.2x the capped yardage on a loss, all of it through 3 yards, half of each yard from 4 to 8, and a 5.5-yard ceiling beyond that.
second_level_yardsdoubleRushing yards earned from 4 to 8, split evenly between line and carrier under the line-yards decomposition.
open_field_yardsintegerRushing yards gained beyond 8, credited to the ball carrier rather than the line.
highlight_yardsdoubleSecond-level plus open-field yards -- the yardage credited to the carrier.
opp_highlight_yardsdoubleHighlight yards earned on opportunity runs, isolating carrier production on carries where the blocking succeeded. Assets published before the 2026-08 fix are identically 0 here, because the inverted opportunity_run gate could never co-occur with non-zero highlight yards.
short_rush_successlogicalTrue when a short-yardage rush gained the yardage needed.
short_rush_attemptlogicalTrue when the play is a rush in a short-yardage situation.
power_rush_successlogicalTrue when a power rushing attempt gained the yardage needed.
power_rush_attemptlogicalTrue when the play is a short-yardage power rushing attempt.
early_downlogicalTrue when the play is a scrimmage play on first or second down.
late_downlogicalTrue when the play is a scrimmage play on third or fourth down.
early_down_passlogicalTrue when the play is a pass on an early down.
early_down_rushlogicalTrue when the play is a rush on an early down.
late_down_passlogicalTrue when the play is a pass on a late down.
late_down_rushlogicalTrue when the play is a rush on a late down.
standard_downlogicalTrue when the offense is on schedule for the series -- first down, second down needing fewer than 8, or third/fourth down needing fewer than 5.
passing_downlogicalTrue when the offense is behind schedule for the series -- second down needing 8 or more, or third/fourth down needing 5 or more.
TFLlogicalTrue when the play was a tackle for loss.
TFL_passlogicalTrue when the play was a tackle for loss on a pass play (a sack).
TFL_rushlogicalTrue when the play was a tackle for loss on a rush play.
havoclogicalTrue when the defense disrupted the play: a pass breakup, tackle for loss, interception or forced fumble.
first_down_yardslogicalWhether the play gained enough yardage to earn a first down.
first_down_penaltylogicalBinary indicator for if a penalty converted the first down.
first_down_earnedlogicalWhether the play earned a first down by means other than yardage (e.g. by penalty).
new_serieslogical
firstD_by_kickofflogical
firstD_by_posslogical
firstD_by_penaltylogical
firstD_by_yardslogical
start.pos_team_spreaddoubleESPN's pos_team_spread value for the play state at the start of the play.
start.elapsed_sharedoubleESPN's elapsed_share value for the play state at the start of the play.
start.spread_timedoubleESPN's spread_time value for the play state at the start of the play.
end.pos_team_spreaddoubleESPN's pos_team_spread value for the play state at the end of the play.
end.elapsed_sharedoubleESPN's elapsed_share value for the play state at the end of the play.
end.spread_timedoubleESPN's spread_time value for the play state at the end of the play.
pass_lengthcharacterString indicator for pass length: short or deep.
pass_locationcharacterString indicator for pass location: left, middle, or right.
shotgunintegerBinary indicator for whether or not the play was in shotgun formation.
no_huddleintegerBinary indicator for whether or not the play was in no_huddle formation.
pass_middleinteger
downintegerThe down for the given play.
distanceinteger
start.yardsToEndzone.touchbackintegerESPN's yardsToEndzone.touchback value for the play state at the start of the play.
penalty_assessed_on_kickofflogicalWhether a penalty was assessed on a kickoff; such plays take the kickoff/touchback win-probability handling.
EP_start_touchbackdoubleExpected points the offense would have had from a touchback on this play.
EP_startdoubleExpected points for the offense at the start of the play.
EP_enddoubleExpected points for the offense at the end of the play.
EP_penalty_cfcharacterCounterfactual expected points for the penalty branch -- the EP had the alternative penalty outcome been taken (null unless a penalty decision existed).
penalty_cf_yardsToEndzonecharacterYards to the end zone in the counterfactual penalty branch.
lag_EP_enddoubleValue of EP_end on the previous play, used for sequence-aware derivations.
lag_change_of_pos_teamlogical
EP_betweendoubleChange in expected points across the play, before penalty adjustment.
EPAdouble
def_EPAdouble
EPA_scrimmagedoubleEPA credited to the play on plays from scrimmage.
EPA_rushdoubleEPA credited to the play on rush plays.
EPA_passdoubleEPA credited to the play on pass plays.
EPA_explosivelogicalTrue when the play was explosive.
EPA_non_explosivedoubleEPA credited to the play on non-explosive plays.
EPA_explosive_passlogicalTrue when the pass play was explosive.
EPA_explosive_rushlogicalTrue when the rush play was explosive.
first_down_createdlogicalTrue when the play produced a first down for the offense.
EPA_successlogicalTrue when the play was successful by EPA.
EPA_success_early_downlogicalTrue when the play on an early down was successful by EPA.
EPA_success_early_down_passlogicalTrue when the pass play on an early down was successful by EPA.
EPA_success_early_down_rushlogicalTrue when the rush play on an early down was successful by EPA.
EPA_success_late_downlogicalTrue when the play on a late down was successful by EPA.
EPA_success_late_down_passlogicalTrue when the pass play on a late down was successful by EPA.
EPA_success_late_down_rushlogicalTrue when the rush play on a late down was successful by EPA.
EPA_success_standard_downlogicalTrue when the play on a standard down was successful by EPA.
EPA_success_passing_downlogicalTrue when the play on a passing down was successful by EPA.
EPA_success_passlogicalTrue when the pass play was successful by EPA.
EPA_success_rushlogicalTrue when the rush play was successful by EPA.
EPA_success_EPAdoubleEPA on successful plays.
EPA_success_standard_down_EPAdoubleEPA on successful plays on a standard down.
EPA_success_passing_down_EPAdoubleEPA on successful plays on a passing down.
EPA_success_pass_EPAdoubleEPA on successful pass plays.
EPA_success_rush_EPAdoubleEPA on successful rush plays.
EPA_middle_8_successlogicalTrue when the play in the middle eight was successful by EPA.
EPA_middle_8_success_passlogicalTrue when the pass play in the middle eight was successful by EPA.
EPA_middle_8_success_rushlogicalTrue when the rush play in the middle eight was successful by EPA.
EPA_penaltydoubleEPA credited to the play attributable to penalties.
EPA_penalty_directdoubleEPA attributable directly to the penalty on the play, separated from the EPA of the play itself (observed -11.7 to 8.05; null when no penalty applied).
EPA_spdoubleEPA credited to the play on special-teams plays.
EPA_fgdoubleEPA credited to the play on field-goal attempts.
EPA_puntdoubleEPA credited to the play on punt plays.
EPA_kickoffdoubleEPA credited to the play on kickoff plays.
qb_epadoubleGives QB credit for EPA for up to the point where a receiver lost a fumble after a completed catch and makes EPA work more like passing yards on plays with fumbles.
start.ExpScoreDiff_touchbackdoubleESPN's ExpScoreDiff_touchback value for the play state at the start of the play.
start.ExpScoreDiffdoubleESPN's ExpScoreDiff value for the play state at the start of the play.
start.ExpScoreDiff_Time_Ratio_touchbackdoubleESPN's ExpScoreDiff_Time_Ratio_touchback value for the play state at the start of the play.
start.ExpScoreDiff_Time_RatiodoubleESPN's ExpScoreDiff_Time_Ratio value for the play state at the start of the play.
end.ExpScoreDiffdoubleESPN's ExpScoreDiff value for the play state at the end of the play.
end.ExpScoreDiff_Time_RatiodoubleESPN's ExpScoreDiff_Time_Ratio value for the play state at the end of the play.
wp_beforedouble
wp_touchbackdoubleWin probability the offense would have had starting from a touchback.
wp_afterdouble
def_wp_beforedouble
home_wp_beforedouble
away_wp_beforedouble
lead_wp_beforedoubleValue of wp_before on the next play, used for sequence-aware derivations.
lead_wp_before2doubleValue of wp_before 2 plays ahead, used for sequence-aware derivations.
def_wp_afterdouble
home_wp_afterdouble
away_wp_afterdouble
wpadoubleWin probability added (WPA) for the posteam.
wpdoubleEstimated win probability for the posteam given the current situation at the start of the given play.
vegas_wpdoubleEstimated win probability for the posteam given the current situation at the start of the given play, incorporating pre-game Vegas line.
def_wpdoubleEstimated win probability for the defteam.
home_wpdoubleEstimated win probability for the home team.
away_wpdoubleEstimated win probability for the away team.
wp_before_naivedoublePre-snap possession-team win probability from the spread-free (naive) WP model.
wp_after_naivedoubleEnd-of-play possession-team win probability from the naive model, after the game-logic adjustment chain.
wpa_naivedoubleWin probability added on the play under the spread-free (naive) model.
def_wp_before_naivedoublePre-snap defense win probability under the naive model (1 - wp_before_naive).
def_wp_after_naivedoubleEnd-of-play defense win probability under the naive model.
home_wp_before_naivedoublePre-snap naive win probability mapped to the home team.
home_wp_after_naivedoubleEnd-of-play naive win probability mapped to the home team.
lead_wp_before_naivedoubleNext play's pre-snap naive win probability, used in the end-of-half and change-of-possession adjustments.
lead_wp_before2_naivedoublePre-snap naive win probability two plays ahead, used where the immediately following row is a non-play.
wp_touchback_naivedoubleNaive-model win probability for the kickoff-touchback substitute state, used as the pre-snap WP on kickoffs.
away_wp_before_naivedoublePre-snap naive win probability mapped to the away team.
away_wp_after_naivedoubleEnd-of-play naive win probability mapped to the away team.
cpcharacterNumeric value indicating the probability for a complete pass based on comparable game situations.
cpoecharacterFor a single pass play this is 1 - cp when the pass was completed or 0 - cp when the pass was incomplete. Analyzed for a whole game or season an indicator for the passer how much over or under expectation his completion percentage was.
xpassdoubleProbability of dropback scaled from 0 to 1.
pass_oedoubleDropback percent over expected on a given play scaled from 0 to 100.
xyac_epacharacterExpected value of EPA gained after the catch, starting from where the catch was made. Zero yards after the catch would be listed as zero EPA.
xyac_mean_yardagecharacterAverage expected yards after the catch based on where the ball was caught.
xyac_median_yardagecharacterMedian expected yards after the catch based on where the ball was caught.
xyac_successcharacterProbability play earns positive EPA (relative to where play started) based on where ball was caught.
xyac_fdcharacterProbability play earns a first down based on where the ball was caught.
drive_startdoubleYard line at which the drive began.
drive_stoppedlogicalTrue when the play ended the drive.
drive_play_indexintegerSequence number of the play within its drive.
drive_offense_playsintegerOffensive plays run on the drive.
prog_drive_EPAdoubleCumulative EPA accrued by the drive up to and including this play.
prog_drive_WPAdoubleCumulative win-probability added by the drive up to and including this play.
drive_offense_yardsintegerOffensive yards gained on the drive.
drive_total_yardsintegerTotal yards gained on the drive.
fixed_driveintegerManually created drive number in a game.
fixed_drive_resultcharacterManually created drive result.
seriesintegerStarts at 1, each new first down increments, numbers shared across both teams NA: kickoffs, extra point/two point conversion attempts, non-plays, no posteam
series_resultcharacterPossible values: First down, Touchdown, Opp touchdown, Field goal, Missed field goal, Safety, Turnover, Punt, Turnover on downs, QB kneel, End of half
series_successinteger1: scored touchdown, gained enough yards for first down.
go_wpdoubleWin probability from going for it on fourth down: conversion-probability-weighted mean of the success and failure states (cfb4th port).
first_down_probdoubleModeled probability of converting the fourth down when going for it.
wp_succeeddoubleMean win probability across yardage outcomes given the fourth-down attempt converts.
wp_faildoubleMean win probability given the fourth-down attempt fails.
fg_make_probdouble
make_fg_wpdoubleWin probability given the field-goal attempt is made.
miss_fg_wpdoubleWin probability given the field-goal attempt misses.
fg_wpdoubleMake-probability-weighted win probability of attempting the field goal.
punt_wpdoubleWin probability of punting, from the bundled punt-outcome distribution.
go_boostdoublecfb4th's headline number: 100 * (go_wp - max(fg_wp, punt_wp)), in percentage points.
go_wp_diffdoublego_wp minus the recommended option's WP (0 when going for it is the recommendation, otherwise <= 0).
punt_wp_diffdoublepunt_wp minus the recommended option's WP (0 when punting is the recommendation, otherwise <= 0).
fg_wp_diffdoublefg_wp minus the recommended option's WP (0 when the field goal is the recommendation, otherwise <= 0).
fourth_down_recommendationcharacterMax-WP fourth-down choice among "go", "punt", and "field_goal".
two_pt_wpdoubleWin probability of going for two: conversion-probability-weighted mean of the 2-point and 0-point outcomes (cfb4th port).
xp_wpdouble
prob_2ptdouble
two_pt_wp_diffdoubletwo_pt_wp minus xp_wp; positive favors going for two.
two_pt_recommendationcharacterPoint-after recommendation: "go_for_2" when two_pt_wp exceeds xp_wp, otherwise "kick_xp".
qbr_epadoubleEPA variant used as an input to the QBR calculation.
weightdoubleOfficial weight, in pounds
non_fumble_sacklogicalTrue when the play was a sack that did not produce a fumble.
sack_epadoubleEPA credited to the play when it is a sack.
pass_epadoubleEPA credited to the play when it is a pass.
rush_epadoubleEPA credited to the play when it is a rush.
pen_epadoubleEPA attributable to a penalty on the play.
sack_weightdoubleWeighting applied to the sack component of the play.
pass_weightdoubleWeighting applied to the pass component of the play.
rush_weightdoubleWeighting applied to the rush component of the play.
pen_weightdoubleWeighting applied to the penalty component of the play.
action_playlogicalTrue when the play advanced the game state -- excludes timeouts, end-of-period markers and other non-action rows.
athlete_namecharacter
sack_player_id2characterESPN athlete id of the second sacker on a split sack (regex fallback for an ESPN sidecar blind spot).
passer_player_idcharacterUnique identifier for the player that attempted the pass.
rusher_player_idcharacterUnique identifier for the player that attempted the run.
receiver_player_idcharacterUnique identifier for the receiver that was targeted on the pass.
punter_player_idcharacterUnique identifier for the punter.
fg_kicker_player_idcharacterESPN athlete id of the field-goal kicker.
sack_player_idcharacterUnique identifier of the player who recorded a solo sack.
punt_return_player_idcharacterESPN athlete id of the punt returner.
kickoff_return_player_idcharacterESPN athlete id of the kickoff returner.
interception_player_idcharacterUnique identifier for the player that intercepted the pass.
pass_breakup_player_idcharacter
fumble_forced_player_idcharacter
fumble_recovered_player_idcharacter
fumble_player_idcharacter
punt_block_player_idcharacterESPN athlete id of the player who blocked the punt.
punt_block_return_player_idcharacterESPN athlete id of the player who returned the blocked punt.
kickoff_player_idcharacterESPN athlete id of the player kicking off.
fg_block_player_idcharacterESPN athlete id of the player who blocked the field goal.
fg_return_player_idcharacterESPN athlete id of the player who returned the blocked or missed field goal.
xp_kicker_player_idcharacter

Example

# For most use cases, call the high-level entry point instead. ``enrich_nfl_pbp`` scores WP, derives WPA, and adds EP/EPA/CP/CPOE in one shot on any nflverse-shape frame

from sportsdataverse.nfl import load_nfl_pbp
from sportsdataverse.nfl.ep_wp import enrich_nfl_pbp

pbp = load_nfl_pbp([2023])
enriched = enrich_nfl_pbp(pbp)
print(enriched.select("game_id", "wp", "def_wp", "home_wp", "away_wp", "wpa").head())

``calculate_wpa`` directly requires ESPN-internal columns
(``wp_before``, ``wp_touchback``, ``wp_after``, ``homeTeamId``,
``start.pos_team.id``, etc.) produced by ``NFLPlayProcess``. It is
called internally by ``NFLPlayProcess.__process_wpa`` and by the
``enrich_nfl_pbp`` orchestrator — a naked
``calculate_wpa(load_nfl_pbp([2023]))`` will raise ``KeyError``
because those columns are absent from a nflverse frame.