Case Study 1.1: The Houston Rockets' Analytical Revolution
Overview
This case study examines how the Houston Rockets, under General Manager Daryl Morey (2007-2020), became the most analytically-driven organization in the NBA and fundamentally changed how teams approach shot selection.
Background
When Daryl Morey was hired as the Houston Rockets' General Manager in 2007, he brought a different perspective to basketball operations. With an MBA from MIT Sloan and a background in consulting rather than playing or traditional scouting, Morey approached basketball as an optimization problem.
His core insight was simple: basketball teams should maximize expected points per possession. This led to identifying which shots were most efficient and building a team designed to take those shots.
The Data Analysis
Shot Efficiency by Zone
Morey's analytics team analyzed shot efficiency across different court locations. Their findings, consistent with broader research, showed dramatic efficiency differences:
| Shot Zone | Approximate FG% | Expected Points |
|---|---|---|
| Restricted Area (0-4 ft) | 62% | 1.24 |
| Paint (Non-RA) (4-14 ft) | 40% | 0.80 |
| Mid-Range (14 ft - 3PT line) | 40% | 0.80 |
| Corner Three | 39% | 1.17 |
| Above-the-Break Three | 35% | 1.05 |
import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
# Shot efficiency data
shot_zones = pd.DataFrame({
'Zone': ['Restricted Area', 'Paint (Non-RA)', 'Mid-Range',
'Corner Three', 'Above-Break Three'],
'FG_Pct': [0.62, 0.40, 0.40, 0.39, 0.35],
'Point_Value': [2, 2, 2, 3, 3]
})
# Calculate expected points
shot_zones['Expected_Points'] = shot_zones['FG_Pct'] * shot_zones['Point_Value']
# Visualize
fig, ax = plt.subplots(figsize=(10, 6))
colors = ['#2ecc71', '#e74c3c', '#e74c3c', '#3498db', '#3498db']
bars = ax.bar(shot_zones['Zone'], shot_zones['Expected_Points'], color=colors)
ax.axhline(y=1.0, color='gray', linestyle='--', label='1.0 Expected Points')
ax.set_ylabel('Expected Points per Attempt')
ax.set_title('Shot Efficiency by Zone')
ax.set_ylim(0, 1.4)
for bar, val in zip(bars, shot_zones['Expected_Points']):
ax.text(bar.get_x() + bar.get_width()/2, bar.get_height() + 0.02,
f'{val:.2f}', ha='center', fontsize=10)
plt.xticks(rotation=45, ha='right')
plt.tight_layout()
plt.legend()
plt.savefig('shot_efficiency.png', dpi=150)
plt.show()
The "Moreyball" Shot Distribution
Based on this analysis, Morey's Rockets aimed to: 1. Maximize layups and dunks: Highest efficiency shots 2. Maximize three-point attempts: High expected value 3. Eliminate mid-range shots: Lowest efficiency
This became known as "Moreyball"—a shot distribution clustered at the rim and behind the three-point line, with minimal mid-range attempts.
Implementation
Player Acquisition Strategy
Morey built rosters specifically designed for this shot profile:
James Harden (acquired 2012) Harden's ability to draw fouls, score at the rim, and create three-point opportunities made him the ideal Moreyball player. His step-back three-pointer became signature.
Role Players The Rockets consistently signed players who could: - Shoot corner threes at high volume - Finish at the rim - Space the floor
Players like Trevor Ariza, P.J. Tucker, and Eric Gordon fit this mold perfectly.
Avoiding "Empty Stats" The Rockets avoided players whose value came from inefficient mid-range shooting, regardless of reputation.
# Example: Comparing player fit with Moreyball philosophy
def moreyball_fit_score(player_stats):
"""
Calculate how well a player fits Moreyball philosophy.
Args:
player_stats: Dictionary with shooting data
- rim_attempts: Shots at rim as % of total
- three_attempts: Three-pointers as % of total
- midrange_attempts: Mid-range as % of total
- rim_pct: FG% at rim
- three_pct: 3P%
Returns:
Fit score from 0-100
"""
# Weight shot distribution (higher rim and 3PT = better)
distribution_score = (
player_stats['rim_attempts'] * 0.4 +
player_stats['three_attempts'] * 0.4 +
(1 - player_stats['midrange_attempts']) * 0.2
) * 100
# Weight efficiency (higher = better)
efficiency_score = (
(player_stats['rim_pct'] / 0.65) * 0.5 + # 65% at rim is excellent
(player_stats['three_pct'] / 0.40) * 0.5 # 40% from 3 is excellent
) * 100
return min(100, (distribution_score * 0.6 + efficiency_score * 0.4))
# Example players
harden_2019 = {
'rim_attempts': 0.28,
'three_attempts': 0.45,
'midrange_attempts': 0.12,
'rim_pct': 0.64,
'three_pct': 0.368
}
traditional_big = {
'rim_attempts': 0.35,
'three_attempts': 0.05,
'midrange_attempts': 0.40,
'rim_pct': 0.60,
'three_pct': 0.30
}
print(f"James Harden Moreyball Fit: {moreyball_fit_score(harden_2019):.1f}")
print(f"Traditional Big Moreyball Fit: {moreyball_fit_score(traditional_big):.1f}")
Offensive System Design
The Rockets' offense was built to generate specific shot types:
Isolation-Heavy Attack Rather than complex motion offenses, the Rockets relied on Harden's ability to create in isolation. This might seem counter-intuitive, but: - Harden's iso efficiency was elite - It generated fouls at a historic rate - It created open three-pointers for teammates
Small Ball By 2020, the Rockets went fully "small ball," playing 6'5" P.J. Tucker at center. This: - Maximized floor spacing - Eliminated inefficient post-up plays - Created more rim attack opportunities
Results
Team Performance
| Season | Wins | Off Rating Rank | 3PA/Game | 3PA Rank |
|---|---|---|---|---|
| 2016-17 | 55 | 3rd | 40.3 | 1st |
| 2017-18 | 65 | 1st | 42.3 | 1st |
| 2018-19 | 53 | 4th | 45.4 | 1st |
| 2019-20 | 44 | 5th | 45.3 | 1st |
The Rockets consistently had elite offenses and led the league in three-point attempts.
Individual Success
James Harden's individual statistics under Moreyball:
- Scoring Titles: 3 consecutive (2018-2020)
- Points Per Game: 36.1 in 2018-19 (highest since 1987)
- True Shooting %: Consistently among league leaders
- MVP: 2018
# Harden's scoring evolution
harden_seasons = pd.DataFrame({
'Season': ['2016-17', '2017-18', '2018-19', '2019-20'],
'PPG': [29.1, 30.4, 36.1, 34.3],
'TS%': [0.613, 0.619, 0.616, 0.626],
'Three_Attempts': [9.3, 10.0, 13.2, 12.4],
'FT_Attempts': [10.9, 10.1, 11.0, 11.8]
})
fig, axes = plt.subplots(1, 2, figsize=(14, 5))
# Scoring and efficiency
ax1 = axes[0]
ax1.bar(harden_seasons['Season'], harden_seasons['PPG'], color='#BA0C2F')
ax1.set_ylabel('Points Per Game')
ax1.set_title('Harden Scoring by Season')
ax1.set_ylim(0, 40)
# Shot attempts
ax2 = axes[1]
width = 0.35
x = np.arange(len(harden_seasons['Season']))
ax2.bar(x - width/2, harden_seasons['Three_Attempts'], width, label='3PA', color='#3498db')
ax2.bar(x + width/2, harden_seasons['FT_Attempts'], width, label='FTA', color='#2ecc71')
ax2.set_xlabel('Season')
ax2.set_ylabel('Attempts per Game')
ax2.set_title('Harden 3PA and FTA by Season')
ax2.set_xticks(x)
ax2.set_xticklabels(harden_seasons['Season'])
ax2.legend()
plt.tight_layout()
plt.savefig('harden_evolution.png', dpi=150)
plt.show()
Critiques and Limitations
Playoff Performance
Despite regular season success, the Rockets never won a championship under Morey. Critics pointed to:
Playoff Defense - Small ball lineups were exploited by teams with dominant bigs - Three-point shooting became less reliable under playoff pressure
Variance in Shooting - Three-point shooting has high variance - In Game 7 of the 2018 Western Conference Finals, the Rockets missed 27 consecutive three-pointers
Predictability - Opponents could game-plan specifically for the Rockets' tendencies - Lack of mid-range threat made defense easier
League Adaptation
As other teams adopted similar approaches, the Rockets' advantage diminished: - League-wide three-point attempts increased - Defenses improved at contesting threes - The "innovation premium" disappeared
Lessons Learned
What Worked
- Evidence-based decision making: Using data to challenge conventional wisdom
- Commitment to philosophy: Fully implementing insights rather than half-measures
- Player acquisition alignment: Building rosters that fit the system
- Efficiency focus: Maximizing expected points per possession
What Could Have Been Better
- Flexibility: Too rigid adherence to shot profile
- Defensive investment: Offense-heavy roster construction
- Playoff adjustments: Inability to adapt when system was countered
Analysis Questions
-
Expected Value Calculation: If a team increases three-point attempts by 10 per game while decreasing mid-range attempts by 10, how many additional points per game would they expect to score, assuming league-average percentages?
-
Variance Analysis: Calculate the standard deviation of points scored on 40 three-point attempts vs. 40 mid-range attempts, assuming league-average percentages. Which has more variance?
-
Roster Construction: Design a hypothetical 5-man lineup optimized for Moreyball principles. What skills would you prioritize at each position?
-
Counter-Strategy: If you were coaching against the Rockets, how would you design your defensive game plan?
-
Modern Application: How have other teams adapted Moreyball principles? Are any current teams running a similar philosophy?
Code Solution: Variance Analysis
import numpy as np
from scipy import stats
def shot_variance_analysis(n_shots, fg_percentage, points_per_make):
"""
Analyze variance in scoring from a shot type.
Args:
n_shots: Number of attempts
fg_percentage: Field goal percentage
points_per_make: Points per made shot (2 or 3)
Returns:
Dictionary with expected points, variance, and confidence interval
"""
# Each shot is a binomial trial
expected_makes = n_shots * fg_percentage
expected_points = expected_makes * points_per_make
# Variance of sum of binomial trials
variance_makes = n_shots * fg_percentage * (1 - fg_percentage)
variance_points = variance_makes * (points_per_make ** 2)
std_points = np.sqrt(variance_points)
# 95% confidence interval
ci_lower = expected_points - 1.96 * std_points
ci_upper = expected_points + 1.96 * std_points
return {
'expected_points': expected_points,
'std_points': std_points,
'variance': variance_points,
'ci_95': (ci_lower, ci_upper)
}
# Compare 40 threes vs 40 mid-range shots
three_pt_analysis = shot_variance_analysis(40, 0.36, 3)
midrange_analysis = shot_variance_analysis(40, 0.40, 2)
print("40 Three-Point Attempts:")
print(f" Expected Points: {three_pt_analysis['expected_points']:.1f}")
print(f" Std Dev: {three_pt_analysis['std_points']:.2f}")
print(f" 95% CI: ({three_pt_analysis['ci_95'][0]:.1f}, {three_pt_analysis['ci_95'][1]:.1f})")
print("\n40 Mid-Range Attempts:")
print(f" Expected Points: {midrange_analysis['expected_points']:.1f}")
print(f" Std Dev: {midrange_analysis['std_points']:.2f}")
print(f" 95% CI: ({midrange_analysis['ci_95'][0]:.1f}, {midrange_analysis['ci_95'][1]:.1f})")
Conclusion
The Houston Rockets under Daryl Morey demonstrated both the power and limitations of analytics-driven basketball. Their approach proved that systematic application of efficiency principles could produce elite regular-season offenses and individual statistical performances. However, their championship drought also showed that analytics alone cannot account for all factors in basketball success, particularly in playoff environments where variance increases and opponents can specifically game-plan.
The Moreyball era's most lasting impact may be its influence on the entire league. The three-point revolution that the Rockets championed is now ubiquitous, fundamentally changing how basketball is played at all levels.
This case study is based on publicly available information and analysis. Team-specific internal analytics are not available.