as an NBA coach? How long does a typical coach last? And does their coaching background play any part in predicting success?
This evaluation was inspired by several key theories. First, there was a typical criticism amongst casual NBA fans that teams overly prefer hiring candidates with previous NBA head coaches experience.
Consequently, this evaluation goals to reply two related questions. First, is it true that NBA teams ceaselessly re-hire candidates with previous head coaching experience? And second, is there any evidence that these candidates under-perform relative to other candidates?
The second theory is that internal candidates (though infrequently hired) are sometimes more successful than external candidates. This theory was derived from a pair of anecdotes. Two of probably the most successful coaches in NBA history, Gregg Popovich of San Antonio and Erik Spoelstra of Miami, were each internal hires. Nonetheless, rigorous quantitative evidence is required to check if this relationship holds over a bigger sample.
This evaluation goals to explore these questions, and supply the code to breed the evaluation in Python.
The Data
The code (contained in a Jupyter notebook) and dataset for this project are available on Github here. The evaluation was performed using Python in Google Colaboratory.
A prerequisite to this evaluation was determining a solution to measure coaching success quantitatively. I made a decision on a straightforward idea: the success of a coach can be best measured by the length of their tenure in that job. Tenure best represents the differing expectations that is perhaps placed on a coach. A coach hired to a contending team can be expected to win games and generate deep playoff runs. A coach hired to a rebuilding team is perhaps judged on the event of younger players and their ability to construct a robust culture. If a coach meets expectations (whatever those could also be), the team will keep them around.
Since there was no existing dataset with all the required data, I collected the information myself from Wikipedia. I recorded every off-season coaching change from 1990 through 2021. For the reason that primary end result variable is tenure, in-season coaching changes were excluded since these coaches often carried an “interim” tag—meaning they were intended to be temporary until a everlasting substitute could possibly be found.
As well as, the next variables were collected:
| Variable | Definition |
| Team | The NBA team the coach was hired for |
| Yr | The yr the coach was hired |
| Coach | The name of the coach |
| Internal? | An indicator if the coach was internal or not—meaning they worked for the organization in some capability immediately prior to being hired as head coach |
| Type | The background of the coach. Categories are Previous HC (prior NBA head coaching experience), Previous AC (prior NBA assistant coaching experience, but no head coaching experience), College (head coach of a faculty team), Player (a former NBA player with no coaching experience), Management (someone with front office experience but no coaching experience), and Foreign (someone coaching outside of North America with no NBA coaching experience). |
| Years | The variety of years a coach was employed within the role. For coaches fired mid-season, the worth was counted as 0.5. |
First, the dataset is imported from its location in Google Drive. I also convert ‘Internal?’ right into a dummy variable, replacing “Yes” with 1 and “No” with 0.
from google.colab import drive
drive.mount('/content/drive')
import pandas as pd
pd.set_option('display.max_columns', None)
#Usher in the dataset
coach = pd.read_csv('/content/drive/MyDrive/Python_Files/Coaches.csv', on_bad_lines = 'skip').iloc[:,0:6]
coach['Internal'] = coach['Internal?'].map(dict(Yes=1, No=0))
coach
This prints a preview of what the dataset looks like:
In total, the dataset incorporates 221 coaching hires over this time.
Descriptive Statistics
First, basic summary Statistics are calculated and visualized to find out the backgrounds of NBA head coaches.
#Create chart of coaching background
import matplotlib.pyplot as plt
#Count variety of coaches per category
counts = coach['Type'].value_counts()
#Create chart
plt.bar(counts.index, counts.values, color = 'blue', edgecolor = 'black')
plt.title('Where Do NBA Coaches Come From?')
plt.figtext(0.76, -0.1, "Made by Brayden Gerrard", ha="center")
plt.xticks(rotation = 45)
plt.ylabel('Variety of Coaches')
plt.gca().spines['top'].set_visible(False)
plt.gca().spines['right'].set_visible(False)
for i, value in enumerate(counts.values):
plt.text(i, value + 1, str(round((value/sum(counts.values))*100,1)) + '%' + ' (' + str(value) + ')', ha='center', fontsize=9)
plt.savefig('coachtype.png', bbox_inches = 'tight')
print(str(round(((coach['Internal'] == 1).sum()/len(coach))*100,1)) + " percent of coaches are internal.")

Over half of coaching hires previously served as an NBA head coach, and nearly 90% had NBA coaching experience of some kind. This answers the primary query posed—NBA teams show a robust preference for knowledgeable head coaches. If you happen to get hired once as an NBA coach, your odds of being hired again are much higher. Moreover, 13.6% of hires are internal, confirming that teams don’t ceaselessly hire from their very own ranks.
Second, I’ll explore the everyday tenure of an NBA head coach. This will be visualized using a histogram.
#Create histogram
plt.hist(coach['Years'], bins =12, edgecolor = 'black', color = 'blue')
plt.title('Distribution of Coaching Tenure')
plt.figtext(0.76, 0, "Made by Brayden Gerrard", ha="center")
plt.annotate('Erik Spoelstra (MIA)', xy=(16.4, 2), xytext=(14 + 1, 15),
arrowprops=dict(facecolor='black', shrink=0.1), fontsize=9, color='black')
plt.gca().spines['top'].set_visible(False)
plt.gca().spines['right'].set_visible(False)
plt.savefig('tenurehist.png', bbox_inches = 'tight')
plt.show()
coach.sort_values('Years', ascending = False)
#Calculate some stats with the information
import numpy as np
print(str(np.median(coach['Years'])) + " years is the median coaching tenure length.")
print(str(round(((coach['Years'] <= 5).sum()/len(coach))*100,1)) + " percent of coaches last five years or less.")
print(str(round((coach['Years'] <= 1).sum()/len(coach)*100,1)) + " percent of coaches last a yr or less.")

Using tenure as an indicator of success, the the information clearly shows that the massive majority of coaches are unsuccessful. The median tenure is just 2.5 seasons. 18.1% of coaches last a single season or less, and barely 10% of coaches last greater than 5 seasons.
This will also be viewed as a survival evaluation plot to see the drop-off at various closing dates:
#Survival evaluation
import matplotlib.ticker as mtick
lst = np.arange(0,18,0.5)
surv = pd.DataFrame(lst, columns = ['Period'])
surv['Number'] = np.nan
for i in range(0,len(surv)):
surv.iloc[i,1] = (coach['Years'] >= surv.iloc[i,0]).sum()/len(coach)
plt.step(surv['Period'],surv['Number'])
plt.title('NBA Coach Survival Rate')
plt.xlabel('Coaching Tenure (Years)')
plt.figtext(0.76, -0.05, "Made by Brayden Gerrard", ha="center")
plt.gca().yaxis.set_major_formatter(mtick.PercentFormatter(1))
plt.gca().spines['top'].set_visible(False)
plt.gca().spines['right'].set_visible(False)
plt.savefig('coachsurvival.png', bbox_inches = 'tight')
plt.show

Lastly, a box plot will be generated to see if there are any obvious differences in tenure based on coaching type. Boxplots also display outliers for every group.
#Create a boxplot
import seaborn as sns
sns.boxplot(data=coach, x='Type', y='Years')
plt.title('Coaching Tenure by Coach Type')
plt.gca().spines['top'].set_visible(False)
plt.gca().spines['right'].set_visible(False)
plt.xlabel('')
plt.xticks(rotation = 30, ha = 'right')
plt.figtext(0.76, -0.1, "Made by Brayden Gerrard", ha="center")
plt.savefig('coachtypeboxplot.png', bbox_inches = 'tight')
plt.show

There are some differences between the groups. Apart from management hires (which have a sample of just six), previous head coaches have the longest average tenure at 3.3 years. Nonetheless, since most of the groups have small sample sizes, we'd like to make use of more advanced techniques to check if the differences are statistically significant.
Statistical Evaluation
First, to check if either Type or Internal has a statistically significant difference among the many group means, we will use ANOVA:
#ANOVA
import statsmodels.api as sm
from statsmodels.formula.api import ols
am = ols('Years ~ C(Type) + C(Internal)', data=coach).fit()
anova_table = sm.stats.anova_lm(am, typ=2)
print(anova_table)

The outcomes show high p-values and low F-stats—indicating no evidence of statistically significant difference in means. Thus, the initial conclusion is that there isn't a evidence NBA teams are under-valuing internal candidates or over-valuing previous head coaching experience as initially hypothesized.
Nonetheless, there's a possible distortion when comparing group averages. NBA coaches are signed to contracts that typically run between three and five years. Teams typically must pay out the rest of the contract even when coaches are dismissed early for poor performance. A coach that lasts two years could also be no worse than one which lasts three or 4 years—the difference could simply be attributable to the length and terms of the initial contract, which is in turn impacted by the desirability of the coach within the job market. Since coaches with prior experience are highly coveted, they might use that leverage to barter longer contracts and/or higher salaries, each of which could deter teams from terminating their employment too early.
To account for this possibility, the end result will be treated as binary slightly than continuous. If a coach lasted greater than 5 seasons, it is very likely they accomplished a minimum of their initial contract term and the team selected to increase or re-sign them. These coaches will likely be treated as successes, with those having a tenure of 5 years or less categorized as unsuccessful. To run this evaluation, all coaching hires from 2020 and 2021 should be excluded, since they've not yet been capable of eclipse 5 seasons.
With a binary dependent variable, a logistic regression will be used to check if any of the variables predict coaching success. Internal and Type are each converted to dummy variables. Since previous head coaches represent probably the most common coaching hires, I set this because the “reference” category against which the others will likely be measured against. Moreover, the dataset incorporates only one foreign-hired coach (David Blatt) so this statement is dropped from the evaluation.
#Logistic regression
coach3 = coach[coach['Year']<2020]
coach3.loc[:, 'Success'] = np.where(coach3['Years'] > 5, 1, 0)
coach_type_dummies = pd.get_dummies(coach3['Type'], prefix = 'Type').astype(int)
coach_type_dummies.drop(columns=['Type_Previous HC'], inplace=True)
coach3 = pd.concat([coach3, coach_type_dummies], axis = 1)
#Drop foreign category / David Blatt since n = 1
coach3 = coach3.drop(columns=['Type_Foreign'])
coach3 = coach3.loc[coach3['Coach'] != "David Blatt"]
print(coach3['Success'].value_counts())
x = coach3[['Internal','Type_Management','Type_Player','Type_Previous AC', 'Type_College']]
x = sm.add_constant(x)
y = coach3['Success']
logm = sm.Logit(y,x)
logm.r = logm.fit(maxiter=1000)
print(logm.r.summary())
#Convert coefficients to odds ratio
print(str(np.exp(-1.4715)) + "is the chances ratio for internal.") #Internal coefficient
print(np.exp(1.0025)) #Management
print(np.exp(-39.6956)) #Player
print(np.exp(-0.3626)) #Previous AC
print(np.exp(-0.6901)) #College

Consistent with ANOVA results, not one of the variables are statistically significant under any conventional threshold. Nonetheless, closer examination of the coefficients tells an interesting story.
The beta coefficients represent the change within the log-odds of the end result. Since that is unintuitive to interpret, the coefficients will be converted to an Odds Ratio as follows:

Internal has an odds ratio of 0.23—indicating that internal candidates are 77% less likely to achieve success in comparison with external candidates. Management has an odds ratio of two.725, indicating these candidates are 172.5% more likely to achieve success. The percentages ratios for players is effectively zero, 0.696 for previous assistant coaches, and 0.5 for school coaches. Since three out of 4 coaching type dummy variables have an odds ratio under one, this means that only management hires were more likely to achieve success than previous head coaches.
From a practical standpoint, these are large effect sizes. So why are the variables statistically insignificant?
The cause is a limited sample size of successful coaches. Out of 202 coaches remaining within the sample, just 23 (11.4%) were successful. Whatever the coach’s background, odds are low they last greater than a couple of seasons. If we take a look at the one category capable of outperform previous head coaches (management hires) specifically:
# Filter to management
manage = coach3[coach3['Type_Management'] == 1]
print(manage['Success'].value_counts())
print(manage)
The filtered dataset incorporates just 6 hires—of which only one (Steve Kerr with Golden State) is assessed as a hit. In other words, your complete effect was driven by a single successful statement. Thus, it might take a considerably larger sample size to be confident if differences exist.
With a p-value of 0.202, the Internal variable comes the closest to statistical significance (though it still falls well in need of a typical alpha of 0.05). Notably, nonetheless, the direction of the effect is definitely the alternative of what was hypothesized—internal hires are less likely to achieve success than external hires. Out of 26 internal hires, only one (Erik Spoelstra of Miami) met the factors for achievement.
Conclusion
In conclusion, this evaluation was capable of draw several key conclusions:
- No matter background, being an NBA coach is usually a short-lived job. It’s rare for a coach to last greater than a couple of seasons.
- The common wisdom that NBA teams strongly prefer to rent previous head coaches holds true. Greater than half of hires already had NBA head coaching experience.
- If teams don’t hire an experienced head coach, they’re more likely to hire an NBA assistant coach. Hires outside of those two categories are especially unusual.
- Though they're ceaselessly hired, there isn't a evidence to suggest NBA teams overly prioritize previous head coaches. On the contrary, previous head coaches stay within the job longer on average and usually tend to outlast their initial contract term—though neither of those differences are statistically significant.
- Despite high-profile anecdotes, there isn't a evidence to suggest that internal hires are more successful than external hires either.
