Learn how to use Python to analyze WR yards after catch for the 2020 season.
If you have any questions about the code here, feel free to reach out to me on Twitter or on Reddit.
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
play.
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!