Tourney Coaches
Who’s the Best NCAA Tournament Coach?
With the NCAA Men’s basketball tournament and my bracket officially busted I want to start gathering information for next year. I unfortunately chose Virginia to win it all over Villanova as I thought they were the best teams all year long. I was right about one team but woefully wrong about the other. Congrats to UMBC but I want to win my bracket challenge next year.
One aspect I have thought to include in my choices next year is the coach of the team. It seems to me that the same coaches are in the sweet sixteen and beyond each year (Bill Self, Coach K, Jim Boeheim, etc). Also it seems certain coaches get their teams to overacheive (Beilein, Brad Stevens, etc.). My goal is to find current coaches that win more than they are supposed to in the tournament.
To do this I have taken the data from the Kaggle NCAA 2018 ML Contest and will analyze it to find the average amount of wins for each seed and compare that to how the coaches do.
Import, Combine, and Clean the Data
To start I import the data for the conferences, teams, and coaches. Then I merge (AKA SQL join) and sort them by team to get data for each team, their coach, and the current conference on a yearly basis.
%matplotlib inline
import matplotlib as plt
import pandas as pd
import numpy as np
import seaborn as sns
import scipy as spy
from sklearn.model_selection import train_test_split
conf = pd.read_csv("TeamConferences.csv")
teams = pd.read_csv("Teams.csv")
coaches = pd.read_csv("TeamCoaches.csv")
allTeams = coaches.merge(teams[["TeamID", "TeamName"]], on="TeamID").merge(conf, on=["Season", "TeamID"])
allTeams.drop(["FirstDayNum","LastDayNum"], axis=1, inplace=True)
allTeams.drop_duplicates(inplace=True)
allTeams.head(25)
Season | TeamID | CoachName | TeamName | ConfAbbrev | |
---|---|---|---|---|---|
0 | 1985 | 1102 | reggie_minton | Air Force | wac |
1 | 1986 | 1102 | reggie_minton | Air Force | wac |
2 | 1987 | 1102 | reggie_minton | Air Force | wac |
3 | 1988 | 1102 | reggie_minton | Air Force | wac |
4 | 1989 | 1102 | reggie_minton | Air Force | wac |
5 | 1990 | 1102 | reggie_minton | Air Force | wac |
6 | 1991 | 1102 | reggie_minton | Air Force | wac |
7 | 1992 | 1102 | reggie_minton | Air Force | wac |
8 | 1993 | 1102 | reggie_minton | Air Force | wac |
9 | 1994 | 1102 | reggie_minton | Air Force | wac |
10 | 1995 | 1102 | reggie_minton | Air Force | wac |
11 | 1996 | 1102 | reggie_minton | Air Force | wac |
12 | 1997 | 1102 | reggie_minton | Air Force | wac |
13 | 1998 | 1102 | reggie_minton | Air Force | wac |
14 | 1999 | 1102 | reggie_minton | Air Force | wac |
15 | 2000 | 1102 | reggie_minton | Air Force | mwc |
16 | 2001 | 1102 | joe_scott | Air Force | mwc |
17 | 2002 | 1102 | joe_scott | Air Force | mwc |
18 | 2003 | 1102 | joe_scott | Air Force | mwc |
19 | 2004 | 1102 | joe_scott | Air Force | mwc |
20 | 2005 | 1102 | chris_mooney | Air Force | mwc |
21 | 2006 | 1102 | jeff_bzdelik | Air Force | mwc |
22 | 2007 | 1102 | jeff_bzdelik | Air Force | mwc |
23 | 2008 | 1102 | jeff_reynolds | Air Force | mwc |
24 | 2009 | 1102 | jeff_reynolds | Air Force | mwc |
Next I will import the compact results as well as the tournament seeds files. Then merge the results with the seeds to create a data frame with all of the results as well as the winning seed and losing seed. I also had to clean the seed values as the seeds included a letter denoting which region the seed was in. All I cared about was the number of the seed, for more explanation and description of the function used see the Basic Starter Kernel - NCAA Men’s Dataset.
results = pd.read_csv("NCAATourneyCompactResults.csv")
seeds = pd.read_csv("NCAATourneySeeds.csv")
# convert and remove string characters from seed values
# borrowed from the Kaggle NCAA 2018 Men's competition tutorial notebook.
def seed_to_int(seed):
#Get just the digits from the seeding. Return as int
s_int = int(seed[1:3])
return s_int
seeds['seed_int'] = seeds.Seed.apply(seed_to_int)
seeds.drop(labels=['Seed'], inplace=True, axis=1) # This is the string label
seedResults = results.merge(seeds, right_on=["TeamID","Season"], left_on= ["WTeamID","Season"]).merge(seeds, right_on=["TeamID","Season"], left_on= ["LTeamID","Season"])
seedResults.drop(["TeamID_x", "TeamID_y"],axis = 1, inplace=True)
seedResults.rename(index=str, columns={"seed_int_x":"WSeed", "seed_int_y":"LSeed"}, inplace=True)
seedResults.head(10)
Season | DayNum | WTeamID | WScore | LTeamID | LScore | WLoc | NumOT | WSeed | LSeed | |
---|---|---|---|---|---|---|---|---|---|---|
0 | 1985 | 136 | 1116 | 63 | 1234 | 54 | N | 0 | 9 | 8 |
1 | 1985 | 136 | 1120 | 59 | 1345 | 58 | N | 0 | 11 | 6 |
2 | 1985 | 138 | 1120 | 66 | 1242 | 64 | N | 0 | 11 | 3 |
3 | 1985 | 136 | 1207 | 68 | 1250 | 43 | N | 0 | 1 | 16 |
4 | 1985 | 138 | 1207 | 63 | 1396 | 46 | N | 0 | 1 | 8 |
5 | 1985 | 143 | 1207 | 65 | 1260 | 53 | N | 0 | 1 | 4 |
6 | 1985 | 145 | 1207 | 60 | 1210 | 54 | N | 0 | 1 | 2 |
7 | 1985 | 152 | 1207 | 77 | 1385 | 59 | N | 0 | 1 | 1 |
8 | 1985 | 136 | 1229 | 58 | 1425 | 55 | N | 0 | 9 | 8 |
9 | 1985 | 136 | 1242 | 49 | 1325 | 38 | N | 0 | 3 | 14 |
Next I needed to merge the seed results with the team information
allResults = seedResults.merge(allTeams, right_on=["TeamID","Season"], left_on= ["WTeamID","Season"]).merge(allTeams, right_on=["TeamID","Season"], left_on= ["LTeamID","Season"])
def xyToWL(colNames):
"""
Convert suffix _x and _y to prefix W and L respectively.
Parameters
----------
colNames : list
List of column names to convert
Returns
-------
list
New column names converted to WColumnName from ColumnName_x
"""
newCols = []
for col in colNames:
if col.endswith("_x"):
newCol = col.replace("_x", "")
newCol = "W" + newCol
newCols.append(newCol)
elif col.endswith("_y"):
newCol = col.replace("_y", "")
newCol = "L" + newCol
newCols.append(newCol)
else:
newCols.append(col)
return newCols
# drop repeated w team id and l team id
allResults.drop(["TeamID_x", "TeamID_y"], axis=1, inplace=True)
allResults.drop_duplicates(inplace=True)
# Convert suffixed columns
allResults.columns = xyToWL(allResults.columns)
allResults = allResults[~((allResults.WSeed ==16) & (allResults.LSeed == 16))]
allResults.sort_values(["Season","DayNum"], inplace=True)
allResults.head(15)
Season | DayNum | WTeamID | WScore | LTeamID | LScore | WLoc | NumOT | WSeed | LSeed | WCoachName | WTeamName | WConfAbbrev | LCoachName | LTeamName | LConfAbbrev | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 1985 | 136 | 1116 | 63 | 1234 | 54 | N | 0 | 9 | 8 | eddie_sutton | Arkansas | swc | george_raveling | Iowa | big_ten |
1 | 1985 | 136 | 1120 | 59 | 1345 | 58 | N | 0 | 11 | 6 | sonny_smith | Auburn | sec | gene_keady | Purdue | big_ten |
3 | 1985 | 136 | 1207 | 68 | 1250 | 43 | N | 0 | 1 | 16 | john_thompson_jr | Georgetown | big_east | tom_schneider | Lehigh | ecc |
8 | 1985 | 136 | 1229 | 58 | 1425 | 55 | N | 0 | 9 | 8 | bob_donewald | Illinois St | mvc | stan_morrison | USC | pac_ten |
9 | 1985 | 136 | 1242 | 49 | 1325 | 38 | N | 0 | 3 | 14 | larry_brown | Kansas | big_eight | danny_nee | Ohio | mac |
10 | 1985 | 136 | 1246 | 66 | 1449 | 58 | N | 0 | 12 | 5 | joe_b_hall | Kentucky | sec | marv_harshman | Washington | pac_ten |
12 | 1985 | 136 | 1256 | 78 | 1338 | 54 | N | 0 | 5 | 12 | andy_russo | Louisiana Tech | southland | roy_chipman | Pittsburgh | big_east |
14 | 1985 | 136 | 1260 | 59 | 1233 | 58 | N | 0 | 4 | 13 | gene_sullivan | Loyola-Chicago | mw_city | pat_kennedy | Iona | maac |
16 | 1985 | 136 | 1314 | 76 | 1292 | 57 | N | 0 | 2 | 15 | dean_smith | North Carolina | acc | bruce_stewart | MTSU | ovc |
19 | 1985 | 136 | 1323 | 79 | 1333 | 70 | N | 0 | 7 | 10 | digger_phelps | Notre Dame | ind | ralph_miller | Oregon St | pac_ten |
20 | 1985 | 136 | 1326 | 75 | 1235 | 64 | N | 0 | 4 | 13 | eldon_miller | Ohio St | big_ten | johnny_orr | Iowa St | big_eight |
21 | 1985 | 136 | 1328 | 96 | 1299 | 83 | N | 0 | 1 | 16 | billy_tubbs | Oklahoma | big_eight | don_corbett | NC A&T | meac |
24 | 1985 | 136 | 1374 | 85 | 1330 | 68 | N | 0 | 5 | 12 | dave_bliss | SMU | swc | paul_webb | Old Dominion | sun_belt |
25 | 1985 | 136 | 1385 | 83 | 1380 | 59 | N | 0 | 1 | 16 | lou_carnesecca | St John's | big_east | robert_hopkins | Southern Univ | swac |
29 | 1985 | 136 | 1396 | 60 | 1439 | 57 | N | 0 | 8 | 9 | john_chaney | Temple | a_ten | charles_moir | Virginia Tech | metro |
Next I needed to calculate the expected wins (EWins) for each seed. To do this I grouped and merged the allResults
dataframe on the seeds to give the totalWins
, totalLosses
, and WPct
for each seed. I then calculated the EWins
using the following formula:
Note: The 4 in the denominator is due to the fact that each seed has 4 teams per year.
bySeed = mergeWL(allResults, "Seed")
# EWins is yearly expected wins per team by their seed. --> totalWins / 4 * number of seasons (4 due to 4 different seeds every year)
bySeed["EWins"] = bySeed.totalWins/(4*seedResults.Season.nunique())
bySeed = bySeed.round(decimals=3)
bySeed.head(16)
Seed | totalWins | totalLosses | WPct | EWins | |
---|---|---|---|---|---|
0 | 1 | 446.0 | 115 | 0.795 | 3.379 |
1 | 2 | 320.0 | 130 | 0.711 | 2.424 |
2 | 3 | 245.0 | 131 | 0.652 | 1.856 |
3 | 4 | 207.0 | 131 | 0.612 | 1.568 |
4 | 5 | 145.0 | 133 | 0.522 | 1.098 |
5 | 6 | 149.0 | 133 | 0.528 | 1.129 |
6 | 7 | 123.0 | 132 | 0.482 | 0.932 |
7 | 8 | 97.0 | 132 | 0.424 | 0.735 |
8 | 9 | 74.0 | 132 | 0.359 | 0.561 |
9 | 10 | 83.0 | 134 | 0.382 | 0.629 |
10 | 11 | 89.0 | 144 | 0.382 | 0.674 |
11 | 12 | 71.0 | 135 | 0.345 | 0.538 |
12 | 13 | 33.0 | 133 | 0.199 | 0.250 |
13 | 14 | 24.0 | 134 | 0.152 | 0.182 |
14 | 15 | 9.0 | 133 | 0.063 | 0.068 |
15 | 16 | 0.0 | 133 | 0.000 | 0.000 |
# helper function mergeWL
def mergeWL(resDF, onCol):
'''
Group resDF by onCol and count totalWins, total Losses and WPct
Parameters
----------
resDF : pandas.dataframe
Dataframe of results to filter and group wins and losses
onCol: str
String of column to group by
Returns
-------
pandas.dataframe
New dataframe with wins, losses, and WPct calculated.
'''
wins = resDF.groupby("W"+onCol, as_index=False)["WTeamID"].agg(['count']).rename(columns={'count': 'totalWins'})
loss = resDF.groupby("L"+onCol, as_index=False)["LTeamID"].agg(['count']).rename(columns={'count': 'totalLosses'})
comb = wins.merge(loss, how="right", left_index = True, right_index = True)
comb.reset_index(inplace=True)
comb.rename(columns={comb.columns[0]:onCol}, inplace=True)
comb["WPct"] = comb.totalWins/(comb.totalWins + comb.totalLosses)
comb.fillna(0, inplace=True)
return comb
Finally on to calculating coach wins, losses, and the average of their wins added based on their seed (AvgWinsAdded
). To start I grouped and merged allResults
by CoachName
.
byCoach = mergeWL(allResults, "CoachName")
byCoach.head(10)
CoachName | totalWins | totalLosses | WPct | |
---|---|---|---|---|
0 | al_brown | 0.0 | 1 | 0.000000 |
1 | al_skinner | 8.0 | 9 | 0.470588 |
2 | alan_leforce | 1.0 | 2 | 0.333333 |
3 | andrew_toole | 0.0 | 1 | 0.000000 |
4 | andy_enfield | 4.0 | 3 | 0.571429 |
5 | andy_kennedy | 2.0 | 2 | 0.500000 |
6 | andy_russo | 2.0 | 2 | 0.500000 |
7 | andy_stoglin | 0.0 | 2 | 0.000000 |
8 | anthony_evans | 1.0 | 1 | 0.500000 |
9 | anthony_grant | 1.0 | 3 | 0.250000 |
Next I calculated the average seed (avgSeed
) and number of appearances (Appearances
) for each coach.
avgSeed = byCoachSeed.groupby("CoachName", as_index=False).agg({'Seed': "mean", 'Season': 'count'})
avgSeed.rename(columns={"Seed":"AvgSeed", "Season":"Appearances"}, inplace=True)
byCoach = byCoach.merge(avgSeed,on="CoachName").round(3)
byCoach["totalWins"] = byCoach["totalWins"].astype(int)
byCoach.head(10)
CoachName | totalWins | totalLosses | WPct | AvgSeed | Appearances | |
---|---|---|---|---|---|---|
0 | al_brown | 0 | 1 | 0.000 | 14.000 | 1 |
1 | al_skinner | 8 | 9 | 0.471 | 6.556 | 9 |
2 | alan_leforce | 1 | 2 | 0.333 | 12.000 | 2 |
3 | andrew_toole | 0 | 1 | 0.000 | 16.000 | 1 |
4 | andy_enfield | 4 | 3 | 0.571 | 11.333 | 3 |
5 | andy_kennedy | 2 | 2 | 0.500 | 11.500 | 2 |
6 | andy_russo | 2 | 2 | 0.500 | 8.500 | 2 |
7 | andy_stoglin | 0 | 2 | 0.000 | 16.000 | 2 |
8 | anthony_evans | 1 | 1 | 0.500 | 15.000 | 1 |
9 | anthony_grant | 1 | 3 | 0.250 | 10.333 | 3 |
Finally I needed to calculate the number of wins added per year by each coach. To do this I created another dataframe called byCoachSeed
to hold all of the wins and losses grouped by coach and season. Using this dataframe I was able to count the number of wins each year by each team (coach) to get their wins in the tournament for that year. Also I calculated the difference between average wins by seed and the actual wins that year for that coach(Diff
).
winCoachSeed = allResults.groupby(["WCoachName", "Season"], as_index=False)["WSeed"].mean()
lossCoachSeed = allResults.groupby(["LCoachName", "Season"], as_index=False)["LSeed"].mean()
winCoachSeed.rename(columns={"WCoachName":"CoachName","WSeed":"Seed"}, inplace=True)
lossCoachSeed.rename(columns={"LCoachName":"CoachName","LSeed":"Seed"}, inplace=True)
byCoachSeed = winCoachSeed.append(lossCoachSeed,ignore_index=True).drop_duplicates().sort_values(["CoachName", "Season"])
byCoachSeed.reset_index(drop=True, inplace=True)
coachWins = allResults.groupby(["WCoachName", "Season"], as_index=False)["WSeed"].count().rename(columns={"WSeed":"TourneyWins","WCoachName":"CoachName"})
byCoachSeed = byCoachSeed.merge(coachWins, how="left",on=["CoachName", "Season"]).fillna(0)
byCoachSeed["TourneyWins"] = byCoachSeed["TourneyWins"].astype(int)
byCoachSeed = byCoachSeed.merge(bySeed[["Seed", "EWins"]], how="left", on="Seed").fillna(0)
byCoachSeed["Diff"] = byCoachSeed.TourneyWins - byCoachSeed.EWins
byCoachSeed.head(15)
CoachName | Season | Seed | TourneyWins | EWins | Diff | |
---|---|---|---|---|---|---|
0 | al_brown | 1986 | 14 | 0 | 0.182 | -0.182 |
1 | al_skinner | 1993 | 8 | 1 | 0.735 | 0.265 |
2 | al_skinner | 1997 | 9 | 0 | 0.561 | -0.561 |
3 | al_skinner | 2001 | 3 | 1 | 1.856 | -0.856 |
4 | al_skinner | 2002 | 11 | 0 | 0.674 | -0.674 |
5 | al_skinner | 2004 | 6 | 2 | 1.129 | 0.871 |
6 | al_skinner | 2005 | 4 | 1 | 1.568 | -0.568 |
7 | al_skinner | 2006 | 4 | 2 | 1.568 | 0.432 |
8 | al_skinner | 2007 | 7 | 1 | 0.932 | 0.068 |
9 | al_skinner | 2009 | 7 | 0 | 0.932 | -0.932 |
10 | alan_leforce | 1991 | 10 | 0 | 0.629 | -0.629 |
11 | alan_leforce | 1992 | 14 | 1 | 0.182 | 0.818 |
12 | andrew_toole | 2015 | 16 | 0 | 0.000 | 0.000 |
13 | andy_enfield | 2013 | 15 | 2 | 0.068 | 1.932 |
14 | andy_enfield | 2016 | 8 | 0 | 0.735 | -0.735 |
To get the AvgWinsAdded
for each coach I was able to group byCoachSeed
from above on the coaches
coachTotalEWins = byCoachSeed.groupby("CoachName", as_index=False)["Diff"].mean()
byCoach = byCoach.merge(coachTotalEWins, how="left", on="CoachName").rename(columns={"Diff":"AvgWinsAdded"})
byCoach.sort_values("AvgWinsAdded",ascending=False, inplace=True)
byCoach.reset_index(drop=True, inplace=True)
byCoach.head(15)
CoachName | totalWins | totalLosses | WPct | AvgSeed | Appearances | AvgWinsAdded | |
---|---|---|---|---|---|---|---|
0 | kevin_ollie | 7 | 1 | 0.875 | 8.0 | 2 | 2.7535 |
1 | john_giannini | 3 | 1 | 0.750 | 13.0 | 1 | 2.7500 |
2 | jim_rosborough | 5 | 1 | 0.833 | 2.0 | 1 | 2.5760 |
3 | kevin_mackey | 2 | 1 | 0.667 | 14.0 | 1 | 1.8180 |
4 | brad_stevens | 12 | 5 | 0.706 | 7.0 | 5 | 1.5090 |
5 | rollie_massimino | 11 | 4 | 0.733 | 9.0 | 5 | 1.4816 |
6 | russ_pennell | 2 | 1 | 0.667 | 12.0 | 1 | 1.4620 |
7 | darrin_horn | 2 | 1 | 0.667 | 12.0 | 1 | 1.4620 |
8 | jim_brandenburg | 2 | 1 | 0.667 | 12.0 | 1 | 1.4620 |
9 | joe_b_hall | 2 | 1 | 0.667 | 12.0 | 1 | 1.4620 |
10 | michael_white | 3 | 1 | 0.750 | 4.0 | 1 | 1.4320 |
11 | craig_esherick | 2 | 1 | 0.667 | 10.0 | 1 | 1.3710 |
12 | johnny_dawkins | 2 | 1 | 0.667 | 10.0 | 1 | 1.3710 |
13 | todd_lickliter | 4 | 2 | 0.667 | 8.5 | 2 | 1.1820 |
14 | greg_gard | 4 | 2 | 0.667 | 7.5 | 2 | 1.1665 |
Kevin Ollie leads the pack! He took a 7 seed to the Final Four and won it the next year. However I am more focused on coaches that have more lasting impact. Let’s limit it to 3 tournament appearances.
Top 50 Coaches by Average Wins Above Seed
byCoach3App = byCoach[byCoach["Appearances"] >= 3].reset_index(drop=True)
byCoach3App.head(50)
CoachName | totalWins | totalLosses | WPct | AvgSeed | Appearances | AvgWinsAdded | |
---|---|---|---|---|---|---|---|
0 | brad_stevens | 12 | 5 | 0.706 | 7.000 | 5 | 1.509000 |
1 | rollie_massimino | 11 | 4 | 0.733 | 9.000 | 5 | 1.481600 |
2 | richard_williams | 6 | 3 | 0.667 | 5.000 | 3 | 0.902000 |
3 | larry_brown | 13 | 4 | 0.765 | 4.200 | 5 | 0.881800 |
4 | john_groce | 4 | 3 | 0.571 | 11.333 | 3 | 0.878667 |
5 | andy_enfield | 4 | 3 | 0.571 | 11.333 | 3 | 0.841000 |
6 | frank_martin | 10 | 5 | 0.667 | 6.600 | 5 | 0.827400 |
7 | billy_donovan | 35 | 12 | 0.745 | 4.071 | 14 | 0.733857 |
8 | john_beilein | 19 | 11 | 0.633 | 7.818 | 11 | 0.725182 |
9 | paul_westhead | 4 | 3 | 0.571 | 11.000 | 3 | 0.719667 |
10 | sonny_smith | 7 | 5 | 0.583 | 9.400 | 5 | 0.716600 |
11 | tom_izzo | 47 | 20 | 0.701 | 4.950 | 20 | 0.702250 |
12 | bill_guthridge | 8 | 3 | 0.727 | 4.000 | 3 | 0.676667 |
13 | stan_heath | 5 | 4 | 0.556 | 10.500 | 4 | 0.640000 |
14 | rick_pitino | 54 | 18 | 0.750 | 3.550 | 20 | 0.615500 |
15 | john_calipari | 52 | 17 | 0.754 | 2.889 | 18 | 0.564389 |
16 | quin_snyder | 5 | 4 | 0.556 | 9.000 | 4 | 0.552750 |
17 | jerry_tarkanian | 22 | 8 | 0.733 | 4.111 | 9 | 0.496556 |
18 | p_j_carlesimo | 12 | 7 | 0.632 | 5.000 | 6 | 0.488667 |
19 | lefty_driesell | 5 | 4 | 0.556 | 8.750 | 4 | 0.487000 |
20 | dick_tarrant | 3 | 4 | 0.429 | 13.250 | 4 | 0.456500 |
21 | denny_crum | 21 | 11 | 0.656 | 5.583 | 12 | 0.448917 |
22 | archie_miller | 5 | 4 | 0.556 | 9.000 | 4 | 0.447000 |
23 | jim_calhoun | 48 | 17 | 0.738 | 4.500 | 20 | 0.435650 |
24 | roy_williams | 77 | 24 | 0.762 | 2.741 | 27 | 0.409593 |
25 | steve_fisher | 26 | 14 | 0.650 | 6.267 | 15 | 0.403000 |
26 | dean_smith | 37 | 13 | 0.740 | 2.615 | 13 | 0.393923 |
27 | thomas_penders | 12 | 11 | 0.522 | 9.636 | 11 | 0.382273 |
28 | tommy_amaker | 4 | 5 | 0.444 | 12.200 | 5 | 0.372600 |
29 | jim_j_o'brien | 11 | 7 | 0.611 | 5.857 | 7 | 0.368143 |
30 | dan_monson | 3 | 3 | 0.500 | 10.000 | 3 | 0.366000 |
31 | steve_donahue | 2 | 3 | 0.400 | 13.333 | 3 | 0.366000 |
32 | chris_mack | 10 | 8 | 0.556 | 7.571 | 7 | 0.335429 |
33 | bo_ryan | 27 | 15 | 0.643 | 5.200 | 15 | 0.332867 |
34 | clem_haskins | 11 | 7 | 0.611 | 6.714 | 7 | 0.326714 |
35 | sean_miller | 19 | 10 | 0.655 | 5.200 | 10 | 0.325000 |
36 | mike_krzyzewski | 92 | 28 | 0.767 | 2.219 | 32 | 0.313219 |
37 | pete_gillen | 8 | 10 | 0.444 | 10.444 | 9 | 0.306333 |
38 | paul_hewitt | 7 | 6 | 0.538 | 8.167 | 6 | 0.300500 |
39 | bill_frieder | 14 | 6 | 0.700 | 4.429 | 7 | 0.298714 |
40 | gary_williams | 28 | 15 | 0.651 | 5.375 | 16 | 0.294063 |
41 | nolan_richardson_jr | 26 | 13 | 0.667 | 5.500 | 14 | 0.291714 |
42 | ben_jacobson | 4 | 4 | 0.500 | 9.250 | 4 | 0.282250 |
43 | jim_boeheim | 52 | 25 | 0.675 | 4.038 | 26 | 0.278962 |
44 | jim_valvano | 8 | 5 | 0.615 | 5.600 | 5 | 0.277400 |
45 | mike_anderson | 9 | 8 | 0.529 | 8.250 | 8 | 0.276500 |
46 | gary_waters | 2 | 3 | 0.400 | 12.333 | 3 | 0.275333 |
47 | billy_kennedy | 3 | 3 | 0.500 | 10.333 | 3 | 0.275333 |
48 | fang_mitchell | 1 | 3 | 0.250 | 15.000 | 3 | 0.265333 |
49 | wimp_sanderson | 11 | 7 | 0.611 | 5.143 | 7 | 0.259857 |
Bottom 50 Coaches
byCoach3App.tail(50)
CoachName | totalWins | totalLosses | WPct | AvgSeed | Appearances | AvgWinsAdded | |
---|---|---|---|---|---|---|---|
198 | scott_nagy | 0 | 3 | 0.000 | 13.000 | 3 | -0.323333 |
199 | bryce_drew | 0 | 3 | 0.000 | 12.000 | 3 | -0.331000 |
200 | seth_greenberg | 1 | 3 | 0.250 | 9.667 | 3 | -0.340667 |
201 | dave_odom | 10 | 9 | 0.526 | 5.222 | 9 | -0.341667 |
202 | bobby_lutz | 2 | 5 | 0.286 | 7.800 | 5 | -0.342600 |
203 | mark_fox | 2 | 5 | 0.286 | 8.200 | 5 | -0.369800 |
204 | mike_montgomery | 18 | 16 | 0.529 | 6.188 | 16 | -0.386000 |
205 | kevin_stallings | 6 | 9 | 0.400 | 6.778 | 9 | -0.388778 |
206 | leonard_hamilton | 7 | 8 | 0.467 | 6.125 | 8 | -0.403375 |
207 | wayne_tinkle | 0 | 4 | 0.000 | 11.750 | 4 | -0.403500 |
208 | fran_dunphy | 3 | 16 | 0.158 | 10.625 | 16 | -0.407125 |
209 | tom_asbury | 0 | 4 | 0.000 | 12.250 | 4 | -0.416750 |
210 | ray_mccallum | 0 | 3 | 0.000 | 12.667 | 3 | -0.426667 |
211 | jud_heathcote | 7 | 7 | 0.500 | 5.143 | 7 | -0.441429 |
212 | tad_boyle | 1 | 4 | 0.200 | 9.250 | 4 | -0.443250 |
213 | greg_mcdermott | 3 | 7 | 0.300 | 8.429 | 7 | -0.448143 |
214 | speedy_morris | 1 | 4 | 0.200 | 9.500 | 4 | -0.450750 |
215 | kelvin_sampson | 12 | 14 | 0.462 | 6.429 | 14 | -0.454571 |
216 | gene_bartow | 2 | 5 | 0.286 | 8.200 | 5 | -0.459200 |
217 | riley_wallace | 0 | 3 | 0.000 | 11.667 | 3 | -0.472333 |
218 | larry_eustachy | 4 | 5 | 0.444 | 6.800 | 5 | -0.478800 |
219 | rick_stansbury | 4 | 6 | 0.400 | 6.667 | 6 | -0.487333 |
220 | travis_ford | 1 | 6 | 0.143 | 8.833 | 6 | -0.492500 |
221 | rich_herrin | 0 | 3 | 0.000 | 11.667 | 3 | -0.495000 |
222 | randy_ayers | 6 | 3 | 0.667 | 3.333 | 3 | -0.497667 |
223 | jamie_dixon | 12 | 12 | 0.500 | 5.091 | 11 | -0.498000 |
224 | gene_keady | 18 | 15 | 0.545 | 4.933 | 15 | -0.500133 |
225 | ed_cooley | 1 | 4 | 0.200 | 9.250 | 4 | -0.509500 |
226 | bob_wenzel | 0 | 3 | 0.000 | 10.000 | 3 | -0.515333 |
227 | lou_henson | 9 | 11 | 0.450 | 5.800 | 10 | -0.533300 |
228 | skip_prosser | 6 | 9 | 0.400 | 7.222 | 9 | -0.536111 |
229 | steve_cleveland | 0 | 3 | 0.000 | 12.000 | 3 | -0.538000 |
230 | jerry_green | 3 | 5 | 0.375 | 6.000 | 5 | -0.547000 |
231 | john_thompson_iii | 9 | 10 | 0.474 | 5.800 | 10 | -0.586300 |
232 | billy_tubbs | 14 | 8 | 0.636 | 2.875 | 8 | -0.609875 |
233 | hugh_durham | 1 | 4 | 0.200 | 8.000 | 4 | -0.617500 |
234 | tony_bennett | 10 | 7 | 0.588 | 3.714 | 7 | -0.619000 |
235 | pat_foster | 0 | 3 | 0.000 | 10.000 | 3 | -0.634000 |
236 | rob_evans | 1 | 3 | 0.250 | 7.333 | 3 | -0.644000 |
237 | norm_stewart | 7 | 10 | 0.412 | 5.900 | 10 | -0.665900 |
238 | jeff_mullins | 0 | 3 | 0.000 | 9.000 | 3 | -0.704667 |
239 | tim_welsh | 0 | 3 | 0.000 | 9.000 | 3 | -0.755000 |
240 | ralph_miller | 0 | 3 | 0.000 | 9.333 | 3 | -0.765333 |
241 | george_raveling | 1 | 4 | 0.200 | 7.750 | 4 | -0.865500 |
242 | danny_nee | 0 | 6 | 0.000 | 8.667 | 6 | -0.867500 |
243 | oliver_purnell | 0 | 6 | 0.000 | 8.167 | 6 | -0.878667 |
244 | frank_haith | 1 | 4 | 0.200 | 7.250 | 4 | -0.897750 |
245 | j_d_barnett | 1 | 3 | 0.250 | 7.667 | 3 | -0.909000 |
246 | eddie_fogler | 2 | 6 | 0.250 | 6.667 | 6 | -0.984833 |
247 | steve_lappas | 2 | 4 | 0.333 | 4.500 | 4 | -1.003750 |
Conclusion
Looking at the Top 50 and bottom 50 provide some insights. Tony Bennett is in the bottom 10% (234 out of 247). Maybe defense doesn’t win championships? Also if Pitt wasn’t happy with Jamie Dixon and his teams’ tournament performance, Kevin Stallings might not have been much of an improvement. On the positive side I can see why Brad Stevens has had success in both NCAA and NBA as he leads the group of coaches with 3 or more appearances. Also a lot of the legends (Izzo, Pitino, Calipari) are up towards the top as well.
Some teams to watch next year if they make the tournament could be Indiana (Archie Miller), South Carolina (Frank Martin), and Michigan (John Beilein). It would be nice to add the results from this year’s tournament as some of these values might change. Beilein would improve as he took #3 Michigan to the Final and Tony Bennett will fall even further.