import math
import matplotlib.pyplot as plt
from matplotlib.ticker import MaxNLocator as MNL
import pandas as pd
from random import choice as RC
import seaborn as sns
#Create 36 Lineups, defined by placement of sluggers.
#C - 7 contact hitters.
#S - 2 single slugger.
def createLineups2() :
lineups = []
for s1 in range(8):
for s2 in range(0, 8-s1) :
lineup = ["C"]*s1 + ["S"] + ["C"]*s2 + ["S"] + ["C"]*(7-s1-s2)
lineups.append(lineup)
return(lineups)
#Base outcome from hitter.
def calcBase(hitter):
#Pure Contact hitter gets one base one third of time.
if hitter == "C" :
p = RC([0,0,1])
#Slugger hits a homerun one tenth of time.
else :
p = RC([0,0,0,0,0,0,0,0,0,3])
return(p)
#Calculates score of one inning for a lineup.
def calcHomeRuns2(lineup):
#Initialize.
inning = 1
score = 0
while inning < 10 :
#Initialize.
outs = 0
base1 = 0
base2 = 0
base3 = 0
#Play ball!
while outs < 3 :
#Current hitter.
hitter = lineup[0]
#Update lineup. Places current hitter at end.
lineup = lineup[1:9] + lineup[0:1]
hit = calcBase(hitter)
#No hit = struck out.
if hit == 0:
outs += 1
#Pure Contact.
elif hit == 1:
score += base3
base3 = base2
base2 = base1
base1 = 1
#Slugger
else:
score += base3 + base2 + base1 + 1
base1 = 0
base2 = 0
base3 = 0
inning += 1
return(score)
#Calculate average number of runs achieved by a lineup.
def scoreMonteCarlo(lineup, iterations):
scores = []
for i in range(iterations):
scores.append(calcHomeRuns2(lineup))
return(sum(scores) / iterations)
lineups = createLineups2()
lineups
[['S', 'S', 'C', 'C', 'C', 'C', 'C', 'C', 'C'], ['S', 'C', 'S', 'C', 'C', 'C', 'C', 'C', 'C'], ['S', 'C', 'C', 'S', 'C', 'C', 'C', 'C', 'C'], ['S', 'C', 'C', 'C', 'S', 'C', 'C', 'C', 'C'], ['S', 'C', 'C', 'C', 'C', 'S', 'C', 'C', 'C'], ['S', 'C', 'C', 'C', 'C', 'C', 'S', 'C', 'C'], ['S', 'C', 'C', 'C', 'C', 'C', 'C', 'S', 'C'], ['S', 'C', 'C', 'C', 'C', 'C', 'C', 'C', 'S'], ['C', 'S', 'S', 'C', 'C', 'C', 'C', 'C', 'C'], ['C', 'S', 'C', 'S', 'C', 'C', 'C', 'C', 'C'], ['C', 'S', 'C', 'C', 'S', 'C', 'C', 'C', 'C'], ['C', 'S', 'C', 'C', 'C', 'S', 'C', 'C', 'C'], ['C', 'S', 'C', 'C', 'C', 'C', 'S', 'C', 'C'], ['C', 'S', 'C', 'C', 'C', 'C', 'C', 'S', 'C'], ['C', 'S', 'C', 'C', 'C', 'C', 'C', 'C', 'S'], ['C', 'C', 'S', 'S', 'C', 'C', 'C', 'C', 'C'], ['C', 'C', 'S', 'C', 'S', 'C', 'C', 'C', 'C'], ['C', 'C', 'S', 'C', 'C', 'S', 'C', 'C', 'C'], ['C', 'C', 'S', 'C', 'C', 'C', 'S', 'C', 'C'], ['C', 'C', 'S', 'C', 'C', 'C', 'C', 'S', 'C'], ['C', 'C', 'S', 'C', 'C', 'C', 'C', 'C', 'S'], ['C', 'C', 'C', 'S', 'S', 'C', 'C', 'C', 'C'], ['C', 'C', 'C', 'S', 'C', 'S', 'C', 'C', 'C'], ['C', 'C', 'C', 'S', 'C', 'C', 'S', 'C', 'C'], ['C', 'C', 'C', 'S', 'C', 'C', 'C', 'S', 'C'], ['C', 'C', 'C', 'S', 'C', 'C', 'C', 'C', 'S'], ['C', 'C', 'C', 'C', 'S', 'S', 'C', 'C', 'C'], ['C', 'C', 'C', 'C', 'S', 'C', 'S', 'C', 'C'], ['C', 'C', 'C', 'C', 'S', 'C', 'C', 'S', 'C'], ['C', 'C', 'C', 'C', 'S', 'C', 'C', 'C', 'S'], ['C', 'C', 'C', 'C', 'C', 'S', 'S', 'C', 'C'], ['C', 'C', 'C', 'C', 'C', 'S', 'C', 'S', 'C'], ['C', 'C', 'C', 'C', 'C', 'S', 'C', 'C', 'S'], ['C', 'C', 'C', 'C', 'C', 'C', 'S', 'S', 'C'], ['C', 'C', 'C', 'C', 'C', 'C', 'S', 'C', 'S'], ['C', 'C', 'C', 'C', 'C', 'C', 'C', 'S', 'S']]
#Create DataFrame.
data = pd.DataFrame(columns = ['S1',
'S2',
'HR'])
for l in lineups :
temp = []
for i in range(9):
if l[i] == 'S':
temp.append(i+1)
x = scoreMonteCarlo(l, 10000000)
data = data.append({'S1' : temp[0],
'S2' : temp[1],
'HR' : x},
ignore_index = True)
data['HR2'] = (data['HR'] - min(data['HR'])) / (max(data['HR']) - min(data['HR']))
data
S1 | S2 | HR | HR2 | |
---|---|---|---|---|
0 | 1.0 | 2.0 | 1.936012 | 0.450360 |
1 | 1.0 | 3.0 | 1.958608 | 0.651445 |
2 | 1.0 | 4.0 | 1.942155 | 0.505034 |
3 | 1.0 | 5.0 | 1.940540 | 0.490654 |
4 | 1.0 | 6.0 | 1.922464 | 0.329806 |
5 | 1.0 | 7.0 | 1.915298 | 0.266031 |
6 | 1.0 | 8.0 | 1.916399 | 0.275833 |
7 | 1.0 | 9.0 | 1.897650 | 0.108984 |
8 | 2.0 | 3.0 | 1.986645 | 0.900942 |
9 | 2.0 | 4.0 | 1.974857 | 0.796042 |
10 | 2.0 | 5.0 | 1.942430 | 0.507477 |
11 | 2.0 | 6.0 | 1.946846 | 0.546779 |
12 | 2.0 | 7.0 | 1.960492 | 0.668206 |
13 | 2.0 | 8.0 | 1.938087 | 0.468833 |
14 | 2.0 | 9.0 | 1.922038 | 0.326012 |
15 | 3.0 | 4.0 | 1.997777 | 1.000000 |
16 | 3.0 | 5.0 | 1.968829 | 0.742397 |
17 | 3.0 | 6.0 | 1.948324 | 0.559922 |
18 | 3.0 | 7.0 | 1.984759 | 0.884155 |
19 | 3.0 | 8.0 | 1.980183 | 0.843434 |
20 | 3.0 | 9.0 | 1.941643 | 0.500473 |
21 | 4.0 | 5.0 | 1.966499 | 0.721662 |
22 | 4.0 | 6.0 | 1.948560 | 0.562026 |
23 | 4.0 | 7.0 | 1.961313 | 0.675517 |
24 | 4.0 | 8.0 | 1.979668 | 0.838851 |
25 | 4.0 | 9.0 | 1.966783 | 0.724192 |
26 | 5.0 | 6.0 | 1.920294 | 0.310489 |
27 | 5.0 | 7.0 | 1.933488 | 0.427905 |
28 | 5.0 | 8.0 | 1.929339 | 0.390979 |
29 | 5.0 | 9.0 | 1.938087 | 0.468827 |
30 | 6.0 | 7.0 | 1.902867 | 0.155414 |
31 | 6.0 | 8.0 | 1.901741 | 0.145387 |
32 | 6.0 | 9.0 | 1.885403 | 0.000000 |
33 | 7.0 | 8.0 | 1.925010 | 0.352460 |
34 | 7.0 | 9.0 | 1.912497 | 0.241103 |
35 | 8.0 | 9.0 | 1.917738 | 0.287746 |
sns.set()
fig = plt.figure(figsize = (15, 15))
ax = fig.add_subplot()
cmap = plt.cm.get_cmap('viridis_r')
plt.scatter(data["S1"],
data["S2"],
c = data["HR2"],
cmap = cmap,
s = 2000,
alpha = 0.5 )
for i in range(36) :
plt.text(data["S1"][i],
data["S2"][i],
round(data["HR"][i], 4),
ha = 'center',
va = 'center',
size = 16)
#Title setup.
ax.set_title('Average Number of Home Runs After 9 Innings', fontsize = 24)
#X-axis setup.
ax.set_xlabel('Slugger 1 Position', fontsize = 22)
ax.xaxis.set_major_locator(MNL(integer = True))
#Y-axis setup.
ax.set_ylabel('Slugger 2 Position', fontsize = 22)
ax.yaxis.set_major_locator(MNL(integer = True))
ax.tick_params(axis = 'both', which = 'major', labelsize = 18)
fig.savefig("2023.08.18 Extra Credit.png");