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.

Finding Rushing Shares and Target Shares with Python

In this post, we are going to go over a step-by-step approach to scraping profootballreference data and visualizing RB rushing shares and target shares to find potential waiver-wire pickups.

If this is your first time following our posts, you'll need to use a notebook environment to run the code. You can set a Google Colab notebook in a couple seconds if you have a Google account.

Scraping profootballreference.com

First things first, we're going to need to scrape profootballreference to get week one data.

Here's the URL for game stats from 2020 week 1 that we are going to scrape. Notice that there is a query parameter for offset that we'll need to deal with. The data is paginated, so we'll need to figure out a way to flip through all of the pages and iteratively scrape each page, and finally concatenate the data together in to one final DataFrame.

Data Munging

Once we scrape the data, we'll need to find total targets for each team and also total rushing attempts for RB's for each team. From there, we can calculate a seperate column for target share and rushing share based off each player's individual rushing attempts and targets. This will be done with Pandas.

Visualizing the results

Finally, we'll create a visualization using matplotlib with rushing share on the x-axis and target share on the y-axis. This will allow us to quickly view how players stacked up against each other week 1 in both these metrics.

The Code

Let's write some code. First things first, open up a Google Colab notebook and import some libraries.

With that out of the way, let's write a function to scrape that URL I linked above and get back week 1 2020 data.

Player Pos Tm Att Y/A Tgt Rec Y/R Y/Tgt RushingYds ReceivingYds RushingTD ReceivingTD
0 Clyde Edwards-Helaire RB KAN 25.0 5.52 2.0 0.0 NaN 0.00 138.0 0.0 1.0 0.0
1 Derrick Henry RB TEN 31.0 3.74 3.0 3.0 5.00 5.00 116.0 15.0 0.0 0.0
2 Benny Snell Jr. RB PIT 19.0 5.95 1.0 0.0 NaN 0.00 113.0 0.0 0.0 0.0
3 Christian McCaffrey RB CAR 23.0 4.22 4.0 3.0 12.67 9.50 97.0 38.0 2.0 0.0
4 Ezekiel Elliott RB DAL 22.0 4.36 4.0 3.0 10.33 7.75 96.0 31.0 1.0 1.0

As you can see here, we are iteratively updating our final df until the offset parameter get's us back an empty DataFrame. This means we have reached the end of our data, and we can break the while loop.

We now have our data ready to be manipulated. What we need to do now is groupby team and find the RB rushing attempts for each team and also the targets for each team for all positions.

Now we can join these two Series objects with our original df to have a column for each player with data on their team targets and team rushing attempts.

Player Pos Tm Att_ind Y/A Tgt Rec Y/R Y/Tgt RushingYds ReceivingYds RushingTD ReceivingTD Att_team
0 Clyde Edwards-Helaire RB KAN 25.0 5.52 2.0 0.0 NaN 0.00 138.0 0.0 1.0 0.0 33.0
1 Derrick Henry RB TEN 31.0 3.74 3.0 3.0 5.00 5.00 116.0 15.0 0.0 0.0 31.0
2 Benny Snell Jr. RB PIT 19.0 5.95 1.0 0.0 NaN 0.00 113.0 0.0 0.0 0.0 26.0
3 Christian McCaffrey RB CAR 23.0 4.22 4.0 3.0 12.67 9.50 97.0 38.0 2.0 0.0 25.0
4 Ezekiel Elliott RB DAL 22.0 4.36 4.0 3.0 10.33 7.75 96.0 31.0 1.0 1.0 24.0
Player Pos Tm Att_ind Y/A Tgt_ind Rec Y/R Y/Tgt RushingYds ReceivingYds RushingTD ReceivingTD Att_team Tgt_team
0 Clyde Edwards-Helaire RB KAN 25.0 5.52 2.0 0.0 NaN 0.00 138.0 0.0 1.0 0.0 33.0 32.0
1 Derrick Henry RB TEN 31.0 3.74 3.0 3.0 5.00 5.00 116.0 15.0 0.0 0.0 31.0 40.0
2 Benny Snell Jr. RB PIT 19.0 5.95 1.0 0.0 NaN 0.00 113.0 0.0 0.0 0.0 26.0 31.0
3 Christian McCaffrey RB CAR 23.0 4.22 4.0 3.0 12.67 9.50 97.0 38.0 2.0 0.0 25.0 34.0
4 Ezekiel Elliott RB DAL 22.0 4.36 4.0 3.0 10.33 7.75 96.0 31.0 1.0 1.0 24.0 37.0

Awesome, so now that we have this data formatted for each player, we can calculate a catch rate and also a rushing share.

Player Pos Tm Att_ind Y/A Tgt_ind Rec Y/R Y/Tgt RushingYds ReceivingYds RushingTD ReceivingTD Att_team Tgt_team RushingShare TgtShare
0 Clyde Edwards-Helaire RB KAN 25.0 5.52 2.0 0.0 NaN 0.00 138.0 0.0 1.0 0.0 33.0 32.0 0.757576 0.062500
1 Derrick Henry RB TEN 31.0 3.74 3.0 3.0 5.00 5.00 116.0 15.0 0.0 0.0 31.0 40.0 1.000000 0.075000
2 Benny Snell Jr. RB PIT 19.0 5.95 1.0 0.0 NaN 0.00 113.0 0.0 0.0 0.0 26.0 31.0 0.730769 0.032258
3 Christian McCaffrey RB CAR 23.0 4.22 4.0 3.0 12.67 9.50 97.0 38.0 2.0 0.0 25.0 34.0 0.920000 0.117647
4 Ezekiel Elliott RB DAL 22.0 4.36 4.0 3.0 10.33 7.75 96.0 31.0 1.0 1.0 24.0 37.0 0.916667 0.108108

The last thing left to do is acually visualize the results with matplotlib. We can do this in a few lines of code.

Player Pos Tm Att_ind Y/A Tgt_ind Rec Y/R Y/Tgt RushingYds ReceivingYds RushingTD ReceivingTD Att_team Tgt_team RushingShare TgtShare
0 Clyde Edwards-Helaire RB KAN 25.0 5.52 2.0 0.0 NaN 0.00 138.0 0.0 1.0 0.0 33.0 32.0 0.757576 0.062500
1 Derrick Henry RB TEN 31.0 3.74 3.0 3.0 5.00 5.00 116.0 15.0 0.0 0.0 31.0 40.0 1.000000 0.075000
2 Benny Snell Jr. RB PIT 19.0 5.95 1.0 0.0 NaN 0.00 113.0 0.0 0.0 0.0 26.0 31.0 0.730769 0.032258
3 Christian McCaffrey RB CAR 23.0 4.22 4.0 3.0 12.67 9.50 97.0 38.0 2.0 0.0 25.0 34.0 0.920000 0.117647
4 Ezekiel Elliott RB DAL 22.0 4.36 4.0 3.0 10.33 7.75 96.0 31.0 1.0 1.0 24.0 37.0 0.916667 0.108108

And there's our visualization!

Some notes:

Derrick Henry and James Robinson are the only RBs in week one with a 100% rushing share. Saquon, CMC, Zeke, Barkley and Jacobs all came pretty close.

Saquon, even though he had a bad week, still had a really decent target share and rushing share.

Alvin Kamara led the way in target share amongst all RBs by a mile.

Hope you guys enjoyed this post, good luck with your season and hopefully you started the season 1-0!