# Spence/Garcia, What Were the Odds of That?¶

post @ endlesspint.com

In [1]:
import numpy as np
import pandas as  pd
import matplotlib.pyplot as plt

plt.style.use('ggplot')
%matplotlib inline

from scipy.stats import binom, poisson, zscore


## (mis)Using Poisson to Get an Idea of Expected Fighter Output¶

Spence could be expected to be busier, but by how much and where?

In [2]:
np.random.seed(8)

sim_cnt_poi = 10000

spence_tot_poi, spence_jab_poi, spence_pow_poi = np.random.poisson(64, sim_cnt_poi), \
np.random.poisson(31, sim_cnt_poi), \
np.random.poisson(33, sim_cnt_poi)
garcia_tot_poi, garcia_jab_poi, garcia_pow_poi = np.random.poisson(53, sim_cnt_poi), \
np.random.poisson(32, sim_cnt_poi), \
np.random.poisson(21, sim_cnt_poi)

plt.figure(figsize=(16,6))

# SPENCE

ax1 = plt.subplot(231)
plt.hist(spence_tot_poi, 14, density=True, color='green')
plt.title("Spence Total Punches/Rd")

ax2 = plt.subplot(232, sharey=ax1)
plt.hist(spence_jab_poi, 14, density=True, color='green')
plt.title("Spence Jabs/Rd")

ax3 = plt.subplot(233, sharey=ax1)
plt.hist(spence_pow_poi, 14, density=True, color='green')
plt.title("Spence Power Punches/Rd")

# GARCIA

plt.subplot(234, sharex=ax1, sharey=ax1)
plt.hist(garcia_tot_poi, 14, density=True)
plt.title("Garcia Total Punches/Rd")

plt.subplot(235, sharex=ax2, sharey=ax1)
plt.hist(garcia_jab_poi, 14, density=True)
plt.title("Garcia Jabs/Rd")

plt.subplot(236, sharex=ax3, sharey=ax1)
plt.hist(garcia_pow_poi, 14, density=True)
plt.title("Garcia Power Punches/Rd")

plt.tight_layout()


## A look at actual thrown performance v expectations¶

In [3]:
spence_total_thrown = [46, 55, 75, 89, 86, 95, 70, 102, 121, 125, 118, 100]
spence_jabs_thrown = [39, 43, 53, 61, 62, 56, 50, 60, 56, 58, 45, 35]
spence_power_thrown = [7, 12, 22, 28, 24, 39, 20, 42, 65, 67, 73, 65]

garcia_total_thrown = [12, 28, 31, 35, 41, 43, 26, 41, 32, 62, 15, 40]
garcia_jabs_thrown = [9, 13, 18, 20, 17, 19, 10, 22, 17, 25, 2, 16]
garcia_power_thrown = [3, 15, 13, 15, 24, 24, 16, 19, 15, 37, 13, 24]


## A tale of two jabs: Spence pumped out that lead left at a ridiculous rate, neutralizing Garcia while setting-up the rest of his own offense¶

In [4]:
def chance_of_throwing_GE(sim, act):
return [np.sum(sim >= x)/len(sim) for x in  act]

spence_comp_thrown = [(spence_tot_poi, spence_total_thrown), (spence_jab_poi, spence_jabs_thrown), (spence_pow_poi, spence_power_thrown)]

garcia_comp_thrown = [(garcia_tot_poi, garcia_total_thrown), (garcia_jab_poi, garcia_jabs_thrown), (garcia_pow_poi, garcia_power_thrown)]

print("SPENCE")
for spence in spence_comp_thrown:
spence_perf = chance_of_throwing_GE(spence[0], spence[1])
print(spence_perf, np.mean(spence_perf))

print("\nGARCIA")
for garcia in garcia_comp_thrown:
garcia_perf = chance_of_throwing_GE(garcia[0], garcia[1])
print(garcia_perf, np.mean(garcia_perf))

SPENCE
[0.9912, 0.882, 0.0963, 0.0015, 0.005, 0.0001, 0.2386, 0.0, 0.0, 0.0, 0.0, 0.0] 0.18455833333333335
[0.093, 0.0245, 0.0001, 0.0, 0.0, 0.0, 0.0009, 0.0, 0.0, 0.0, 0.011, 0.2537] 0.031933333333333334
[1.0, 1.0, 0.9827, 0.8285, 0.9537, 0.1682, 0.9959, 0.0747, 0.0, 0.0, 0.0, 0.0] 0.5003083333333334

GARCIA
[1.0, 1.0, 0.9997, 0.9969, 0.9615, 0.9309, 1.0, 0.9615, 0.9992, 0.1232, 1.0, 0.9713] 0.9120166666666667
[1.0, 0.9999, 0.9971, 0.9905, 0.9981, 0.995, 1.0, 0.9725, 0.9981, 0.9089, 1.0, 0.9991] 0.9882666666666666
[1.0, 0.927, 0.978, 0.927, 0.283, 0.283, 0.8865, 0.6958, 0.927, 0.0008, 0.978, 0.283] 0.6807583333333332


## What about contact? "Everyone's gotta plan until they get hit."¶

In [5]:
s_plot = 1

fig = plt.figure(figsize=(16,6))

for stat in ((406, .298, "Garcia total", 75), (188, .209, "Garcia jabs", 21), (218, .431, "Garcia power", 54)):
n, p, category, N = stat[0], stat[1], stat[2], stat[3]
x = np.arange(binom.ppf(0.025, n, p),
binom.ppf(0.975, n, p))

sim_bouts = 10000

print("95 percent range for %s: \t" % category, int(np.min(x)), " - ", int(np.max(x)))
print("\t %s actually landed: \t" % category, N)
print("\t prob of landing this %s count or less:" % category,
"{0:.0f}%".format(np.sum(np.random.binomial(n, p, sim_bouts) < N)/float(sim_bouts) * 100))

ax.plot(x, binom.pmf(x, n, p), 'ro', ms=5, label='binom pmf')
plt.title(category)
ax.vlines(x, 0, binom.pmf(x, n, p), colors='r', lw=5, alpha=0.5)
ax.vlines(N, 0, np.max(binom.pmf(x, n, p)), lw=3, linestyles=":")
s_plot += 1

plt.tight_layout()
plt.show()

95 percent range for Garcia total: 	 103  -  138
Garcia total actually landed: 	 75
prob of landing this Garcia total count or less: 0%
95 percent range for Garcia jabs: 	 29  -  49
Garcia jabs actually landed: 	 21
prob of landing this Garcia jabs count or less: 0%
95 percent range for Garcia power: 	 80  -  107
Garcia power actually landed: 	 54
prob of landing this Garcia power count or less: 0%


## Both fighters had their rates affected but while Mikey fell off the chart, almost literally and in a bad sense, Spence's superiour activity with the jab allowed him to set up and deliver the power punches, especially in volume over the second half of the bout¶

In [6]:
s_plot = 1

fig = plt.figure(figsize=(16,6))

for stat in ((1082, .343, "Spence total", 345), (618, .198, "Spence jabs", 108), (464, .480, "Spence power", 237)):
n, p, category, N = stat[0], stat[1], stat[2], stat[3]
x = np.arange(binom.ppf(0.025, n, p),
binom.ppf(0.975, n, p))

sim_bouts = 10000

print("95 percent range for %s: \t" % category, int(np.min(x)), " - ", int(np.max(x)))
print("\t %s actually landed: \t" % category, N)
print("\t prob of landing this %s count or less:" % category,
"{0:.0f}%".format(np.sum(np.random.binomial(n, p, sim_bouts) < N)/float(sim_bouts) * 100))

ax.plot(x, binom.pmf(x, n, p), 'go', ms=5, label='binom pmf')
plt.title(category)
ax.vlines(x, 0, binom.pmf(x, n, p), colors='g', lw=5, alpha=0.5)
ax.vlines(N, 0, np.max(binom.pmf(x, n, p)), lw=3, linestyles=":")
s_plot += 1

plt.tight_layout()
plt.show()

95 percent range for Spence total: 	 341  -  401
Spence total actually landed: 	 345
prob of landing this Spence total count or less: 4%
95 percent range for Spence jabs: 	 103  -  141
Spence jabs actually landed: 	 108
prob of landing this Spence jabs count or less: 7%
95 percent range for Spence power: 	 202  -  243
Spence power actually landed: 	 237
prob of landing this Spence power count or less: 90%


## One more look at thrown punches¶

In [7]:
def standardized_fight_night(sim_rds, poi_lambda, n_times, act):
act_rds = len(act)
fight_night_zscore = np.zeros(act_rds)

for i in range(n_times):
fight_night_zscore += zscore(np.append(np.random.poisson(poi_lambda, sim_rds), act))[-act_rds:]

return fight_night_zscore/n_times

spence_total_zscore = standardized_fight_night(60, 64, 100, spence_total_thrown)
spence_total_zscore

Out[7]:
array([-1.42441765, -0.84977684,  0.42720275,  1.32108846,  1.12954152,
1.70418233,  0.10795785,  2.15112519,  3.36425579,  3.61965171,
3.17270886,  2.02342723])
In [8]:
garcia_total_zscore = standardized_fight_night(60, 53, 100, garcia_total_thrown)
garcia_total_zscore

Out[8]:
array([-3.40959768, -1.96473539, -1.69382371, -1.33260814, -0.79078479,
-0.610177  , -2.14534318, -0.79078479, -1.60351982,  1.10559696,
-3.138686  , -0.88108868])
In [9]:
plt.plot(spence_total_zscore, garcia_total_zscore, 'go')

Out[9]:
[<matplotlib.lines.Line2D at 0x245153e6f98>]
In [ ]: