If you have any questions about the code here, feel free to reach out to me on Twitter or on Reddit.

Shameless Plug Section

If you like Fantasy Football and have an interest in learning how to code, check out our Ultimate Guide on Learning Python with Fantasy Football Online Course. Here is a link to purchase for 15% off. The course includes 16 chapters of material, 14 hours of video, hundreds of data sets, lifetime updates, and a Slack channel invite to join the Fantasy Football with Python community.

In this part (and the next couple parts) of the intermediate series, we're going to be looking at YAC yardage for WRs.

YAC stands for yards after catch, and it's a measure of how many yards a receiver gained (drum roll please) after they made a catch.

It'll be interesting to see which receivers have the most YAC yardage this season (I'm guessing McLaurin, AJ Brown, and Tyreek Hill), but it'll also

be interesting to see which receivers have the most YAC yardage over expected. Play by play data provided by nflfastR also gives us access to

an expected yards after catch model, which tells us on each play, how many yards a WR can be expected to gain (given where they caught the ball, the defense, etc.).

So we can take actual YAC and subtract out expected YAC and get a number for YAC over expected. The receivers leading the league in YAC over expected are the best WRs

at making something happen after the play, compared to the average receiver in the NFL. We'll also look at yards after catch per reception.

Finally, we'll start working on plotting distribution of yards after catch by plotting AJ Brown's YAC this season. AJ Brown has been an absolute YAC monster this season,

and it's been a (humble brag incoming) blast having him on my lineup in 2 leagues this year.

We'll start off this post with installing and importing the necessary libraries. If you're working from Colab, you'll have to run the command below in a cell to install

the nflfastpy module. This is where we'll be getting our data from. If you're using jupyter, then just pip install it in your terminal.

And next we import the necessary libraries plus adjusting some pandas and matplotlib settings.

And last part of our setup is grabbing our data. We're going to be grabbing play by play data in the first line below and then grabbing roster data to find player positions (we only want to include WRs in our data)

In our df DataFrame, we have a couple relevant columns. xyac_mean_yardage gives us the mean expected yards after catch. air_yards gives us the distance a ball was thrown.

yards_gained gives us the actual number of yards gained by a receiver. The difference between air yards and yards gained on complete passes is our YAC number.

We're going to be creating a function called calc_yac that helps us calculate YAC and pass it in to the apply method. The calc_yac function is only going to calculate yac if the receiver caught the ball on a given


What we are going to do now is group by receiver_player_id and receiver_player_name and sum the values for each of the aforementioned columns. We will be left with a

row for each receiver that has the sum of their expected yards after catch, air yards, and yards gained.

receiver_player_name xyac_mean_yardage complete_pass air_yards yards_gained yac gsis_id position
1 L.Fitzgerald 300.391423 45.0 337.0 346.0 171.0 00-0022921 WR
7 T.Ginn 49.643114 3.0 121.0 40.0 10.0 00-0025396 WR
9 D.Amendola 281.603665 37.0 444.0 539.0 258.0 00-0026035 WR
10 D.Jackson 131.486253 13.0 391.0 155.0 25.0 00-0026189 WR
14 J.Edelman 172.011492 21.0 401.0 315.0 64.0 00-0027150 WR

Now that we have our data properly formatted, let's calculate YAC over expected using nflfastR's xyac model.

receiver_player_name xyac_mean_yardage complete_pass air_yards yards_gained yac gsis_id position yac_over_expected yac_per_catch
437 D.Samuel 308.174402 33.0 97.0 391.0 398.0 00-0035719 WR 89.825598 12.060606
274 C.Sims 130.418611 19.0 264.0 345.0 177.0 00-0034104 WR 46.581389 9.315789
453 I.Wright 109.213838 25.0 105.0 182.0 134.0 00-0036142 WR 24.786162 5.360000
469 F.Swain 71.489968 12.0 173.0 156.0 96.0 00-0036247 WR 24.510032 8.000000
409 M.Taylor 26.960925 5.0 40.0 66.0 47.0 00-0035480 WR 20.039075 9.400000

Um, these results are... interesting. Deebo Samuel seems to be the YAC MVP of the season given these results, and Deebo Samuel is great, but I don't know how much I trust the xyac model given the other rows, to be completely honest.

Let's move on to just finding the top YAC guys and top YAC per catch.

receiver_player_name yac
0 D.Adams 507.0
1 C.Kupp 477.0
2 R.Anderson 464.0
3 R.Woods 463.0
4 D.Hopkins 442.0
receiver_player_name complete_pass yac_per_catch
0 D.Samuel 33.0 12.060606
1 M.Pittman 33.0 7.333333
2 M.Hardman 33.0 7.303030
3 A.Brown 51.0 7.137255
4 D.Amendola 37.0 6.972973

It's interesting that we have two LA Rams WR in the top 5 for YAC for the season so far. Davante Adams at the top of the list doesn't surprise me in the slightest.

Deebo tops a list again, this time for YAC per catch. Shame he was injured most of the season. I think he would have had a fantastic second year campaign.

Amendola (as someone who doesn't watch many Lions games) is a surprise to me on this list.

Let's move on to plotting YAC. I chose to use AJ Brown as the example here because it seems like every week he pulls off a monster after catch run.

And that's it for this part of the intermediate series. Thank you for reading!