cwendt94 / espn-api

ESPN Fantasy API! (Football, Basketball)
MIT License
544 stars 183 forks source link

Broken player stats #421

Closed cjwin2000 closed 1 year ago

cjwin2000 commented 1 year ago

Sport

Basketball

Summary

The stats dictionary from the player class seems to be broken. The code below uses a playerId (Luka Doncic) and prints the sorted list of games (keys) from the player's schedule and then from their stats. It then prints the intersection of these lists, which in theory should be identical lists of 82 games. I removed the final two entries from the stats due to those keys being for averages and predictions. The data from the schedule seems to be correct (82 games that line up with the Mavericks' schedule), but the data from the stats is inconsistent.

There are more than the proper 82 games listed. For example, even though the stats list '5' as a key, the Mavericks did not play on the fifth day of the season, and the schedule omits this key correctly. Also, the stats for the keys where the player did play are wrong sometimes. For example the output from the code below shows that in the first game of the season (key of 3), Doncic had 18 points and 29 fantasy points. In reality, he had 35 points and 40 fantasy points. Some of the records in the response don't even have the "total" key that should allow users to access fields like points and rebounds for specific games. The code snippet below actually fails eventually for this reason. Some of the values, however are correct. His most recent game (key 57) looks to be accurate. Any idea if this is something on my end or a bug with the API? I have included the output I am getting below the code. I should also mention this happens for multiple players, I am just using Doncic as an example.

Code:

from espn_api.basketball import League

my_year = 2023
my_league_id = PLACEHOLDER
toggle_debug = False

league = League(league_id=my_league_id, year=my_year, debug=toggle_debug)

# Luka Doncic
my_playerId = 3945274

# Luka Doncic player object
player = league.player_info(playerId=my_playerId)

sched = list(player.schedule.keys())
sched1 = [eval(i) for i in sched]
sched1.sort()
print("Player schedule keys\n", sched1)
print(len(sched1))

stats = list(player.stats.keys())
stats = stats[:-2]
stats1 = [eval(i) for i in stats]
stats1.sort()
print("Player stats keys\n", stats1)
print(len(stats1)) 

for game in sched1:
    if str(game) in stats:
        print("KEY: ", game, "\t", player.schedule[str(game)], "\t", player.stats[str(game)]['applied_total'], "\t", player.stats[str(game)]['total']['PTS'])

Output:

Player schedule keys
 [3, 6, 9, 11, 13, 14, 17, 19, 22, 24, 25, 27, 30, 31, 33, 35, 38, 41, 42, 44, 46, 48, 50, 51, 54, 55, 57, 59, 61, 62, 64, 66, 68, 70, 72, 74, 76, 78, 81, 83, 84, 86, 88, 90, 91, 94, 96, 98, 100, 102, 104, 106, 109, 111, 113, 115, 117, 118, 120, 122, 130, 133, 135, 137, 140, 142, 143, 146, 148, 150, 152, 155, 157, 159, 161, 162, 164, 167, 168, 171, 173, 175]
82
Player stats keys
 [3, 5, 6, 8, 9, 10, 11, 13, 14, 15, 16, 17, 19, 21, 22, 23, 24, 25, 27, 28, 30, 31, 32, 33, 34, 35, 36, 38, 40, 41, 42, 44, 46, 47, 48, 50, 51, 53, 54, 55, 56, 57, 58, 62, 64, 66, 68, 70, 72, 74, 76, 77, 79, 81, 83, 86, 88, 89, 91, 93, 94, 97, 99, 100, 103, 104, 107, 109, 111, 113, 115, 117, 120, 122, 130, 132, 134, 136, 138, 140, 142, 144, 146, 149, 151, 152, 154, 156, 158, 160, 162, 163, 165, 167, 170, 172, 174]
97
KEY:  3      {'team': 'PHO', 'date': datetime.datetime(2022, 10, 19, 22, 0)}     29.0    18.0
KEY:  6      {'team': 'MEM', 'date': datetime.datetime(2022, 10, 22, 20, 30)}    60.0    32.0
KEY:  9      {'team': 'NOP', 'date': datetime.datetime(2022, 10, 25, 19, 30)}    54.5    37.0
KEY:  11     {'team': 'BKN', 'date': datetime.datetime(2022, 10, 27, 19, 30)}    20.0    16.0
KEY:  13     {'team': 'OKC', 'date': datetime.datetime(2022, 10, 29, 21, 0)}     39.0    23.0
KEY:  14     {'team': 'ORL', 'date': datetime.datetime(2022, 10, 30, 19, 30)}    47.0    44.0
KEY:  17     {'team': 'UTA', 'date': datetime.datetime(2022, 11, 2, 20, 30)}     49.0    33.0
KEY:  19     {'team': 'TOR', 'date': datetime.datetime(2022, 11, 4, 20, 30)}     39.5    33.0
KEY:  22     {'team': 'BKN', 'date': datetime.datetime(2022, 11, 7, 21, 45)}     44.0    36.0
KEY:  24     {'team': 'ORL', 'date': datetime.datetime(2022, 11, 9, 17, 30)}     36.0    24.0
KEY:  25     {'team': 'WAS', 'date': datetime.datetime(2022, 11, 10, 19, 0)}     71.0    32.0
KEY:  27     {'team': 'POR', 'date': datetime.datetime(2022, 11, 12, 20, 30)}    75.5    42.0

Logs/Data

No response

cjwin2000 commented 1 year ago

Update:

I'm pretty confident I found the issue. I added in a line to log the raw stats response in player.py and the response contains data from both the 2023 and 2022 seasons. I have attached the response to this comment. Whenever there is a scoringPeriodId of equal value for both seasons, it prefers the 2022 season data, and it will list all unique scoringPeriodIds when using this API causing there to be too many keys. There should be however many team games have been played plus two--one for average and one for projections I'm guessing since these both have scoringPeriodId=0. Going back to my example of the first game of the season with scoringPeriodId=3, you'll see that the incorrect data I mentioned above is just the data from that same scoringPeriodId from the 2022 season. In fact, if you don't sort the scoringPeriodIds like I did above, you'll see they're in the proper order (most recent game first), with the 2022-only (thus far) keys appended at the end.

Apologies for the json being in a zip. Github limitations 🙃

Doncic_response.zip

cjwin2000 commented 1 year ago

Created a pull request to fix this. I don't fully understand what's going on so hopefully that doesn't break any other functionality.

Some of the records in the response don't even have the "total" key that should allow users to access fields like points and rebounds for specific games. The code snippet below actually fails eventually for this reason. Some of the values, however are correct

Ignore this. I am an idiot and didn't realize this was due to the player sitting out the game. In my testing everything stats-related for players seems to be working correctly.

cwendt94 commented 1 year ago

Thanks for digging into this and creating a PR! I will check it out now and see if I get the same results! We had a similar issue in the football class and had to filter out other years in player class here

cwendt94 commented 1 year ago

PR has been merged and is in the latest v0.28.1 package! Thanks for all the help!