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 15 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.

Plotting Air Yards for the top 10 PPR Receivers

In this post, we are going to be plotting air yards for the top 10 PPR receivers so far in the 2020 season. This will be an exercise in flexing our data visualization skills with matplotlib.

Two new things we are doing in this post: (1) we're using nflfastR to find team colors and (2) we're also using nflfastR to find player headshots and going to be appending them to the visualization. Just some added fluff to make our visualization look a bit nicer. Figuring out how to incorporate these two things is going to be 80% of the new stuff in this post, but it will help us strengthen our data visualization skills.

First things first, open up a new Google Colab or jupyter notebook and import the libraries you'll be needing in the first cell.

Below, we're mainly doing three things. I've commented the details in the code block below, but for a high level overview:

Firstly, we're importing 2020 play by play data using the read_csv function. We can provide a file path to a CSV located on our local machine or in our Google Colab runtime, or in this case, we can provide the URL for a CSV file hosted remotely somewhere on the web. Pandas takes care of making the request and downloading the gzip file behind the scenes, and loads it directly in to a DataFrame for us to use.

Secondly, we're going to be running a groupby and sum to find those player's with the most receiving-relevant PPR fantasy points, sorting in descending order, and then grabbing the top 10. This might change by the time you run this code. This code currently works for Week 3. It should work for Week 4 and on, but you'll have to adjust things for example when we locate the player headshots.

Lastly, we're grabbing team team data (team_df) and merging it with our final DataFrame. This team team data contains the team color data in the form of hexidecimal code. We're going to be using team color data to color our visualizations based off which team a player is on.

receiver_player_id receiver_player_name air_yards team_color team_logo_wikipedia
2 32013030-2d30-3033-3035-3634b926c47f D.Hopkins 3.0 #97233f https://upload.wikimedia.org/wikipedia/en/thum...
8 32013030-2d30-3033-3035-3634b926c47f D.Hopkins -4.0 #97233f https://upload.wikimedia.org/wikipedia/en/thum...
22 32013030-2d30-3033-3035-3634b926c47f D.Hopkins -1.0 #97233f https://upload.wikimedia.org/wikipedia/en/thum...
23 32013030-2d30-3033-3035-3634b926c47f D.Hopkins 6.0 #97233f https://upload.wikimedia.org/wikipedia/en/thum...
26 32013030-2d30-3033-3035-3634b926c47f D.Hopkins -2.0 #97233f https://upload.wikimedia.org/wikipedia/en/thum...

Great! So what are we left with? We're left with rows containing each passing play each player in the top 10 PPR receiving group was involved with. The data contains the air yards for each player, the player's id, name, their team's color, and a link to their team's logo (in case you want to add that to the final visualization as well; I left it out).

Let's work on getting those player headshots appended to this DataFrame as well. Player headshots also come from nflfastR, but there's one small problem. The headshot data does not have a player ID column we can use to join the two tables.

As a roundabout solution, we're going to bring in the headshot data, and try to find those rows that contain our player names in our passing_df. This will get us close to our solution, but not quite there. There will be other player's also with the name R.Anderson that we have to specifically identify and drop before joining our data. That will be our last step before merging the data.

These are the 10 players included in our passing_df.

receiver_player_name teamPlayers.position team.fullName teamPlayers.headshot_url
0 C.Ridley WR Atlanta Falcons http://static.nfl.com/static/content/public/st...
1 R.Anderson RB Cincinnati Bengals http://static.nfl.com/static/content/public/st...
2 D.Hopkins WR Houston Texans http://static.nfl.com/static/content/public/st...
3 T.Hill WR Kansas City Chiefs http://static.nfl.com/static/content/public/st...
4 T.Kelce TE Kansas City Chiefs http://static.nfl.com/static/content/public/st...
5 K.Allen WR Los Angeles Chargers http://static.nfl.com/static/content/public/st...
6 S.Diggs WR Minnesota Vikings http://static.nfl.com/static/content/public/st...
7 A.Kamara RB New Orleans Saints http://static.nfl.com/static/content/public/st...
8 R.Anderson WR New York Jets http://static.nfl.com/static/content/public/st...
9 D.Metcalf WR Seattle Seahawks http://static.nfl.com/static/content/public/st...
10 T.Lockett WR Seattle Seahawks http://static.nfl.com/static/content/public/st...

As we can see, we're almost there. There's one player that does not belong and that's R.Anderson for the Bengals. We can remove his row by simply using the drop method.

Now we can merge this roster_df that has the headshot data with our passing_df with a simple one liner.

receiver_player_id receiver_player_name air_yards team_color team_logo_wikipedia teamPlayers.headshot_url
0 32013030-2d30-3033-3035-3634b926c47f D.Hopkins 3.0 #97233f https://upload.wikimedia.org/wikipedia/en/thum... http://static.nfl.com/static/content/public/st...
1 32013030-2d30-3033-3035-3634b926c47f D.Hopkins -4.0 #97233f https://upload.wikimedia.org/wikipedia/en/thum... http://static.nfl.com/static/content/public/st...
2 32013030-2d30-3033-3035-3634b926c47f D.Hopkins -1.0 #97233f https://upload.wikimedia.org/wikipedia/en/thum... http://static.nfl.com/static/content/public/st...
3 32013030-2d30-3033-3035-3634b926c47f D.Hopkins 6.0 #97233f https://upload.wikimedia.org/wikipedia/en/thum... http://static.nfl.com/static/content/public/st...
4 32013030-2d30-3033-3035-3634b926c47f D.Hopkins -2.0 #97233f https://upload.wikimedia.org/wikipedia/en/thum... http://static.nfl.com/static/content/public/st...

All that's left to do is visualize the results. The hard part here will be getting the player headshots on there. We're going to be plotting each player's air yards as a kernel-density estimation.

And that's it! This is not going to lie the coolest visualization I've probably ever made for my course or blog. I'll be using player headshots in my visualizations much more often now probably.

If you want to make this more useful for fantasy football analysis, I encourage you to find the top 10 player's in terms of air yards and plot their distributions instead (You'll probably be surprised who tops the list in air yards through week 3 considering they've had a lower than expected performance in weeks 1-3).

Thanks for reading. Good luck in week 4!