nbastatpy 0.1.6__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of nbastatpy might be problematic. Click here for more details.
- nbastatpy/__init__.py +1 -0
- nbastatpy/game.py +153 -0
- nbastatpy/player.py +507 -0
- nbastatpy/season.py +578 -0
- nbastatpy/team.py +436 -0
- nbastatpy/utils.py +98 -0
- nbastatpy-0.1.6.dist-info/LICENSE +21 -0
- nbastatpy-0.1.6.dist-info/METADATA +67 -0
- nbastatpy-0.1.6.dist-info/RECORD +10 -0
- nbastatpy-0.1.6.dist-info/WHEEL +4 -0
nbastatpy/__init__.py
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
name = "nbastatpy"
|
nbastatpy/game.py
ADDED
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
from typing import List
|
|
2
|
+
|
|
3
|
+
import nba_api.stats.endpoints as nba
|
|
4
|
+
import pandas as pd
|
|
5
|
+
|
|
6
|
+
from nbastatpy.utils import Formatter
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class Game:
|
|
10
|
+
def __init__(self, game_id: str):
|
|
11
|
+
"""This represents a game. Given an ID, you can get boxscore (and other) information through one of the 'get' methods
|
|
12
|
+
|
|
13
|
+
Args:
|
|
14
|
+
game_id (str): string with 10 digits
|
|
15
|
+
"""
|
|
16
|
+
self.game_id = Formatter.format_game_id(game_id)
|
|
17
|
+
|
|
18
|
+
def get_boxscore(self) -> List[pd.DataFrame]:
|
|
19
|
+
"""Gets traditional boxscore
|
|
20
|
+
|
|
21
|
+
Returns:
|
|
22
|
+
List[pd.DataFrame]: list of dataframes (players, starters/bench, team)
|
|
23
|
+
"""
|
|
24
|
+
self.boxscore = nba.BoxScoreTraditionalV3(self.game_id).get_data_frames()
|
|
25
|
+
return self.boxscore
|
|
26
|
+
|
|
27
|
+
def get_advanced(self):
|
|
28
|
+
"""
|
|
29
|
+
Retrieves the advanced box score data for the game.
|
|
30
|
+
|
|
31
|
+
Returns:
|
|
32
|
+
pandas.DataFrame: The advanced box score data for the game.
|
|
33
|
+
"""
|
|
34
|
+
self.adv_box = nba.BoxScoreAdvancedV3(self.game_id).get_data_frames()
|
|
35
|
+
return self.adv_box
|
|
36
|
+
|
|
37
|
+
def get_defense(self):
|
|
38
|
+
"""
|
|
39
|
+
Retrieves the defensive statistics for the game.
|
|
40
|
+
|
|
41
|
+
Returns:
|
|
42
|
+
def_box (pandas.DataFrame): DataFrame containing the defensive statistics.
|
|
43
|
+
"""
|
|
44
|
+
self.def_box = nba.BoxScoreDefensiveV2(self.game_id).get_data_frames()
|
|
45
|
+
return self.def_box
|
|
46
|
+
|
|
47
|
+
def get_four_factors(self):
|
|
48
|
+
"""
|
|
49
|
+
Retrieves the four factors data for the game.
|
|
50
|
+
|
|
51
|
+
Returns:
|
|
52
|
+
pandas.DataFrame: The four factors data for the game.
|
|
53
|
+
"""
|
|
54
|
+
self.four_factors = nba.BoxScoreFourFactorsV3(self.game_id).get_data_frames()
|
|
55
|
+
return self.four_factors
|
|
56
|
+
|
|
57
|
+
def get_hustle(self) -> List[pd.DataFrame]:
|
|
58
|
+
"""Gets hustle data for a given game
|
|
59
|
+
|
|
60
|
+
Returns:
|
|
61
|
+
List[pd.DataFrame]: list of two dataframes (players, teams)
|
|
62
|
+
"""
|
|
63
|
+
self.hustle = nba.BoxScoreHustleV2(self.game_id).get_data_frames()
|
|
64
|
+
return self.hustle
|
|
65
|
+
|
|
66
|
+
def get_matchups(self):
|
|
67
|
+
"""
|
|
68
|
+
Retrieves the matchups for the game.
|
|
69
|
+
|
|
70
|
+
Returns:
|
|
71
|
+
pandas.DataFrame: The matchups data for the game.
|
|
72
|
+
"""
|
|
73
|
+
self.matchups = nba.BoxScoreMatchupsV3(self.game_id).get_data_frames()
|
|
74
|
+
return self.matchups
|
|
75
|
+
|
|
76
|
+
def get_misc(self):
|
|
77
|
+
"""
|
|
78
|
+
Retrieves miscellaneous box score data for the game.
|
|
79
|
+
|
|
80
|
+
Returns:
|
|
81
|
+
pandas.DataFrame: The miscellaneous box score data.
|
|
82
|
+
"""
|
|
83
|
+
self.misc = nba.BoxScoreMiscV3(self.game_id).get_data_frames()
|
|
84
|
+
return self.misc
|
|
85
|
+
|
|
86
|
+
def get_scoring(self):
|
|
87
|
+
"""
|
|
88
|
+
Retrieves the scoring data for the game.
|
|
89
|
+
|
|
90
|
+
Returns:
|
|
91
|
+
pandas.DataFrame: The scoring data for the game.
|
|
92
|
+
"""
|
|
93
|
+
self.scoring = nba.BoxScoreScoringV3(self.game_id).get_data_frames()
|
|
94
|
+
return self.scoring
|
|
95
|
+
|
|
96
|
+
def get_usage(self) -> List[pd.DataFrame]:
|
|
97
|
+
"""Gets usage data for a given game
|
|
98
|
+
|
|
99
|
+
Returns:
|
|
100
|
+
List[pd.DataFrame]: list of two dataframes (players, teams)
|
|
101
|
+
"""
|
|
102
|
+
self.usage = nba.BoxScoreUsageV3(self.game_id).get_data_frames()
|
|
103
|
+
return self.usage
|
|
104
|
+
|
|
105
|
+
def get_playertrack(self):
|
|
106
|
+
"""
|
|
107
|
+
Retrieves the player tracking data for the game.
|
|
108
|
+
|
|
109
|
+
Returns:
|
|
110
|
+
playertrack (pandas.DataFrame): The player tracking data for the game.
|
|
111
|
+
"""
|
|
112
|
+
self.playertrack = nba.BoxScorePlayerTrackV3(self.game_id).get_data_frames()
|
|
113
|
+
return self.playertrack
|
|
114
|
+
|
|
115
|
+
def get_rotations(self):
|
|
116
|
+
"""
|
|
117
|
+
Retrieves the rotations data for the game.
|
|
118
|
+
|
|
119
|
+
Returns:
|
|
120
|
+
pandas.DataFrame: The rotations data for the game.
|
|
121
|
+
"""
|
|
122
|
+
self.rotations = pd.concat(
|
|
123
|
+
nba.GameRotation(game_id=self.game_id).get_data_frames()
|
|
124
|
+
)
|
|
125
|
+
return self.rotations
|
|
126
|
+
|
|
127
|
+
def get_playbyplay(self) -> pd.DataFrame:
|
|
128
|
+
"""
|
|
129
|
+
Retrieves the play-by-play data for the game.
|
|
130
|
+
|
|
131
|
+
Returns:
|
|
132
|
+
pd.DataFrame: The play-by-play data as a pandas DataFrame.
|
|
133
|
+
"""
|
|
134
|
+
self.playbyplay = nba.PlayByPlayV3(self.game_id).get_data_frames()[0]
|
|
135
|
+
return self.playbyplay
|
|
136
|
+
|
|
137
|
+
def get_win_probability(self) -> pd.DataFrame:
|
|
138
|
+
"""
|
|
139
|
+
Retrieves the win probability data for the game.
|
|
140
|
+
|
|
141
|
+
Returns:
|
|
142
|
+
pd.DataFrame: The win probability data as a pandas DataFrame.
|
|
143
|
+
"""
|
|
144
|
+
self.win_probability = nba.WinProbabilityPBP(
|
|
145
|
+
game_id=self.game_id
|
|
146
|
+
).get_data_frames()[0]
|
|
147
|
+
return self.win_probability
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
if __name__ == "__main__":
|
|
151
|
+
GAME_ID = "0022301148"
|
|
152
|
+
game = Game(game_id=GAME_ID)
|
|
153
|
+
print(game.get_win_probability())
|
nbastatpy/player.py
ADDED
|
@@ -0,0 +1,507 @@
|
|
|
1
|
+
from io import BytesIO
|
|
2
|
+
|
|
3
|
+
import nba_api.stats.endpoints as nba
|
|
4
|
+
import pandas as pd
|
|
5
|
+
import requests
|
|
6
|
+
from bs4 import BeautifulSoup
|
|
7
|
+
from loguru import logger
|
|
8
|
+
from nba_api.stats.endpoints import leaguegamefinder
|
|
9
|
+
from nba_api.stats.static import players, teams
|
|
10
|
+
from PIL import Image
|
|
11
|
+
|
|
12
|
+
from nbastatpy.utils import Formatter, PlayTypes
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class Player:
|
|
16
|
+
def __init__(
|
|
17
|
+
self,
|
|
18
|
+
player: str,
|
|
19
|
+
season_year: str = None,
|
|
20
|
+
playoffs: bool = False,
|
|
21
|
+
permode: str = "PERGAME",
|
|
22
|
+
):
|
|
23
|
+
"""
|
|
24
|
+
Initializes a Player object.
|
|
25
|
+
|
|
26
|
+
Args:
|
|
27
|
+
player (str): The name or ID of the player.
|
|
28
|
+
season_year (str, optional): The season year. Defaults to None.
|
|
29
|
+
playoffs (bool, optional): Whether to retrieve playoff data. Defaults to False.
|
|
30
|
+
permode (str, optional): The per mode for the player's stats. Defaults to "PERGAME".
|
|
31
|
+
"""
|
|
32
|
+
self.permode = PlayTypes.PERMODE[
|
|
33
|
+
permode.replace("_", "").replace("-", "").upper()
|
|
34
|
+
]
|
|
35
|
+
self.name_meta = players.find_player_by_id(player)
|
|
36
|
+
if self.name_meta:
|
|
37
|
+
self.name_meta = [self.name_meta]
|
|
38
|
+
else:
|
|
39
|
+
self.name_meta = players.find_players_by_full_name(player)
|
|
40
|
+
|
|
41
|
+
if not self.name_meta:
|
|
42
|
+
raise ValueError(f"{player} not found")
|
|
43
|
+
if len(self.name_meta) > 1:
|
|
44
|
+
logger.warning(
|
|
45
|
+
f"Multiple players returned. Using: {self.name_meta[0]['full_name']}"
|
|
46
|
+
)
|
|
47
|
+
self.id = self.name_meta[0]["id"]
|
|
48
|
+
self.name = self.name_meta[0]["full_name"]
|
|
49
|
+
self.first_name = self.name_meta[0]["first_name"]
|
|
50
|
+
self.last_name = self.name_meta[0]["last_name"]
|
|
51
|
+
self.is_active = self.name_meta[0]["is_active"]
|
|
52
|
+
|
|
53
|
+
if season_year:
|
|
54
|
+
self.season_year = season_year
|
|
55
|
+
else:
|
|
56
|
+
self.season_year = Formatter.get_current_season_year()
|
|
57
|
+
self.season = Formatter.format_season(self.season_year)
|
|
58
|
+
self.season_type = "Regular Season"
|
|
59
|
+
if playoffs:
|
|
60
|
+
self.season_type = "Playoffs"
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
def get_common_info(self) -> pd.DataFrame:
|
|
64
|
+
"""Gets common info like height, weight, draft_year, etc. and sets as class attr
|
|
65
|
+
|
|
66
|
+
Returns:
|
|
67
|
+
pd.DataFrame: A DataFrame containing the common information of the player.
|
|
68
|
+
"""
|
|
69
|
+
self.common_info = (
|
|
70
|
+
nba.CommonPlayerInfo(self.id).get_data_frames()[0].iloc[0].to_dict()
|
|
71
|
+
)
|
|
72
|
+
|
|
73
|
+
for attr_name, value in self.common_info.items():
|
|
74
|
+
setattr(self, attr_name.lower(), self.common_info.get(attr_name, None))
|
|
75
|
+
|
|
76
|
+
return self.common_info
|
|
77
|
+
|
|
78
|
+
def get_salary(self) -> pd.DataFrame:
|
|
79
|
+
"""
|
|
80
|
+
Retrieves the salary information for a player from hoopshype.com.
|
|
81
|
+
|
|
82
|
+
Returns:
|
|
83
|
+
pd.DataFrame: A DataFrame containing the salary information for the player.
|
|
84
|
+
"""
|
|
85
|
+
salary_url = f"https://hoopshype.com/player/{self.first_name}-{self.last_name}/salary/".lower()
|
|
86
|
+
result = requests.get(salary_url)
|
|
87
|
+
soup = BeautifulSoup(result.content, features="html.parser")
|
|
88
|
+
tables = soup.find_all("table")
|
|
89
|
+
if len(tables) > 1:
|
|
90
|
+
# Get the table rows
|
|
91
|
+
rows = [[cell.text.strip() for cell in row.find_all('td')] for row in tables[0].find_all('tr')]
|
|
92
|
+
|
|
93
|
+
rows2 = [[cell.text.strip() for cell in row.find_all('td')] for row in tables[1].find_all('tr')]
|
|
94
|
+
|
|
95
|
+
projected = pd.DataFrame(rows[1:], columns=rows[0])
|
|
96
|
+
projected["Team"] = projected.columns[1]
|
|
97
|
+
projected = projected.rename(columns={projected.columns[1]:"Salary"})
|
|
98
|
+
projected["Salary_Type"] = "Projected"
|
|
99
|
+
|
|
100
|
+
historical = pd.DataFrame(rows2[1:], columns=rows2[0])
|
|
101
|
+
historical["Salary_Type"] = "Historical"
|
|
102
|
+
|
|
103
|
+
self.salary_df = pd.concat([projected, historical])
|
|
104
|
+
|
|
105
|
+
else:
|
|
106
|
+
# Get the table rows
|
|
107
|
+
rows = [[cell.text.strip() for cell in row.find_all('td')] for row in tables[0].find_all('tr')]
|
|
108
|
+
self.salary_df = pd.DataFrame(rows[1:], columns=rows[0])
|
|
109
|
+
|
|
110
|
+
return self.salary_df
|
|
111
|
+
|
|
112
|
+
def get_headshot(self):
|
|
113
|
+
"""
|
|
114
|
+
Retrieves the headshot image of the player.
|
|
115
|
+
|
|
116
|
+
Returns:
|
|
117
|
+
PIL.Image.Image: The headshot image of the player.
|
|
118
|
+
"""
|
|
119
|
+
pic_url = f"https://cdn.nba.com/headshots/nba/latest/1040x760/{self.id}.png"
|
|
120
|
+
pic = requests.get(pic_url)
|
|
121
|
+
self.headshot = Image.open(BytesIO(pic.content))
|
|
122
|
+
return self.headshot
|
|
123
|
+
|
|
124
|
+
def get_season_career_totals(self) -> pd.DataFrame:
|
|
125
|
+
"""Gets seasons and career data
|
|
126
|
+
|
|
127
|
+
Returns:
|
|
128
|
+
pd.DataFrame: 2 dataframes, season totals and career
|
|
129
|
+
"""
|
|
130
|
+
df_list = nba.PlayerCareerStats(player_id=self.id).get_data_frames()
|
|
131
|
+
self.career_totals = df_list[1]
|
|
132
|
+
self.season_totals = df_list[0]
|
|
133
|
+
return self.season_totals, self.career_totals
|
|
134
|
+
|
|
135
|
+
def get_splits(self) -> pd.DataFrame:
|
|
136
|
+
"""Gets all splits for a given season"""
|
|
137
|
+
|
|
138
|
+
self.splits_data = pd.concat(
|
|
139
|
+
nba.PlayerDashboardByGeneralSplits(
|
|
140
|
+
self.id,
|
|
141
|
+
season=self.season,
|
|
142
|
+
season_type_playoffs=self.season_type,
|
|
143
|
+
per_mode_detailed=self.permode,
|
|
144
|
+
).get_data_frames()
|
|
145
|
+
)
|
|
146
|
+
|
|
147
|
+
return self.splits_data
|
|
148
|
+
|
|
149
|
+
def get_game_splits(self) -> pd.DataFrame:
|
|
150
|
+
"""Gets splits for the game (halftime, quarter, etc.)
|
|
151
|
+
|
|
152
|
+
Returns:
|
|
153
|
+
pd.DataFrame: dataframe with all game splits for a season
|
|
154
|
+
"""
|
|
155
|
+
|
|
156
|
+
self.game_splits = pd.concat(
|
|
157
|
+
nba.PlayerDashboardByGameSplits(
|
|
158
|
+
self.id,
|
|
159
|
+
season=self.season,
|
|
160
|
+
season_type_playoffs=self.season_type,
|
|
161
|
+
per_mode_detailed=self.permode,
|
|
162
|
+
).get_data_frames()
|
|
163
|
+
)
|
|
164
|
+
return self.game_splits
|
|
165
|
+
|
|
166
|
+
def get_shooting_splits(self) -> pd.DataFrame:
|
|
167
|
+
|
|
168
|
+
self.shooting_splits = pd.concat(
|
|
169
|
+
nba.PlayerDashboardByShootingSplits(
|
|
170
|
+
self.id,
|
|
171
|
+
season=self.season,
|
|
172
|
+
season_type_playoffs=self.season_type,
|
|
173
|
+
per_mode_detailed=self.permode,
|
|
174
|
+
).get_data_frames()
|
|
175
|
+
)
|
|
176
|
+
return self.shooting_splits
|
|
177
|
+
|
|
178
|
+
def get_combine_stats(self) -> pd.DataFrame:
|
|
179
|
+
"""Gets draft combine data for the player's draft year"""
|
|
180
|
+
if not hasattr(
|
|
181
|
+
self, "draft_year"
|
|
182
|
+
): # Check if we know the player's draft year yet
|
|
183
|
+
self.get_common_info()
|
|
184
|
+
|
|
185
|
+
self.combine_stats = nba.DraftCombineStats(
|
|
186
|
+
season_all_time=self.draft_year
|
|
187
|
+
).get_data_frames()[0]
|
|
188
|
+
|
|
189
|
+
self.combine_nonstationary_shooting = nba.DraftCombineNonStationaryShooting(
|
|
190
|
+
season_year=self.draft_year
|
|
191
|
+
).get_data_frames()[0]
|
|
192
|
+
|
|
193
|
+
self.combine_spot_shooting = nba.DraftCombineSpotShooting(
|
|
194
|
+
season_year=self.draft_year
|
|
195
|
+
).get_data_frames()[0]
|
|
196
|
+
|
|
197
|
+
return [
|
|
198
|
+
self.combine_stats,
|
|
199
|
+
self.combine_nonstationary_shooting,
|
|
200
|
+
self.combine_spot_shooting,
|
|
201
|
+
]
|
|
202
|
+
|
|
203
|
+
def get_awards(self) -> pd.DataFrame:
|
|
204
|
+
"""Gets any awards won by the player.
|
|
205
|
+
|
|
206
|
+
Returns:
|
|
207
|
+
pd.DataFrame: A DataFrame containing the player's awards.
|
|
208
|
+
"""
|
|
209
|
+
self.awards = nba.PlayerAwards(self.id).get_data_frames()[0]
|
|
210
|
+
return self.awards
|
|
211
|
+
|
|
212
|
+
def get_games_boxscore(self) -> pd.DataFrame:
|
|
213
|
+
"""
|
|
214
|
+
Retrieves the boxscore data for the games played by the player.
|
|
215
|
+
|
|
216
|
+
Returns:
|
|
217
|
+
pd.DataFrame: The boxscore data for the player's games.
|
|
218
|
+
"""
|
|
219
|
+
self.games_boxscore = leaguegamefinder.LeagueGameFinder(
|
|
220
|
+
player_id_nullable=self.id,
|
|
221
|
+
season_nullable=self.season,
|
|
222
|
+
season_type_nullable=self.season_type,
|
|
223
|
+
).get_data_frames()[0]
|
|
224
|
+
return self.games_boxscore
|
|
225
|
+
|
|
226
|
+
def get_matchups(self, defense: bool = False) -> pd.DataFrame:
|
|
227
|
+
"""
|
|
228
|
+
Retrieves the matchups data for the player.
|
|
229
|
+
|
|
230
|
+
Args:
|
|
231
|
+
defense (bool, optional): If True, retrieves the defensive matchups data.
|
|
232
|
+
If False, retrieves the offensive matchups data. Defaults to False.
|
|
233
|
+
|
|
234
|
+
Returns:
|
|
235
|
+
pd.DataFrame: The matchups data for the player.
|
|
236
|
+
"""
|
|
237
|
+
if defense:
|
|
238
|
+
self.matchups = nba.LeagueSeasonMatchups(
|
|
239
|
+
def_player_id_nullable=self.id,
|
|
240
|
+
season=self.season,
|
|
241
|
+
season_type_playoffs=self.season_type,
|
|
242
|
+
per_mode_simple=self.permode,
|
|
243
|
+
).get_data_frames()[0]
|
|
244
|
+
else:
|
|
245
|
+
self.matchups = nba.LeagueSeasonMatchups(
|
|
246
|
+
off_player_id_nullable=self.id,
|
|
247
|
+
season=self.season,
|
|
248
|
+
season_type_playoffs=self.season_type,
|
|
249
|
+
per_mode_simple=self.permode,
|
|
250
|
+
).get_data_frames()[0]
|
|
251
|
+
return self.matchups
|
|
252
|
+
|
|
253
|
+
def get_clutch(self) -> pd.DataFrame:
|
|
254
|
+
"""Gets clutch data for multiple clutch segments
|
|
255
|
+
|
|
256
|
+
Returns:
|
|
257
|
+
pd.DataFrame: dataframe with a given year of clutch segments
|
|
258
|
+
"""
|
|
259
|
+
self.clutch = pd.concat(
|
|
260
|
+
nba.PlayerDashboardByClutch(
|
|
261
|
+
player_id=self.id,
|
|
262
|
+
season=self.season,
|
|
263
|
+
season_type_playoffs=self.season_type,
|
|
264
|
+
per_mode_detailed=self.permode,
|
|
265
|
+
).get_data_frames()
|
|
266
|
+
)
|
|
267
|
+
return self.clutch
|
|
268
|
+
|
|
269
|
+
def get_pt_pass(self) -> pd.DataFrame:
|
|
270
|
+
"""
|
|
271
|
+
Retrieves the passing statistics for the player.
|
|
272
|
+
|
|
273
|
+
Returns:
|
|
274
|
+
pd.DataFrame: A DataFrame containing the passing statistics for the player.
|
|
275
|
+
"""
|
|
276
|
+
if not hasattr(self, "season_totals"):
|
|
277
|
+
logger.info("Getting Teams")
|
|
278
|
+
teams = self.get_season_career_totals()[0]
|
|
279
|
+
else:
|
|
280
|
+
teams = self.season_totals.copy()
|
|
281
|
+
|
|
282
|
+
teams = teams[(teams["SEASON_ID"] == self.season) & (teams["TEAM_ID"] != 0)][
|
|
283
|
+
"TEAM_ID"
|
|
284
|
+
].tolist()
|
|
285
|
+
|
|
286
|
+
if len(teams) > 1:
|
|
287
|
+
self.pt_pass = []
|
|
288
|
+
for team in teams:
|
|
289
|
+
self.pt_pass.append(
|
|
290
|
+
pd.concat(
|
|
291
|
+
nba.PlayerDashPtPass(
|
|
292
|
+
player_id=self.id,
|
|
293
|
+
team_id=team,
|
|
294
|
+
season=self.season,
|
|
295
|
+
season_type_all_star=self.season_type,
|
|
296
|
+
per_mode_simple=self.permode,
|
|
297
|
+
).get_data_frames()
|
|
298
|
+
)
|
|
299
|
+
)
|
|
300
|
+
|
|
301
|
+
self.pt_pass = pd.concat(self.pt_pass)
|
|
302
|
+
|
|
303
|
+
else:
|
|
304
|
+
self.pt_pass = pd.concat(
|
|
305
|
+
nba.PlayerDashPtPass(
|
|
306
|
+
player_id=self.id,
|
|
307
|
+
team_id=teams[0],
|
|
308
|
+
season=self.season,
|
|
309
|
+
season_type_all_star=self.season_type,
|
|
310
|
+
per_mode_simple=self.permode,
|
|
311
|
+
).get_data_frames()
|
|
312
|
+
)
|
|
313
|
+
|
|
314
|
+
group_cols = ["PASS_TO", "PASS_FROM"]
|
|
315
|
+
self.pt_pass["GROUP_SET"] = self.pt_pass[group_cols].apply(
|
|
316
|
+
Formatter.combine_strings, axis=1
|
|
317
|
+
)
|
|
318
|
+
self.pt_pass = self.pt_pass.drop(columns=group_cols)
|
|
319
|
+
|
|
320
|
+
return self.pt_pass
|
|
321
|
+
|
|
322
|
+
def get_pt_reb(self) -> pd.DataFrame:
|
|
323
|
+
"""
|
|
324
|
+
Retrieves the rebounds data for the player.
|
|
325
|
+
|
|
326
|
+
Returns:
|
|
327
|
+
pd.DataFrame: A DataFrame containing the rebounds data.
|
|
328
|
+
"""
|
|
329
|
+
if not hasattr(self, "season_totals"):
|
|
330
|
+
logger.info("Getting Teams")
|
|
331
|
+
teams = self.get_season_career_totals()[0]
|
|
332
|
+
else:
|
|
333
|
+
teams = self.season_totals.copy()
|
|
334
|
+
|
|
335
|
+
teams = teams[(teams["SEASON_ID"] == self.season) & (teams["TEAM_ID"] != 0)][
|
|
336
|
+
"TEAM_ID"
|
|
337
|
+
].tolist()
|
|
338
|
+
|
|
339
|
+
if len(teams) > 1:
|
|
340
|
+
self.pt_reb = []
|
|
341
|
+
for team in teams:
|
|
342
|
+
self.pt_reb.append(
|
|
343
|
+
pd.concat(
|
|
344
|
+
nba.PlayerDashPtReb(
|
|
345
|
+
player_id=self.id,
|
|
346
|
+
team_id=team,
|
|
347
|
+
season=self.season,
|
|
348
|
+
season_type_all_star=self.season_type,
|
|
349
|
+
per_mode_simple=self.permode,
|
|
350
|
+
).get_data_frames()
|
|
351
|
+
)
|
|
352
|
+
)
|
|
353
|
+
|
|
354
|
+
self.pt_reb = pd.concat(self.pt_reb)
|
|
355
|
+
|
|
356
|
+
else:
|
|
357
|
+
self.pt_reb = pd.concat(
|
|
358
|
+
nba.PlayerDashPtReb(
|
|
359
|
+
player_id=self.id,
|
|
360
|
+
team_id=teams[0],
|
|
361
|
+
season=self.season,
|
|
362
|
+
season_type_all_star=self.season_type,
|
|
363
|
+
per_mode_simple=self.permode,
|
|
364
|
+
).get_data_frames()
|
|
365
|
+
)
|
|
366
|
+
|
|
367
|
+
group_cols = [
|
|
368
|
+
"OVERALL",
|
|
369
|
+
"SHOT_TYPE_RANGE",
|
|
370
|
+
"REB_NUM_CONTESTING_RANGE",
|
|
371
|
+
"SHOT_DIST_RANGE",
|
|
372
|
+
"REB_DIST_RANGE",
|
|
373
|
+
]
|
|
374
|
+
self.pt_reb["GROUP_SET"] = self.pt_reb[group_cols].apply(
|
|
375
|
+
Formatter.combine_strings, axis=1
|
|
376
|
+
)
|
|
377
|
+
self.pt_reb = self.pt_reb.drop(columns=group_cols)
|
|
378
|
+
|
|
379
|
+
return self.pt_reb
|
|
380
|
+
|
|
381
|
+
def get_defense_against_team(self, opposing_team: str) -> pd.DataFrame:
|
|
382
|
+
"""
|
|
383
|
+
Retrieves the defensive statistics of the player against a specific team.
|
|
384
|
+
|
|
385
|
+
Args:
|
|
386
|
+
opposing_team (str): The abbreviation of the opposing team.
|
|
387
|
+
|
|
388
|
+
Returns:
|
|
389
|
+
pd.DataFrame: A DataFrame containing the defensive statistics of the player against the specified team.
|
|
390
|
+
"""
|
|
391
|
+
opp_tm_id = teams.find_team_by_abbreviation(opposing_team)["id"]
|
|
392
|
+
|
|
393
|
+
self.defense_against_team = nba.PlayerDashPtShotDefend(
|
|
394
|
+
player_id=self.id,
|
|
395
|
+
team_id=opp_tm_id,
|
|
396
|
+
season=self.season,
|
|
397
|
+
season_type_all_star=self.season_type,
|
|
398
|
+
per_mode_simple=self.permode,
|
|
399
|
+
).get_data_frames()[0]
|
|
400
|
+
return self.defense_against_team
|
|
401
|
+
|
|
402
|
+
def get_pt_shots(self) -> pd.DataFrame:
|
|
403
|
+
"""
|
|
404
|
+
Retrieves the shots data for the player.
|
|
405
|
+
|
|
406
|
+
Returns:
|
|
407
|
+
pd.DataFrame: The shots data for the player.
|
|
408
|
+
"""
|
|
409
|
+
if not hasattr(self, "season_totals"):
|
|
410
|
+
logger.info("Getting Teams")
|
|
411
|
+
teams = self.get_season_career_totals()[0]
|
|
412
|
+
else:
|
|
413
|
+
teams = self.season_totals.copy()
|
|
414
|
+
|
|
415
|
+
teams = teams[(teams["SEASON_ID"] == self.season) & (teams["TEAM_ID"] != 0)][
|
|
416
|
+
"TEAM_ID"
|
|
417
|
+
].tolist()
|
|
418
|
+
|
|
419
|
+
if len(teams) > 1:
|
|
420
|
+
self.pt_shots = []
|
|
421
|
+
for team in teams:
|
|
422
|
+
self.pt_shots.append(
|
|
423
|
+
pd.concat(
|
|
424
|
+
nba.PlayerDashPtShots(
|
|
425
|
+
player_id=self.id,
|
|
426
|
+
team_id=team,
|
|
427
|
+
season=self.season,
|
|
428
|
+
season_type_all_star=self.season_type,
|
|
429
|
+
per_mode_simple=self.permode,
|
|
430
|
+
).get_data_frames()
|
|
431
|
+
)
|
|
432
|
+
)
|
|
433
|
+
|
|
434
|
+
self.pt_shots = pd.concat(self.pt_shots)
|
|
435
|
+
|
|
436
|
+
else:
|
|
437
|
+
self.pt_shots = pd.concat(
|
|
438
|
+
nba.PlayerDashPtShots(
|
|
439
|
+
player_id=self.id,
|
|
440
|
+
team_id=teams[0],
|
|
441
|
+
season=self.season,
|
|
442
|
+
season_type_all_star=self.season_type,
|
|
443
|
+
per_mode_simple=self.permode,
|
|
444
|
+
).get_data_frames()
|
|
445
|
+
)
|
|
446
|
+
|
|
447
|
+
group_cols = [
|
|
448
|
+
"SHOT_TYPE",
|
|
449
|
+
"SHOT_CLOCK_RANGE",
|
|
450
|
+
"DRIBBLE_RANGE",
|
|
451
|
+
"CLOSE_DEF_DIST_RANGE",
|
|
452
|
+
"TOUCH_TIME_RANGE",
|
|
453
|
+
]
|
|
454
|
+
self.pt_shots["GROUP_SET"] = self.pt_shots[group_cols].apply(
|
|
455
|
+
Formatter.combine_strings, axis=1
|
|
456
|
+
)
|
|
457
|
+
self.pt_shots = self.pt_shots.drop(columns=group_cols)
|
|
458
|
+
|
|
459
|
+
return self.pt_shots
|
|
460
|
+
|
|
461
|
+
def get_shot_chart(self) -> pd.DataFrame:
|
|
462
|
+
"""
|
|
463
|
+
Retrieves the shot chart data for the player.
|
|
464
|
+
|
|
465
|
+
Returns:
|
|
466
|
+
pd.DataFrame: The shot chart data for the player.
|
|
467
|
+
"""
|
|
468
|
+
if not hasattr(self, "season_totals"):
|
|
469
|
+
logger.info("Getting Teams")
|
|
470
|
+
teams = self.get_season_career_totals()[0]
|
|
471
|
+
else:
|
|
472
|
+
teams = self.season_totals.copy()
|
|
473
|
+
|
|
474
|
+
teams = teams[(teams["SEASON_ID"] == self.season) & (teams["TEAM_ID"] != 0)][
|
|
475
|
+
"TEAM_ID"
|
|
476
|
+
].tolist()
|
|
477
|
+
|
|
478
|
+
if len(teams) > 1:
|
|
479
|
+
self.shot_chart = []
|
|
480
|
+
for team in teams:
|
|
481
|
+
self.shot_chart.append(
|
|
482
|
+
nba.ShotChartDetail(
|
|
483
|
+
player_id=self.id,
|
|
484
|
+
team_id=team,
|
|
485
|
+
season_nullable=self.season,
|
|
486
|
+
season_type_all_star=self.season_type,
|
|
487
|
+
).get_data_frames()[0]
|
|
488
|
+
)
|
|
489
|
+
|
|
490
|
+
self.shot_chart = pd.concat(self.shot_chart)
|
|
491
|
+
|
|
492
|
+
else:
|
|
493
|
+
self.shot_chart = nba.ShotChartDetail(
|
|
494
|
+
player_id=self.id,
|
|
495
|
+
team_id=teams[0],
|
|
496
|
+
season_nullable=self.season,
|
|
497
|
+
season_type_all_star=self.season_type,
|
|
498
|
+
).get_data_frames()[0]
|
|
499
|
+
|
|
500
|
+
return self.shot_chart
|
|
501
|
+
|
|
502
|
+
|
|
503
|
+
if __name__ == "__main__":
|
|
504
|
+
player_name = "giannis"
|
|
505
|
+
player_seas = "2020"
|
|
506
|
+
player = Player(player_name, player_seas)
|
|
507
|
+
print(player.get_salary())
|