The purpose of this project is to give a unique ranking on NBA Players based on how valuable they are for Fantasy Basketball 9-Cat mode. The value is based on the mean value for each category for the top 200 players in that category, and the z-score of the individual players are used to determine their value. Also, this tool will provide a 8-Cat ranking as well, as most players tend to lack at a specific category, so another option to cancel the lowest z-score will also be provided. This tool will be helpful to determine how much value will be gained or lost through trades, waiver wire pickups, or building the team.
Fantasy Basketball 9-Cat:
Fantasy Basketball 9-Cat is a specific gamemode of Fantasy Basketball. A league is created between friends and people gather NBA Players in their team based on either a draft or an auction. Then, they have weekly matchups within each other where they try to win the 9 statistical categories of basketball which are fg%, ft%, 3pt, points, rebounds, assists, steals, blocks, and turnovers. Specific NBA players are great at a few categories, some are alright at a bunch, and the best players both specialize at certain categories, and don’t hurt at others. Through this tool, a correct determination of the value of players will be created.
There will also be an option to change the season, which will be useful to track who the best Fantasy Basketball players were historically as well.
Fantasy Basketball 9-Cat:
Fantasy Basketball 9-Cat is a specific gamemode of Fantasy Basketball. A league is created between friends and people gather NBA Players in their team based on either a draft or an auction. Then, they have weekly matchups within each other where they try to win the 9 statistical categories of basketball which are fg%, ft%, 3pt, points, rebounds, assists, steals, blocks, and turnovers. Specific NBA players are great at a few categories, some are alright at a bunch, and the best players both specialize at certain categories, and don’t hurt at others. Through this tool, a correct determination of the value of players will be created.
There will also be an option to change the season, which will be useful to track who the best Fantasy Basketball players were historically as well.
Step 1: Importing Data
Step 1: Importing Data
Data will be imported from Basketball Reference. https://www.basketball-reference.com/leagues/NBA_1986_totals.html#totals_stats. Then, each of the 9-Cat related statistics are pulled. This tool starts from 1982 for stat-tracking purposes and the introduction of three pointers.
Adjust Year Here:
year="2009";nbaYears=TextWords[ToString[Range[1982,2024]]];basketballSeason=Import["https://www.basketball-reference.com/leagues/NBA_"<>year<>"_totals.html#totals_stats","Data"];playerDataBaseRaw=Delete[Flatten[basketballSeason,2][[-28]][[3]],-1];
Remove Blank 3pt%, 2pt%, and ft% that mess with data, multiple teams players played for, players with less than 1000 minutes played, accolades, and non-Fantasy Basketball 9-Cat related categories so that only the following remains: Player Name, Games Played, FG%, 3P, FT%, TRB, AST, STL, BLK, TOV, PTS:
In[]:=
rangeLenPlayers=(Length@playerDataBaseRaw-1)//Range;playerDataBase3pt=Table[If[playerDataBaseRaw[[n]][[13]]==0,Insert[playerDataBaseRaw[[n]],0,13],playerDataBaseRaw[[n]]],{n,rangeLenPlayers}];playerDataBase2pt=Table[If[playerDataBase3pt[[n]][[16]]==0,Insert[playerDataBase3pt[[n]],0,16],playerDataBase3pt[[n]]],{n,rangeLenPlayers}];playerDataBaseEmptyFixed=Table[If[playerDataBase2pt[[n]][[20]]==0,Insert[playerDataBase2pt[[n]],0,20],playerDataBase2pt[[n]]],{n,rangeLenPlayers}];positions=GatherBy[rangeLenPlayers,playerDataBaseEmptyFixed[[#]][[1]]&];positionsToDeleteRaw=Select[positions,Length[#]>1&];positionsToDelete=Partition[Flatten[Table[Delete[positionsToDeleteRaw[[n]],1],{n,Range[Length[positionsToDeleteRaw]]}]],1];playerDataBaseTMFixed=Delete[playerDataBaseEmptyFixed,positionsToDelete];rangeLenTMFixed=Range[Length[playerDataBaseTMFixed]];playerDataBaseLimited=Table[If[playerDataBaseTMFixed[[n]][[8]]<=1000,Nothing,playerDataBaseTMFixed[[n]]],{n,rangeLenTMFixed}];rangeLenNew=Length@playerDataBaseLimited//Range;playerDataBaseNoAcc=Table[Take[playerDataBaseLimited[[n]],31],{n,rangeLenNew}];cleanDataSeason=Table[playerDataBaseNoAcc[[n]][[{2,6,11,12,21,24,25,26,27,28,30}]],{n,rangeLenNew}];cleanDataAverages=Table[(cleanDataSeason[[n]][[{4,6,7,8,9,10,11}]]/cleanDataSeason[[n]][[2]]),{n,rangeLenNew}]//N;cleanDataComplete=Table[Join[cleanDataSeason[[n]][[{1,2,3,5}]],cleanDataAverages[[n]]],{n,rangeLenNew}];cleanRangeLen=Length@cleanDataComplete//Range;
Step 2: Calculating the Mean and Standard Deviation for Individual Categories
Step 2: Calculating the Mean and Standard Deviation for Individual Categories
For the 9 categories, the value of the stat is divided by the games played by the player, and all of the values are stored in a list. Then, the mean and the standard deviation of the specific category is found. This is done for each of the 9 categories. The means and standard deviations for each category is listed out.
In[]:=
fgValues=Table[cleanDataComplete[[n]][[3]],{n,cleanRangeLen}];fgValuesMean=Mean[fgValues];fgValuesSD=StandardDeviation[fgValues];ftValues=Table[cleanDataComplete[[n]][[4]],{n,cleanRangeLen}];ftValuesMean=Mean[ftValues];ftValuesSD=StandardDeviation[ftValues];threeptValues=Table[cleanDataComplete[[n]][[5]],{n,cleanRangeLen}];threeptValuesMean=Mean[threeptValues];threeptValuesSD=StandardDeviation[threeptValues];rbdValues=Table[cleanDataComplete[[n]][[6]],{n,cleanRangeLen}];rbdValuesMean=Mean[rbdValues];rbdValuesSD=StandardDeviation[rbdValues];astValues=Table[cleanDataComplete[[n]][[7]],{n,cleanRangeLen}];astValuesMean=Mean[astValues];astValuesSD=StandardDeviation[astValues];stlValues=Table[cleanDataComplete[[n]][[8]],{n,cleanRangeLen}];stlValuesMean=Mean[stlValues];stlValuesSD=StandardDeviation[stlValues];blkValues=Table[cleanDataComplete[[n]][[9]],{n,cleanRangeLen}];blkValuesMean=Mean[blkValues];blkValuesSD=StandardDeviation[blkValues];tovValues=Sort[Table[cleanDataComplete[[n]][[10]],{n,cleanRangeLen}]];tovValuesMean=Mean[tovValues];tovValuesSD=StandardDeviation[tovValues];ptsValues=Table[cleanDataComplete[[n]][[11]],{n,cleanRangeLen}];ptsValuesMean=Mean[ptsValues];ptsValuesSD=StandardDeviation[ptsValues];
Step 3: z-Scores for Individual Players are Calculated
Step 3: z-Scores for Individual Players are Calculated
Each player who survived the restrictions will be listed out with their stats in 9 categories, divided by the number of games they have played. Afterwards, using the mean and the standard deviation the z score for each individual category of a player is calculated. Here, as turnover is a negative stat and the less turnovers win in Fantasy Basketball 9-Cat, it will be multiplied by -1 for the calculation. Afterward, as the name of the players and their z-scores for each category is found, the z-scores will be added. This will give us the z-score ranking for relevant players in Fantasy Basketball 9-Cat. The result will be displayed in a list, with the z-scores of each players in different categories, and the total z-scores.
categories=Table[Style[{"Name","GP","FG%","FT%","3PT","RBD","AST","STL","BLK","TOV","PTS","Z-SCORE"}[[n]],Bold],{n,Range[12]}];zscores=Table[Flatten[Join[{cleanDataComplete[[n]][[{1,2}]],0.5*((cleanDataComplete[[n]][[3]]-fgValuesMean)/fgValuesSD),0.5*((cleanDataComplete[[n]][[4]]-ftValuesMean)/ftValuesSD),((cleanDataComplete[[n]][[5]]-threeptValuesMean)/threeptValuesSD),((cleanDataComplete[[n]][[6]]-rbdValuesMean)/rbdValuesSD),((cleanDataComplete[[n]][[7]]-astValuesMean)/astValuesSD),((cleanDataComplete[[n]][[8]]-stlValuesMean)/stlValuesSD),((cleanDataComplete[[n]][[9]]-blkValuesMean)/blkValuesSD),-0.25*((cleanDataComplete[[n]][[10]]-tovValuesMean)/tovValuesSD),((cleanDataComplete[[n]][[11]]-ptsValuesMean)/ptsValuesSD)}]],{n,cleanRangeLen}];zscoresTotal=Reverse[SortBy[Table[Flatten[Join[{zscores[[n]],Total[zscores[[n]][[{3,4,5,6,7,8,9,10,11}]]]}]],{n,cleanRangeLen}],Last]];tableSeason=NumberForm[Grid[Partition[Flatten[Join[{categories,zscoresTotal}]],12],Spacings->{3,0.5},Frame->All],4]
See output table here: https://www.wolframcloud.com/obj/8bc10dd9-76ae-42bb-8bc2-95dc742f001d
Step 4: Greatest and Worst 9-Cat Season of All-Time
Step 4: Greatest and Worst 9-Cat Season of All-Time
Best Player Each Season
bestPlayerEachSeason=Table[basketballSeason=Import["https://www.basketball-reference.com/leagues/NBA_"<>year<>"_totals.html#totals_stats","Data"];playerDataBaseRaw=Delete[Flatten[basketballSeason,2][[-28]][[3]],-1];rangeLenPlayers=(Length@playerDataBaseRaw-1)//Range;playerDataBase3pt=Table[If[playerDataBaseRaw[[n]][[13]]==0,Insert[playerDataBaseRaw[[n]],0,13],playerDataBaseRaw[[n]]],{n,rangeLenPlayers}];playerDataBase2pt=Table[If[playerDataBase3pt[[n]][[16]]==0,Insert[playerDataBase3pt[[n]],0,16],playerDataBase3pt[[n]]],{n,rangeLenPlayers}];playerDataBaseEmptyFixed=Table[If[playerDataBase2pt[[n]][[20]]==0,Insert[playerDataBase2pt[[n]],0,20],playerDataBase2pt[[n]]],{n,rangeLenPlayers}];positions=GatherBy[rangeLenPlayers,playerDataBaseEmptyFixed[[#]][[1]]&];positionsToDeleteRaw=Select[positions,Length[#]>1&];positionsToDelete=Partition[Flatten[Table[Delete[positionsToDeleteRaw[[n]],1],{n,Range[Length[positionsToDeleteRaw]]}]],1];playerDataBaseTMFixed=Delete[playerDataBaseEmptyFixed,positionsToDelete];rangeLenTMFixed=Range[Length[playerDataBaseTMFixed]];playerDataBaseLimited=Table[If[playerDataBaseTMFixed[[n]][[8]]<=1000,Nothing,playerDataBaseTMFixed[[n]]],{n,rangeLenTMFixed}];rangeLenNew=Length@playerDataBaseLimited//Range;playerDataBaseNoAcc=Table[Take[playerDataBaseLimited[[n]],31],{n,rangeLenNew}];cleanDataSeason=Table[playerDataBaseNoAcc[[n]][[{2,6,11,12,21,24,25,26,27,28,30}]],{n,rangeLenNew}];cleanDataAverages=Table[(cleanDataSeason[[n]][[{4,6,7,8,9,10,11}]]/cleanDataSeason[[n]][[2]]),{n,rangeLenNew}]//N;cleanDataComplete=Table[Join[cleanDataSeason[[n]][[{1,2,3,5}]],cleanDataAverages[[n]]],{n,rangeLenNew}];cleanRangeLen=Length@cleanDataComplete//Range;fgValues=Table[cleanDataComplete[[n]][[3]],{n,cleanRangeLen}];fgValuesMean=Mean[fgValues];fgValuesSD=StandardDeviation[fgValues];ftValues=Table[cleanDataComplete[[n]][[4]],{n,cleanRangeLen}];ftValuesMean=Mean[ftValues];ftValuesSD=StandardDeviation[ftValues];threeptValues=Table[cleanDataComplete[[n]][[5]],{n,cleanRangeLen}];threeptValuesMean=Mean[threeptValues];threeptValuesSD=StandardDeviation[threeptValues];rbdValues=Table[cleanDataComplete[[n]][[6]],{n,cleanRangeLen}];rbdValuesMean=Mean[rbdValues];rbdValuesSD=StandardDeviation[rbdValues];astValues=Table[cleanDataComplete[[n]][[7]],{n,cleanRangeLen}];astValuesMean=Mean[astValues];astValuesSD=StandardDeviation[astValues];stlValues=Table[cleanDataComplete[[n]][[8]],{n,cleanRangeLen}];stlValuesMean=Mean[stlValues];stlValuesSD=StandardDeviation[stlValues];blkValues=Table[cleanDataComplete[[n]][[9]],{n,cleanRangeLen}];blkValuesMean=Mean[blkValues];blkValuesSD=StandardDeviation[blkValues];tovValues=Sort[Table[cleanDataComplete[[n]][[10]],{n,cleanRangeLen}]];tovValuesMean=Mean[tovValues];tovValuesSD=StandardDeviation[tovValues];ptsValues=Table[cleanDataComplete[[n]][[11]],{n,cleanRangeLen}];ptsValuesMean=Mean[ptsValues];ptsValuesSD=StandardDeviation[ptsValues];zscores=Table[Flatten[Join[{year,cleanDataComplete[[n]][[{1,2}]],0.50*((cleanDataComplete[[n]][[3]]-fgValuesMean)/fgValuesSD),0.50*((cleanDataComplete[[n]][[4]]-ftValuesMean)/ftValuesSD),((cleanDataComplete[[n]][[5]]-threeptValuesMean)/threeptValuesSD),((cleanDataComplete[[n]][[6]]-rbdValuesMean)/rbdValuesSD),((cleanDataComplete[[n]][[7]]-astValuesMean)/astValuesSD),((cleanDataComplete[[n]][[8]]-stlValuesMean)/stlValuesSD),((cleanDataComplete[[n]][[9]]-blkValuesMean)/blkValuesSD),-0.25*((cleanDataComplete[[n]][[10]]-tovValuesMean)/tovValuesSD),((cleanDataComplete[[n]][[11]]-ptsValuesMean)/ptsValuesSD)}]],{n,cleanRangeLen}];zscoresTotal=First[Reverse[SortBy[Table[Flatten[Join[{zscores[[n]],Total[zscores[[n]][[{4,5,6,7,8,9,10,11,12}]]]}]],{n,cleanRangeLen}],Last]]],{year,nbaYears}];categoriesYear=Table[Style[{"Year","Name","GP","FG%","FT%","3PT","RBD","AST","STL","BLK","TOV","PTS","Z-SCORE"}[[n]],Bold],{n,Range[13]}];bestEachSeasonTable=NumberForm[Grid[Partition[Flatten[Join[{categoriesYear,Reverse[SortBy[bestPlayerEachSeason,Last]]}]],13],Spacings->{3,0.5},Frame->All],4]
See the output table here: https://www.wolframcloud.com/obj/a463fe1e-6f88-401e-87cc-de43c5aec73c
Worst Player Each Season (Min 1000 Minutes Played)
See the output table here: https://www.wolframcloud.com/obj/37c6e7fb-01eb-4034-858f-7e870ad35110
Step 5: Highest Z-Score for a Stat
Step 5: Highest Z-Score for a Stat
Situation for a Single Case
Highest Z-Score for a Single Stat Each Season:
Lowest Z-Score for a Single Stat Each Season:
Step 6: 8-Cat Rankings
Step 6: 8-Cat Rankings
For this, as almost every player has a weakness in a category, we are ignoring the worst category for each player and rank them again. This is used by pulling out the data with the player name and the lowest z-score is eliminated. Then, the same process as Step 3 is repeated to calculate the total z-scores and rank players accordingly. For this process, only the player name and their total z-score is listed out.
See output table here: https://www.wolframcloud.com/obj/8a47a45a-e4ef-4113-b1e6-e16978b6a7cf
Stats Credits goes to Basketball Reference
CITE THIS NOTEBOOK
CITE THIS NOTEBOOK
NBA player ranking in Fantasy Basketball 9-Cat mode: mean category scores and Z-score
by Hakan Bora Yavuzkara
Wolfram Community, STAFF PICKS, April 17, 2025
https://community.wolfram.com/groups/-/m/t/3446307
by Hakan Bora Yavuzkara
Wolfram Community, STAFF PICKS, April 17, 2025
https://community.wolfram.com/groups/-/m/t/3446307