Measuring Bryce Young's Turnaround

Bryce Young's rookie season was one of the worst in the league that year. Three seasons later he's a league-average starter, and better than that in parts of 2026. This post uses play-by-play and FTN charting data to find when the change happened, what actually changed, and how much to trust seven weeks of 2026.

Four seasons at a glance

Carolina drafted Young first overall in 2023. He finished his rookie year 36th of 39 qualifying quarterbacks in EPA per dropback, was benched after Week 2 of 2024, and got the job back in Week 8. Every season since has been better than the one before.

SeasonDropbacksEPA / dropbackRankCPOESack rateSuccess rate
2023620−0.22836 of 39−1.410.0%37.1%
2024451−0.02729 of 40+0.76.4%40.6%
2025539−0.01229 of 38+1.05.0%43.8%
2026 (through Week 7)251+0.09315 of 32+0.76.8%44.2%

Season totals hide the timing, though. Figure 1 shows all 50 games where Young had at least 15 dropbacks.

Figure 1: EPA per dropback in every Bryce Young start, 2023 through Week 7 of 2026, with a rolling six-game average weighted by dropbacks.

Single games swing wildly: anywhere from about −0.75 to +0.63. A game is only 30 to 50 dropbacks, and one play's EPA has a standard deviation of about 1.6, so a single game's average is roughly ±0.25 of noise on its own. The rolling average is clearer: it sits well below zero through 2023 and the start of 2024, then climbs and stays near or above zero.

When did it change?

Eyeballing a rolling average isn't a test. A Bayesian change-point model asks the question directly: if Young's true EPA per dropback was one constant before some game and another constant after it, which game is the most likely break, and is a break more likely than no change at all?

Each game's average is treated as the true rate for its segment plus noise that shrinks with more dropbacks (variance σ²/n). Each segment's true rate gets a prior centered on the league average, with a spread equal to how much quarterbacks really differ (0.11 EPA per dropback, estimated from 2023–25). Integrating out the unknown rates gives a closed-form likelihood for every possible break point.

def segment_log_ml(y, n, m0, s0, sigma2):
    """Log marginal likelihood of game means y (n dropbacks each) sharing one
    unknown true rate with prior N(m0, s0^2). The rate is integrated out."""
    v = sigma2 / n                         # each game's sampling variance
    a = 1 / s0**2 + np.sum(1 / v)
    resid = y - m0
    return -0.5 * (np.sum(np.log(2 * np.pi * v))
                   + np.log(1 + s0**2 * np.sum(1 / v))
                   + np.sum(resid**2 / v)
                   - np.sum(resid / v)**2 / a)

# Every possible single break: segment 1 = games[:t], segment 2 = games[t:]
log_like = np.array([segment_log_ml(y[:t], n[:t], m0, s0, sigma2) +
                     segment_log_ml(y[t:], n[t:], m0, s0, sigma2) for t in taus])
posterior = np.exp(log_like - log_like.max())
posterior /= posterior.sum()               # uniform prior over break locations
Figure 2: Posterior probability that Young's true level changed right after each start. Vertical lines mark the start of each season.
  • A change is real. The one-break model beats the no-change model by a Bayes factor of about 15 to 1.
  • It happened in 2024. 83% of the probability falls in the 2024 season (including the offseason before it), and the single most likely break is the benching itself: between Week 2 against the Chargers and his return in Week 8 against Denver.
  • It was a step, not a climb. Before the break Young averaged −0.259 EPA per dropback; after it, +0.038. Adding a second break (the best candidate is late 2025) barely improves the fit (Bayes factor ≈ 1), so 2025 and 2026 look like the same new level rather than continued improvement, at least so far.

The location is fuzzy within 2024. The next most likely breaks are a week or a month after his return, which is what you'd expect when a player improves over a few games rather than overnight. But the data points to the benching window, not to 2025 or 2026.

What actually changed

EPA mixes the quarterback with everyone around him. Two sources help separate them. Charted pressure data (available through 2025) shows how he handled pressure, and FTN's play-by-play charting records things like whether a sack was the quarterback's fault, whether a throw was catchable, and which read he threw to.

Pressure

SeasonPressured onPressures that became sacksEPA when pressuredEPA from a clean pocket
202332.9% (30.1%)30.4% (22.6%)−0.76 (−0.48)+0.03 (+0.20)
202432.6% (30.7%)19.7% (21.8%)−0.32 (−0.42)+0.11 (+0.22)
202530.8% (29.8%)16.3% (20.3%)−0.35 (−0.46)+0.14 (+0.27)

League median of qualifying quarterbacks in parentheses.

This is the biggest single change. As a rookie, Young turned 30% of his pressures into sacks, one of the worst rates in the league. By 2025 it was 16%, better than the median. He's also gone from far below average when pressured to above average. How often he's pressured barely moved, so this isn't mainly the offensive line getting better. It's Young handling pressure differently.

The weak spot that's left is the clean pocket. Even in 2025, when nobody got to him, he produced +0.14 EPA per dropback against a league median of +0.27. Young has become good at avoiding disasters; he isn't yet producing like a top quarterback when everything goes right.

Decisions and accuracy

ftn = ftn.rename(columns={"nflverse_game_id": "game_id", "nflverse_play_id": "play_id"})
d = dropbacks.merge(ftn, on=["game_id", "play_id"])            # 99.9% of dropbacks match
att = d[(d.pass_attempt == 1) & (d.sack == 0)]
aimed = att[~att.is_throw_away]

by = ["season", "passer"]
rates = pd.DataFrame({
    "qb_fault_sack": d.groupby(by).is_qb_fault_sack.mean(),     # per dropback
    "int_worthy": att.groupby(by).is_interception_worthy.mean(), # per attempt
    "catchable": aimed.groupby(by).is_catchable_ball.mean(),     # per aimed throw
    "drop": aimed[aimed.is_catchable_ball].groupby(by).is_drop.mean(),
    "first_read": att[att.read_thrown.isin(["1", "2", "CHK"])]
                     .groupby(by).read_thrown.apply(lambda s: (s == "1").mean()),
})
Figure 3: Reads and accuracy by season, from FTN charting. Hover a group for the league median. Catchable rate excludes throwaways.
Figure 4: Mistakes and bailouts by season. QB-fault sacks are per dropback; interception-worthy throws and throwaways are per attempt; drops are a share of catchable targets.
  • Fewer mistakes. Sacks charted as his fault fell from 2.9% of dropbacks in 2023 to 1.1–1.7% in 2024–25 and none so far in 2026. Interception-worthy throws fell from 3.6% of attempts to 1.8%, now well below the league median of 2.8%.
  • Throwing it away instead. He already threw the ball away about twice as often as the median as a rookie (7.8%), and in 2026 it's 11.4%, nearly three times the median. Paired with the falling sack rate, it shows a quarterback giving up on dead plays rather than holding the ball.
  • Trusting the first read. He threw to his first read on 62% of attempts as a rookie and 74% in 2026, above the median, while his checkdown rate fell from 22% to 14%.
  • Accuracy hasn't moved. About 71–75% of his aimed throws are catchable every season, at or slightly below the league median throughout. Receiver drops are close to league average every year, so the supporting cast isn't the explanation either way.

The scheme changed too

Dave Canales became head coach in 2024, after Frank Reich was fired midway through 2023, and the offense around Young looks different. Play-action went from 14% of his dropbacks in 2023 to 26% in 2026, and pre-snap motion from 26% to 53%. Both make reads easier, and they help explain why he throws to his first read more often. This data can't fully separate the coaching from the quarterback. But the changes that are most clearly his own, sacks he causes and interception-worthy throws, improved the most.

How much should we trust 2026?

Seven weeks is 251 dropbacks, and Figure 1 shows how noisy that is. One bad game against Tampa Bay in Week 7 (−0.61) dropped him from 7th (+0.200) to 15th. A standard fix is empirical-Bayes shrinkage: pull each quarterback's rate toward the league average by an amount that depends on how much data he has, using the real spread of quarterback talent (0.11 EPA per dropback) and the noise in a single dropback (about 1.6).

noise = per_play_var / q26.dropbacks                     # sampling variance of each QB's average
q26["shrunk"] = (tau2 * q26.epa + noise * league_mean) / (tau2 + noise)
q26["post_sd"] = np.sqrt(tau2 * noise / (tau2 + noise))

# Simulate every QB's true rate from his posterior and rank them
draws = rng.normal(q26.shrunk.values[:, None], q26.post_sd.values[:, None], size=(len(q26), 20_000))
ranks = (-draws).argsort(axis=0).argsort(axis=0) + 1
Figure 5: 2026 quarterbacks through Week 7, raw EPA per dropback vs. the shrunk estimate. Points below the diagonal are pulled down toward the league average; points above it are pulled up.

Young's +0.093 shrinks to +0.068, still 15th of 32, with a posterior standard deviation of 0.075. Simulating everyone's true rate gives him a 66% chance of being an above-average quarterback this season and a 30% chance of being top 10, with a 90% interval for his rank of 4th to 27th. The same method put his 2025 season at almost exactly average (+0.001), and there's about an 82% chance his true 2026 level is higher than that. So the honest summary is: likely better than last year, probably above average, and not yet proven to be more than that.

Caveats

  • 2026 data is through Week 7. Every 2026 number here will move as the season goes on.
  • Charted pressure data isn't published for 2026 yet, so the pressure table stops at 2025.
  • FTN charting involves judgment. What counts as "catchable" or "interception-worthy" is a charter's call, though it's applied consistently across the league.
  • The change-point model assumes a level shift. A gradual improvement would spread its probability across many games, which is part of why the location is fuzzy within 2024.

Data and code

Play-by-play, participation, and FTN charting data from nflverse, 2023 through Week 7 of 2026, regular season only. Every number and chart comes from football-analysis/bryce_young.py.

← Back to all posts