FantasyCalc API Intro with Python
Guest post from Josh Cordell at FantasyCalc showing users how to interact with their trade value calculator API!
FantasyCalc.com Intro
Hey FDP readers! I'm Josh from FantasyCalc.com. I've learned Python, R, Angular, SQL, AWS, and a whole lot more working on my fantasy football website over the past few years, so I'm excited to have the opportunity to collaborate by guest writing an article here.
FantasyCalc uses an algorithm to calculate player trade value from almost 1 million real fantasy football trades. In this article, we're going to compare those values to ADP to find over/undervalued players.
What do I need to know?
You should be familiar with lists, maps, and for loops from the first three intro to python articles. In this project, we'll cover APIs and JSON, and how we can combine multiple data sources for data analysis.
Application Program Interface (API) are how websites interact with backend databases and servers to get data. The APIs we're going to use return data in the JSON format - a common human readable response format consisting of strings, numbers, maps and lists. We're going to use two in this article:
FantasyCalc.com's player value API
FantasyFootballCalculator's ADP API
If you click on the FantasyCalc link, you'll see what JSON data looks like. Websites use HTML and CSS to turn JSON data into something that looks much prettier for human consumption. For example, the FantasyCalc API is the exact same API that powers the rankings.
Let's get started!
First, we'll want to import the data from the external APIs. We can do this using the requests library. Let's import it and tell Python to expect JSON data.
import requests
trade_values = requests.get("https://api.fantasycalc.com/values/current?isDynasty=false&numQbs=1&numTeams=12&ppr=1").json()
adp = requests.get("https://fantasyfootballcalculator.com/api/v1/adp/standard?teams=12&year=2023").json()
trade_values[0]
{'player': {'id': 7569,
'name': 'Justin Jefferson',
'mflId': '14836',
'sleeperId': '6794',
'position': 'WR',
'maybeBirthday': '1999-06-16',
'maybeHeight': '73',
'maybeWeight': 195,
'maybeCollege': 'LSU',
'maybeTeam': 'MIN',
'maybeAge': 24.082668278253426,
'maybeYoe': 3},
'value': 10726,
'overallRank': 1,
'positionRank': 1,
'trend30Day': -144,
'redraftDynastyValueDifference': 0,
'redraftDynastyValuePercDifference': 0,
'redraftValue': 10726,
'combinedValue': 21452,
'maybeMovingStandardDeviation': 3,
'maybeMovingStandardDeviationPerc': 0,
'maybeMovingStandardDeviationAdjusted': 2,
'displayTrend': False,
'maybeOwner': None,
'starter': False}
More on APIs
We use a combination of path and query parameters to tell the server exactly what data we want. APIs are manually defined and will usually host documentation for how to use them. This is is too large of a topic to cover in this article, so here's an article if you'd like to learn a little more.
For now, we'll move on with our data imported.
Researching the data
We want to compare a player's ADP to their trade value. We're using two different sources with different response formats, so we'll need to figure out how we can compare them. Let's take a deeper look into the response JSON from both sites.
You can easily visualize the JSON responses in a tool like https://jsonviewer.stack.hu/.
Looking at FantasyCalc.com's player value API, we'll notice:
Now, looking at FantasyFootballCalculator's ADP API, we'll notice:
So for each player, we'll want to compare FantasyCalc's "overallRank" to FFC's "adp".
Reformatting the data
Now that we know which values on the JSON response we want to compare, we can reformat each source into the same format. We'll want to be able to lookup a player's ADP or trade value from their name, so we'll use the Map data structure.
adp_map = {}
for player in adp['players']:
adp_map[player['name']] = player['adp']
trade_values_map = {}
for player in trade_values:
trade_values_map[player['player']['name']] = player['overallRank']
print('ADP map: ', adp_map)
print('Trade value map: ', trade_values_map)
ADP map: {'Christian McCaffrey': 1.3, 'Austin Ekeler': 2.0, 'Jonathan Taylor': 2.7, 'Justin Jefferson': 3.7, 'Saquon Barkley': 3.9, "Ja'Marr Chase": 6.4, 'Kenneth Walker III': 6.8, 'Nick Chubb': 7.8, 'Josh Jacobs': 7.9, 'Travis Kelce': 9.5, 'Derrick Henry': 9.7, 'Tony Pollard': 11.9, 'Travis Etienne': 12.3, 'Tyreek Hill': 12.9, 'Cooper Kupp': 13.8, 'Breece Hall': 15.6, 'Davante Adams': 16.3, 'Bijan Robinson': 17.4, 'CeeDee Lamb': 17.7, 'Stefon Diggs': 18.1, 'Najee Harris': 19.0, 'A.J. Brown': 19.2, 'George Kittle': 23.8, 'Jaylen Waddle': 23.8, 'Mark Andrews': 24.5, 'Dalvin Cook': 24.7, 'Rhamondre Stevenson': 25.4, 'Amon-Ra St. Brown': 26.3, 'Garrett Wilson': 28.1, 'Tee Higgins': 29.0, 'J.K. Dobbins': 29.6, 'Josh Allen': 29.8, 'Patrick Mahomes': 30.8, 'Chris Olave': 31.6, 'DeVonta Smith': 31.7, 'Aaron Jones': 33.1, 'Calvin Ridley': 34.3, 'Deebo Samuel': 37.0, 'Cam Akers': 38.6, 'D.K. Metcalf': 38.9, 'Amari Cooper': 39.5, 'T.J. Hockenson': 39.9, 'Jalen Hurts': 41.0, 'Miles Sanders': 41.2, 'Christian Watson': 41.8, 'Dameon Pierce': 42.4, 'D.J. Moore': 43.3, 'Joe Burrow': 47.0, 'Keenan Allen': 47.2, 'Kyle Pitts': 47.7, 'Terry McLaurin': 47.7, "D'Andre Swift": 48.7, 'David Montgomery': 48.9, 'Joe Mixon': 50.4, 'Mike Williams': 52.4, 'Jerry Jeudy': 53.4, 'Isiah Pacheco': 54.2, 'Tyler Lockett': 56.0, 'Justin Fields': 56.2, 'Dallas Goedert': 58.4, 'DeAndre Hopkins': 59.3, 'Lamar Jackson': 60.0, 'Tyler Allgeier': 60.1, 'Jameson Williams': 60.6, 'Drake London': 62.0, 'James Conner': 62.4, 'Darren Waller': 62.5, 'Justin Herbert': 65.6, 'Mike Evans': 66.0, 'Brandon Aiyuk': 68.0, 'Christian Kirk': 68.7, 'Brian Robinson Jr.': 70.1, 'Trevor Lawrence': 70.3, 'Chris Godwin': 71.2, 'Alvin Kamara': 71.5, 'Javonte Williams': 73.0, 'Jamaal Williams': 75.3, 'George Pickens': 75.6, 'Jahan Dotson': 75.7, 'Michael Pittman Jr.': 76.2, 'Dak Prescott': 77.0, 'A.J. Dillon': 78.6, 'Rashaad Penny': 78.9, 'Rashod Bateman': 79.9, 'Pat Freiermuth': 81.9, 'Treylon Burks': 83.8, 'James Cook': 84.5, 'Marquise Brown': 84.9, 'Gabriel Davis': 85.1, 'Rachaad White': 85.3, 'Evan Engram': 86.6, 'Deshaun Watson': 87.5, 'Kadarius Toney': 88.6, 'Courtland Sutton': 90.0, 'Kirk Cousins': 91.4, 'David Njoku': 92.3, 'Damien Harris': 93.1, 'Alexander Mattison': 93.3, 'Tua Tagovailoa': 94.5, 'Diontae Johnson': 94.7, 'Daniel Jones': 95.6, 'Donta Foreman': 98.4, 'Elijah Mitchell': 99.6, 'Brandin Cooks': 100.7, 'Jakobi Meyers': 101.2, 'Antonio Gibson': 103.2, 'Michael Thomas': 104.9, 'JuJu Smith-Schuster': 105.1, 'Geno Smith': 106.6, 'Jared Goff': 107.6, 'Aaron Rodgers': 107.9, 'Cole Kmet': 109.0, 'Darnell Mooney': 110.5, 'Ezekiel Elliott': 110.6, 'Jahmyr Gibbs': 112.6, 'Kenneth Gainwell': 113.8, 'Raheem Mostert': 114.1, 'Dalton Schultz': 114.4, 'Elijah Moore': 114.6, 'Russell Wilson': 115.0, 'Devin Singletary': 116.1, 'Dawson Knox': 117.1, 'Allen Lazard': 118.7, 'Samaje Perine': 119.1, 'San Francisco Defense': 120.8, 'Donovan Peoples-Jones': 121.3, 'Cordarrelle Patterson': 121.5, 'Zay Jones': 121.5, 'Tyler Boyd': 121.7, 'Kareem Hunt': 123.8, 'Nico Collins': 123.8, 'Chigoziem Okonkwo': 123.8, 'Michael Mayer': 123.9, 'Greg Dulcich': 124.0, 'Jerick McKinnon': 124.7, 'Buffalo Defense': 125.9, 'Dallas Defense': 128.2, 'Adam Thielen': 129.3, 'Derek Carr': 130.8, 'Leonard Fournette': 132.4, 'Chuba Hubbard': 132.8, 'Rondale Moore': 134.7, 'Taysom Hill': 135.1, 'Justin Tucker': 136.3, 'Jaxon Smith-Njigba': 136.4, 'Denver Defense': 137.6, 'Philadelphia Defense': 138.0, 'Tyler Bass': 140.2, 'Trey Lance': 140.5, 'Dalton Kincaid': 140.8, 'John Metchie III': 141.2, 'Kyler Murray': 142.2, 'Matthew Stafford': 142.8, 'New England Defense': 143.4, 'Harrison Butker': 143.5, 'Daniel Carlson': 143.5, 'Tampa Bay Defense': 143.8, 'Clyde Edwards-Helaire': 144.1, 'Kenny Pickett': 144.3, 'Quentin Johnston': 144.4, 'Jaylen Warren': 144.4, 'Gerald Everett': 145.0, 'Zach Ertz': 145.9, 'Zach Charbonnet': 146.1, 'Baltimore Defense': 146.3, 'Jordan Addison': 146.9, 'Zamir White': 147.2, 'Mike Gesicki': 147.3, 'Anthony Richardson': 147.7, 'Zay Flowers': 150.2, 'Skyy Moore': 150.6, 'Michael Gallup': 151.4, 'Kansas City Defense': 153.3, "Wan'Dale Robinson": 154.6, 'Nick Folk': 155.8, 'Younghoe Koo': 156.1, 'Gus Edwards': 156.8, 'Romeo Doubs': 157.8, 'Jimmy Garoppolo': 157.9, 'Alec Pierce': 158.0, 'Sean Tucker': 158.3, 'Jordan Love': 158.9, 'Michael Carter': 159.3, 'Tyler Higbee': 159.4, 'Pittsburgh Defense': 159.4, 'James Robinson': 160.4, 'New Orleans Defense': 160.5, 'Devon Achane': 160.8, 'Miami Defense': 161.0, 'Hunter Renfrow': 161.7, 'Jason Sanders': 161.9, 'Jerome Ford': 162.8, 'Cincinnati Defense': 162.9, 'Brock Purdy': 163.3, 'K.J. Osborn': 163.6, 'Brandon McManus': 167.7, 'Matt Gay': 169.3, 'Mecole Hardman': 169.6, 'Graham Gano': 171.9, 'Wil Lutz': 172.6, 'Jake Elliott': 173.7, 'Jason Myers': 174.5, 'Greg Joseph': 176.2}
Trade value map: {'Justin Jefferson': 1, 'Christian McCaffrey': 2, "Ja'Marr Chase": 3, 'Bijan Robinson': 4, 'Cooper Kupp': 5, 'Austin Ekeler': 6, 'Travis Kelce': 7, 'A.J. Brown': 8, 'Jonathan Taylor': 9, 'CeeDee Lamb': 10, 'Nick Chubb': 11, 'Patrick Mahomes': 12, 'Saquon Barkley': 13, 'Stefon Diggs': 14, 'Tyreek Hill': 15, 'Derrick Henry': 16, 'Josh Jacobs': 17, 'Garrett Wilson': 18, 'Jaylen Waddle': 19, 'Josh Allen': 20, 'Tony Pollard': 21, 'Davante Adams': 22, 'Amon-Ra St. Brown': 23, 'Breece Hall': 24, 'Rhamondre Stevenson': 25, 'Jalen Hurts': 26, 'Chris Olave': 27, 'Travis Etienne': 28, 'DK Metcalf': 29, 'Jahmyr Gibbs': 30, 'Tee Higgins': 31, 'Kenneth Walker': 32, 'Mark Andrews': 33, 'Najee Harris': 34, 'Miles Sanders': 35, 'DeVonta Smith': 36, 'Joe Burrow': 37, 'Deebo Samuel': 38, 'Lamar Jackson': 39, 'Trevor Lawrence': 40, 'Joe Mixon': 41, 'Aaron Jones': 42, 'Justin Herbert': 43, 'DJ Moore': 44, 'Terry McLaurin': 45, 'J.K. Dobbins': 46, 'Dalvin Cook': 47, 'Calvin Ridley': 48, 'Alvin Kamara': 49, "D'Andre Swift": 50, 'Justin Fields': 51, 'Javonte Williams': 52, 'Drake London': 53, 'Brandon Aiyuk': 54, 'Chris Godwin': 55, 'Amari Cooper': 56, 'DeAndre Hopkins': 57, 'Keenan Allen': 58, 'George Kittle': 59, 'David Montgomery': 60, 'Jerry Jeudy': 61, 'Michael Pittman': 62, 'Jaxon Smith-Njigba': 63, 'Cam Akers': 64, 'Dameon Pierce': 65, 'Diontae Johnson': 66, 'Rachaad White': 67, 'Deshaun Watson': 68, 'James Conner': 69, 'Christian Watson': 70, 'Christian Kirk': 71, 'Marquise Brown': 72, 'Mike Evans': 73, 'Alexander Mattison': 74, 'Treylon Burks': 75, 'Anthony Richardson': 76, 'Jahan Dotson': 77, 'T.J. Hockenson': 78, 'Dallas Goedert': 79, 'Darren Waller': 80, 'Mike Williams': 81, 'Zach Charbonnet': 82, 'Jameson Williams': 83, 'Quentin Johnston': 84, 'Tyler Lockett': 85, 'Jordan Addison': 86, 'Bryce Young': 87, 'Zay Flowers': 88, 'Kyler Murray': 89, 'Kyle Pitts': 90, 'Antonio Gibson': 91, 'Devon Achane': 92, 'AJ Dillon': 93, 'Samaje Perine': 94, 'Dak Prescott': 95, 'James Cook': 96, 'Isiah Pacheco': 97, 'Rashaad Penny': 98, 'George Pickens': 99, 'Jamaal Williams': 100, 'Khalil Herbert': 101, 'Jerick McKinnon': 102, 'Tua Tagovailoa': 103, 'C.J. Stroud': 104, 'Ezekiel Elliott': 105, 'Daniel Jones': 106, 'Michael Thomas': 107, 'Kadarius Toney': 108, 'Brian Robinson': 109, 'Odell Beckham': 110, 'Courtland Sutton': 111, 'Brandin Cooks': 112, 'Elijah Mitchell': 113, 'Dalton Kincaid': 114, 'Damien Harris': 115, 'Rashod Bateman': 116, 'JuJu Smith-Schuster': 117, 'Kendre Miller': 118, 'Devin Singletary': 119, 'Tyler Allgeier': 120, 'Allen Lazard': 121, 'Gabe Davis': 122, 'Jakobi Meyers': 123, 'Skyy Moore': 124, 'Jared Goff': 125, 'Evan Engram': 126, 'Roschon Johnson': 127, 'Elijah Moore': 128, 'Aaron Rodgers': 129, 'Adam Thielen': 130, 'Kirk Cousins': 131, 'Russell Wilson': 132, 'Jaylen Warren': 133, 'Tank Bigsby': 134, 'Jonathan Mingo': 135, 'Jordan Love': 136, "D'Onta Foreman": 137, 'David Njoku': 138, 'Kareem Hunt': 139, 'Darnell Mooney': 140}
Comparing the data
Now we have both data sources in the same format, we can easily compare the two. Let's loop over the trades values, and use the name key to get that player's trade value, and print the result.
Note the trade values might have some different players than ADP. If we have a player in the trade values that does not have ADP data, we'll just skip them.
for name, player_trade_value in trade_values_map.items():
player_adp = adp_map.get(name)
# Skip players without ADP data
if player_adp is None:
continue
diff = player_trade_value - player_adp
print(name, player_trade_value, player_adp, diff)
Justin Jefferson 1 3.7 -2.7
Christian McCaffrey 2 1.3 0.7
Ja'Marr Chase 3 6.4 -3.4000000000000004
Bijan Robinson 4 17.4 -13.399999999999999
Cooper Kupp 5 13.8 -8.8
Austin Ekeler 6 2.0 4.0
Travis Kelce 7 9.5 -2.5
A.J. Brown 8 19.2 -11.2
Jonathan Taylor 9 2.7 6.3
CeeDee Lamb 10 17.7 -7.699999999999999
Nick Chubb 11 7.8 3.2
Patrick Mahomes 12 30.8 -18.8
Saquon Barkley 13 3.9 9.1
Stefon Diggs 14 18.1 -4.100000000000001
Tyreek Hill 15 12.9 2.0999999999999996
Derrick Henry 16 9.7 6.300000000000001
Josh Jacobs 17 7.9 9.1
Garrett Wilson 18 28.1 -10.100000000000001
Jaylen Waddle 19 23.8 -4.800000000000001
Josh Allen 20 29.8 -9.8
Tony Pollard 21 11.9 9.1
Davante Adams 22 16.3 5.699999999999999
Amon-Ra St. Brown 23 26.3 -3.3000000000000007
Breece Hall 24 15.6 8.4
Rhamondre Stevenson 25 25.4 -0.3999999999999986
Jalen Hurts 26 41.0 -15.0
Chris Olave 27 31.6 -4.600000000000001
Travis Etienne 28 12.3 15.7
Jahmyr Gibbs 30 112.6 -82.6
Tee Higgins 31 29.0 2.0
Mark Andrews 33 24.5 8.5
Najee Harris 34 19.0 15.0
Miles Sanders 35 41.2 -6.200000000000003
DeVonta Smith 36 31.7 4.300000000000001
Joe Burrow 37 47.0 -10.0
Deebo Samuel 38 37.0 1.0
Lamar Jackson 39 60.0 -21.0
Trevor Lawrence 40 70.3 -30.299999999999997
Joe Mixon 41 50.4 -9.399999999999999
Aaron Jones 42 33.1 8.899999999999999
Justin Herbert 43 65.6 -22.599999999999994
Terry McLaurin 45 47.7 -2.700000000000003
J.K. Dobbins 46 29.6 16.4
Dalvin Cook 47 24.7 22.3
Calvin Ridley 48 34.3 13.700000000000003
Alvin Kamara 49 71.5 -22.5
D'Andre Swift 50 48.7 1.2999999999999972
Justin Fields 51 56.2 -5.200000000000003
Javonte Williams 52 73.0 -21.0
Drake London 53 62.0 -9.0
Brandon Aiyuk 54 68.0 -14.0
Chris Godwin 55 71.2 -16.200000000000003
Amari Cooper 56 39.5 16.5
DeAndre Hopkins 57 59.3 -2.299999999999997
Keenan Allen 58 47.2 10.799999999999997
George Kittle 59 23.8 35.2
David Montgomery 60 48.9 11.100000000000001
Jerry Jeudy 61 53.4 7.600000000000001
Jaxon Smith-Njigba 63 136.4 -73.4
Cam Akers 64 38.6 25.4
Dameon Pierce 65 42.4 22.6
Diontae Johnson 66 94.7 -28.700000000000003
Rachaad White 67 85.3 -18.299999999999997
Deshaun Watson 68 87.5 -19.5
James Conner 69 62.4 6.600000000000001
Christian Watson 70 41.8 28.200000000000003
Christian Kirk 71 68.7 2.299999999999997
Marquise Brown 72 84.9 -12.900000000000006
Mike Evans 73 66.0 7.0
Alexander Mattison 74 93.3 -19.299999999999997
Treylon Burks 75 83.8 -8.799999999999997
Anthony Richardson 76 147.7 -71.69999999999999
Jahan Dotson 77 75.7 1.2999999999999972
T.J. Hockenson 78 39.9 38.1
Dallas Goedert 79 58.4 20.6
Darren Waller 80 62.5 17.5
Mike Williams 81 52.4 28.6
Zach Charbonnet 82 146.1 -64.1
Jameson Williams 83 60.6 22.4
Quentin Johnston 84 144.4 -60.400000000000006
Tyler Lockett 85 56.0 29.0
Jordan Addison 86 146.9 -60.900000000000006
Zay Flowers 88 150.2 -62.19999999999999
Kyler Murray 89 142.2 -53.19999999999999
Kyle Pitts 90 47.7 42.3
Antonio Gibson 91 103.2 -12.200000000000003
Devon Achane 92 160.8 -68.80000000000001
Samaje Perine 94 119.1 -25.099999999999994
Dak Prescott 95 77.0 18.0
James Cook 96 84.5 11.5
Isiah Pacheco 97 54.2 42.8
Rashaad Penny 98 78.9 19.099999999999994
George Pickens 99 75.6 23.400000000000006
Jamaal Williams 100 75.3 24.700000000000003
Jerick McKinnon 102 124.7 -22.700000000000003
Tua Tagovailoa 103 94.5 8.5
Ezekiel Elliott 105 110.6 -5.599999999999994
Daniel Jones 106 95.6 10.400000000000006
Michael Thomas 107 104.9 2.0999999999999943
Kadarius Toney 108 88.6 19.400000000000006
Courtland Sutton 111 90.0 21.0
Brandin Cooks 112 100.7 11.299999999999997
Elijah Mitchell 113 99.6 13.400000000000006
Dalton Kincaid 114 140.8 -26.80000000000001
Damien Harris 115 93.1 21.900000000000006
Rashod Bateman 116 79.9 36.099999999999994
JuJu Smith-Schuster 117 105.1 11.900000000000006
Devin Singletary 119 116.1 2.9000000000000057
Tyler Allgeier 120 60.1 59.9
Allen Lazard 121 118.7 2.299999999999997
Jakobi Meyers 123 101.2 21.799999999999997
Skyy Moore 124 150.6 -26.599999999999994
Jared Goff 125 107.6 17.400000000000006
Evan Engram 126 86.6 39.400000000000006
Elijah Moore 128 114.6 13.400000000000006
Aaron Rodgers 129 107.9 21.099999999999994
Adam Thielen 130 129.3 0.6999999999999886
Kirk Cousins 131 91.4 39.599999999999994
Russell Wilson 132 115.0 17.0
Jaylen Warren 133 144.4 -11.400000000000006
Jordan Love 136 158.9 -22.900000000000006
David Njoku 138 92.3 45.7
Kareem Hunt 139 123.8 15.200000000000003
Darnell Mooney 140 110.5 29.5
Formatting our results
Now we have the comparison data between ADP and trade value! We'll want to sort it though, so the results show our top over/undervalued players.
Instead of printing each row, let's add them to a list and sort the list at the end.
diffs = []
for name, player_trade_value in trade_values_map.items():
player_adp = adp_map.get(name)
# Skip players without ADP data
if player_adp is None:
continue
diff = player_trade_value - player_adp
diffs.append([name, player_trade_value, player_adp, diff])
# Use a lambda to sort by the 'diff' we defined above.
# d[3] is sorting by the 4th element of the list since lists are indexed started from zero.
sorted_diffs = sorted(diffs, key=lambda d: d[3])
for diff in sorted_diffs:
print(diff)
['Jahmyr Gibbs', 30, 112.6, -82.6]
['Jaxon Smith-Njigba', 63, 136.4, -73.4]
['Anthony Richardson', 76, 147.7, -71.69999999999999]
['Devon Achane', 92, 160.8, -68.80000000000001]
['Zach Charbonnet', 82, 146.1, -64.1]
['Zay Flowers', 88, 150.2, -62.19999999999999]
['Jordan Addison', 86, 146.9, -60.900000000000006]
['Quentin Johnston', 84, 144.4, -60.400000000000006]
['Kyler Murray', 89, 142.2, -53.19999999999999]
['Trevor Lawrence', 40, 70.3, -30.299999999999997]
['Diontae Johnson', 66, 94.7, -28.700000000000003]
['Dalton Kincaid', 114, 140.8, -26.80000000000001]
['Skyy Moore', 124, 150.6, -26.599999999999994]
['Samaje Perine', 94, 119.1, -25.099999999999994]
['Jordan Love', 136, 158.9, -22.900000000000006]
['Jerick McKinnon', 102, 124.7, -22.700000000000003]
['Justin Herbert', 43, 65.6, -22.599999999999994]
['Alvin Kamara', 49, 71.5, -22.5]
['Lamar Jackson', 39, 60.0, -21.0]
['Javonte Williams', 52, 73.0, -21.0]
['Deshaun Watson', 68, 87.5, -19.5]
['Alexander Mattison', 74, 93.3, -19.299999999999997]
['Patrick Mahomes', 12, 30.8, -18.8]
['Rachaad White', 67, 85.3, -18.299999999999997]
['Chris Godwin', 55, 71.2, -16.200000000000003]
['Jalen Hurts', 26, 41.0, -15.0]
['Brandon Aiyuk', 54, 68.0, -14.0]
['Bijan Robinson', 4, 17.4, -13.399999999999999]
['Marquise Brown', 72, 84.9, -12.900000000000006]
['Antonio Gibson', 91, 103.2, -12.200000000000003]
['Jaylen Warren', 133, 144.4, -11.400000000000006]
['A.J. Brown', 8, 19.2, -11.2]
['Garrett Wilson', 18, 28.1, -10.100000000000001]
['Joe Burrow', 37, 47.0, -10.0]
['Josh Allen', 20, 29.8, -9.8]
['Joe Mixon', 41, 50.4, -9.399999999999999]
['Drake London', 53, 62.0, -9.0]
['Cooper Kupp', 5, 13.8, -8.8]
['Treylon Burks', 75, 83.8, -8.799999999999997]
['CeeDee Lamb', 10, 17.7, -7.699999999999999]
['Miles Sanders', 35, 41.2, -6.200000000000003]
['Ezekiel Elliott', 105, 110.6, -5.599999999999994]
['Justin Fields', 51, 56.2, -5.200000000000003]
['Jaylen Waddle', 19, 23.8, -4.800000000000001]
['Chris Olave', 27, 31.6, -4.600000000000001]
['Stefon Diggs', 14, 18.1, -4.100000000000001]
["Ja'Marr Chase", 3, 6.4, -3.4000000000000004]
['Amon-Ra St. Brown', 23, 26.3, -3.3000000000000007]
['Terry McLaurin', 45, 47.7, -2.700000000000003]
['Justin Jefferson', 1, 3.7, -2.7]
['Travis Kelce', 7, 9.5, -2.5]
['DeAndre Hopkins', 57, 59.3, -2.299999999999997]
['Rhamondre Stevenson', 25, 25.4, -0.3999999999999986]
['Adam Thielen', 130, 129.3, 0.6999999999999886]
['Christian McCaffrey', 2, 1.3, 0.7]
['Deebo Samuel', 38, 37.0, 1.0]
["D'Andre Swift", 50, 48.7, 1.2999999999999972]
['Jahan Dotson', 77, 75.7, 1.2999999999999972]
['Tee Higgins', 31, 29.0, 2.0]
['Michael Thomas', 107, 104.9, 2.0999999999999943]
['Tyreek Hill', 15, 12.9, 2.0999999999999996]
['Christian Kirk', 71, 68.7, 2.299999999999997]
['Allen Lazard', 121, 118.7, 2.299999999999997]
['Devin Singletary', 119, 116.1, 2.9000000000000057]
['Nick Chubb', 11, 7.8, 3.2]
['Austin Ekeler', 6, 2.0, 4.0]
['DeVonta Smith', 36, 31.7, 4.300000000000001]
['Davante Adams', 22, 16.3, 5.699999999999999]
['Jonathan Taylor', 9, 2.7, 6.3]
['Derrick Henry', 16, 9.7, 6.300000000000001]
['James Conner', 69, 62.4, 6.600000000000001]
['Mike Evans', 73, 66.0, 7.0]
['Jerry Jeudy', 61, 53.4, 7.600000000000001]
['Breece Hall', 24, 15.6, 8.4]
['Mark Andrews', 33, 24.5, 8.5]
['Tua Tagovailoa', 103, 94.5, 8.5]
['Aaron Jones', 42, 33.1, 8.899999999999999]
['Saquon Barkley', 13, 3.9, 9.1]
['Josh Jacobs', 17, 7.9, 9.1]
['Tony Pollard', 21, 11.9, 9.1]
['Daniel Jones', 106, 95.6, 10.400000000000006]
['Keenan Allen', 58, 47.2, 10.799999999999997]
['David Montgomery', 60, 48.9, 11.100000000000001]
['Brandin Cooks', 112, 100.7, 11.299999999999997]
['James Cook', 96, 84.5, 11.5]
['JuJu Smith-Schuster', 117, 105.1, 11.900000000000006]
['Elijah Mitchell', 113, 99.6, 13.400000000000006]
['Elijah Moore', 128, 114.6, 13.400000000000006]
['Calvin Ridley', 48, 34.3, 13.700000000000003]
['Najee Harris', 34, 19.0, 15.0]
['Kareem Hunt', 139, 123.8, 15.200000000000003]
['Travis Etienne', 28, 12.3, 15.7]
['J.K. Dobbins', 46, 29.6, 16.4]
['Amari Cooper', 56, 39.5, 16.5]
['Russell Wilson', 132, 115.0, 17.0]
['Jared Goff', 125, 107.6, 17.400000000000006]
['Darren Waller', 80, 62.5, 17.5]
['Dak Prescott', 95, 77.0, 18.0]
['Rashaad Penny', 98, 78.9, 19.099999999999994]
['Kadarius Toney', 108, 88.6, 19.400000000000006]
['Dallas Goedert', 79, 58.4, 20.6]
['Courtland Sutton', 111, 90.0, 21.0]
['Aaron Rodgers', 129, 107.9, 21.099999999999994]
['Jakobi Meyers', 123, 101.2, 21.799999999999997]
['Damien Harris', 115, 93.1, 21.900000000000006]
['Dalvin Cook', 47, 24.7, 22.3]
['Jameson Williams', 83, 60.6, 22.4]
['Dameon Pierce', 65, 42.4, 22.6]
['George Pickens', 99, 75.6, 23.400000000000006]
['Jamaal Williams', 100, 75.3, 24.700000000000003]
['Cam Akers', 64, 38.6, 25.4]
['Christian Watson', 70, 41.8, 28.200000000000003]
['Mike Williams', 81, 52.4, 28.6]
['Tyler Lockett', 85, 56.0, 29.0]
['Darnell Mooney', 140, 110.5, 29.5]
['George Kittle', 59, 23.8, 35.2]
['Rashod Bateman', 116, 79.9, 36.099999999999994]
['T.J. Hockenson', 78, 39.9, 38.1]
['Evan Engram', 126, 86.6, 39.400000000000006]
['Kirk Cousins', 131, 91.4, 39.599999999999994]
['Kyle Pitts', 90, 47.7, 42.3]
['Isiah Pacheco', 97, 54.2, 42.8]
['David Njoku', 138, 92.3, 45.7]
['Tyler Allgeier', 120, 60.1, 59.9]
We can now use pandas , Python's data manipulation library, to format our data as a table for better readability.
import pandas as pd
df = pd.DataFrame(sorted_diffs, columns=['name', 'trade_value_rank', 'adp', 'tv - adp'])
with pd.option_context('display.max_rows', None):
display(df[:10])
name | trade_value_rank | adp | tv - adp | |
---|---|---|---|---|
0 | Jahmyr Gibbs | 30 | 112.6 | -82.6 |
1 | Jaxon Smith-Njigba | 63 | 136.4 | -73.4 |
2 | Anthony Richardson | 76 | 147.7 | -71.7 |
3 | Devon Achane | 92 | 160.8 | -68.8 |
4 | Zach Charbonnet | 82 | 146.1 | -64.1 |
5 | Zay Flowers | 88 | 150.2 | -62.2 |
6 | Jordan Addison | 86 | 146.9 | -60.9 |
7 | Quentin Johnston | 84 | 144.4 | -60.4 |
8 | Kyler Murray | 89 | 142.2 | -53.2 |
9 | Trevor Lawrence | 40 | 70.3 | -30.3 |
10 | Diontae Johnson | 66 | 94.7 | -28.7 |
11 | Dalton Kincaid | 114 | 140.8 | -26.8 |
12 | Skyy Moore | 124 | 150.6 | -26.6 |
13 | Samaje Perine | 94 | 119.1 | -25.1 |
14 | Jordan Love | 136 | 158.9 | -22.9 |
15 | Jerick McKinnon | 102 | 124.7 | -22.7 |
16 | Justin Herbert | 43 | 65.6 | -22.6 |
17 | Alvin Kamara | 49 | 71.5 | -22.5 |
18 | Lamar Jackson | 39 | 60.0 | -21.0 |
19 | Javonte Williams | 52 | 73.0 | -21.0 |
20 | Deshaun Watson | 68 | 87.5 | -19.5 |
21 | Alexander Mattison | 74 | 93.3 | -19.3 |
22 | Patrick Mahomes | 12 | 30.8 | -18.8 |
23 | Rachaad White | 67 | 85.3 | -18.3 |
24 | Chris Godwin | 55 | 71.2 | -16.2 |
25 | Jalen Hurts | 26 | 41.0 | -15.0 |
26 | Brandon Aiyuk | 54 | 68.0 | -14.0 |
27 | Bijan Robinson | 4 | 17.4 | -13.4 |
28 | Marquise Brown | 72 | 84.9 | -12.9 |
29 | Antonio Gibson | 91 | 103.2 | -12.2 |
30 | Jaylen Warren | 133 | 144.4 | -11.4 |
31 | A.J. Brown | 8 | 19.2 | -11.2 |
32 | Garrett Wilson | 18 | 28.1 | -10.1 |
33 | Joe Burrow | 37 | 47.0 | -10.0 |
34 | Josh Allen | 20 | 29.8 | -9.8 |
35 | Joe Mixon | 41 | 50.4 | -9.4 |
36 | Drake London | 53 | 62.0 | -9.0 |
37 | Cooper Kupp | 5 | 13.8 | -8.8 |
38 | Treylon Burks | 75 | 83.8 | -8.8 |
39 | CeeDee Lamb | 10 | 17.7 | -7.7 |
40 | Miles Sanders | 35 | 41.2 | -6.2 |
41 | Ezekiel Elliott | 105 | 110.6 | -5.6 |
42 | Justin Fields | 51 | 56.2 | -5.2 |
43 | Jaylen Waddle | 19 | 23.8 | -4.8 |
44 | Chris Olave | 27 | 31.6 | -4.6 |
45 | Stefon Diggs | 14 | 18.1 | -4.1 |
46 | Ja'Marr Chase | 3 | 6.4 | -3.4 |
47 | Amon-Ra St. Brown | 23 | 26.3 | -3.3 |
48 | Terry McLaurin | 45 | 47.7 | -2.7 |
49 | Justin Jefferson | 1 | 3.7 | -2.7 |
50 | Travis Kelce | 7 | 9.5 | -2.5 |
51 | DeAndre Hopkins | 57 | 59.3 | -2.3 |
52 | Rhamondre Stevenson | 25 | 25.4 | -0.4 |
53 | Adam Thielen | 130 | 129.3 | 0.7 |
54 | Christian McCaffrey | 2 | 1.3 | 0.7 |
55 | Deebo Samuel | 38 | 37.0 | 1.0 |
56 | D'Andre Swift | 50 | 48.7 | 1.3 |
57 | Jahan Dotson | 77 | 75.7 | 1.3 |
58 | Tee Higgins | 31 | 29.0 | 2.0 |
59 | Michael Thomas | 107 | 104.9 | 2.1 |
60 | Tyreek Hill | 15 | 12.9 | 2.1 |
61 | Christian Kirk | 71 | 68.7 | 2.3 |
62 | Allen Lazard | 121 | 118.7 | 2.3 |
63 | Devin Singletary | 119 | 116.1 | 2.9 |
64 | Nick Chubb | 11 | 7.8 | 3.2 |
65 | Austin Ekeler | 6 | 2.0 | 4.0 |
66 | DeVonta Smith | 36 | 31.7 | 4.3 |
67 | Davante Adams | 22 | 16.3 | 5.7 |
68 | Jonathan Taylor | 9 | 2.7 | 6.3 |
69 | Derrick Henry | 16 | 9.7 | 6.3 |
70 | James Conner | 69 | 62.4 | 6.6 |
71 | Mike Evans | 73 | 66.0 | 7.0 |
72 | Jerry Jeudy | 61 | 53.4 | 7.6 |
73 | Breece Hall | 24 | 15.6 | 8.4 |
74 | Mark Andrews | 33 | 24.5 | 8.5 |
75 | Tua Tagovailoa | 103 | 94.5 | 8.5 |
76 | Aaron Jones | 42 | 33.1 | 8.9 |
77 | Saquon Barkley | 13 | 3.9 | 9.1 |
78 | Josh Jacobs | 17 | 7.9 | 9.1 |
79 | Tony Pollard | 21 | 11.9 | 9.1 |
80 | Daniel Jones | 106 | 95.6 | 10.4 |
81 | Keenan Allen | 58 | 47.2 | 10.8 |
82 | David Montgomery | 60 | 48.9 | 11.1 |
83 | Brandin Cooks | 112 | 100.7 | 11.3 |
84 | James Cook | 96 | 84.5 | 11.5 |
85 | JuJu Smith-Schuster | 117 | 105.1 | 11.9 |
86 | Elijah Mitchell | 113 | 99.6 | 13.4 |
87 | Elijah Moore | 128 | 114.6 | 13.4 |
88 | Calvin Ridley | 48 | 34.3 | 13.7 |
89 | Najee Harris | 34 | 19.0 | 15.0 |
90 | Kareem Hunt | 139 | 123.8 | 15.2 |
91 | Travis Etienne | 28 | 12.3 | 15.7 |
92 | J.K. Dobbins | 46 | 29.6 | 16.4 |
93 | Amari Cooper | 56 | 39.5 | 16.5 |
94 | Russell Wilson | 132 | 115.0 | 17.0 |
95 | Jared Goff | 125 | 107.6 | 17.4 |
96 | Darren Waller | 80 | 62.5 | 17.5 |
97 | Dak Prescott | 95 | 77.0 | 18.0 |
98 | Rashaad Penny | 98 | 78.9 | 19.1 |
99 | Kadarius Toney | 108 | 88.6 | 19.4 |
100 | Dallas Goedert | 79 | 58.4 | 20.6 |
101 | Courtland Sutton | 111 | 90.0 | 21.0 |
102 | Aaron Rodgers | 129 | 107.9 | 21.1 |
103 | Jakobi Meyers | 123 | 101.2 | 21.8 |
104 | Damien Harris | 115 | 93.1 | 21.9 |
105 | Dalvin Cook | 47 | 24.7 | 22.3 |
106 | Jameson Williams | 83 | 60.6 | 22.4 |
107 | Dameon Pierce | 65 | 42.4 | 22.6 |
108 | George Pickens | 99 | 75.6 | 23.4 |
109 | Jamaal Williams | 100 | 75.3 | 24.7 |
110 | Cam Akers | 64 | 38.6 | 25.4 |
111 | Christian Watson | 70 | 41.8 | 28.2 |
112 | Mike Williams | 81 | 52.4 | 28.6 |
113 | Tyler Lockett | 85 | 56.0 | 29.0 |
114 | Darnell Mooney | 140 | 110.5 | 29.5 |
115 | George Kittle | 59 | 23.8 | 35.2 |
116 | Rashod Bateman | 116 | 79.9 | 36.1 |
117 | T.J. Hockenson | 78 | 39.9 | 38.1 |
118 | Evan Engram | 126 | 86.6 | 39.4 |
119 | Kirk Cousins | 131 | 91.4 | 39.6 |
120 | Kyle Pitts | 90 | 47.7 | 42.3 |
121 | Isiah Pacheco | 97 | 54.2 | 42.8 |
122 | David Njoku | 138 | 92.3 | 45.7 |
123 | Tyler Allgeier | 120 | 60.1 | 59.9 |
Challenge yourself
Concluding thoughts
Fetching, reformatting, and comparing multiple data sources is a very common programming task. I'm excited I got the opportunity to teach these concepts with an example using fantasy football data. I've spent thousands of hours learning Python, web development, infrastructure, and more on my own fantasy football projects, and have got plenty of help from the fantasy community, so I'm happy to take this opportunity to collaborate to pay it forward.