【Python學習筆記-MLB「防禦率」與勝負的關係?】(下)
《Rick.C & Peter.R 共同創作》
一 、投手的責任到底怎麼看?
在上一篇【Python學習筆記-MLB「防禦率」與勝負的關係?(上)】中,我們討論到了,究竟防禦率低卻輸掉比賽的2.13%是怎麼一回是呢?還有防禦率低的隊伍一定會是主隊嗎?我們就來繼續進行探討吧!!
一、傳說的2.13%究竟是發生了什麼呢?
雖然確定防禦率低的隊伍幾乎就是勝者,但我們還挺好奇這剩下的2.13%究竟是怎麼回事,所以我們特別拉出來觀察看看。
我們總共的資料筆數為15439筆,而防禦率低卻落敗的場數共有329場。
df[df["more_ERA_win"] == 0]
我們想了一下,可能造成防禦率低卻輸掉的最直接原因,那應該就是「非自責分數」高吧,因為非自責分的失分不會記錄在防禦率中,所以在計算上才會出現低防禦率卻輸掉比賽,但這依舊是我們的猜想,所以我們來實證看看。
我們本身數據就擁有「主客隊得分」以及「投手自責分(ER)」這兩個數據,因此我們將敵隊的得分減去自家隊的自責分,那麼就可以得到自己的非自責分。
df['Home_NotER'] = df['客隊得分'] - df["Home_Pitcher_ER"]layout = go.Layout(title='三振率與勝負關係')
df['Away_NotER'] = df['主隊得分'] - df["Away_Pitcher_ER"]
df.head(5)
深度回測一層又一層!
接著我們分別計算兩種狀況的非自責分平均為多少
- 正常 : 防禦率低獲勝、防禦率高落敗
- 例外 : 防禦率低落敗 、防禦率高獲勝
先來看正常的情況下,防禦率低獲勝的隊伍,其非自責分平均每場為0.21分,而防禦率高落敗的隊伍,其非自責分平均每場為0.43分,其實都算相當的低,但很明顯防禦率低的隊伍非自責分相對較低,因此能夠拿下比賽勝利。
df_win = df[df["more_ERA_win"] == 1]
win_notera = 0
lose_notera = 0
for i in range(len(df_win)):
if df_win['W/L'][i] == 0:
win_notera += df_win['Away_NotER'][i]
lose_notera += df_win['Home_NotER'][i]
else:
win_notera += df_win['Home_NotER'][i]
lose_notera += df_win['Away_NotER'][i]
print("防禦率低獲勝的非自責分平均為 : " + str(round((win_notera/len(df_win)),2)) + " 分")
print("防禦率高落敗的非自責分平均為 : " + str(round((lose_notera/len(df_win)),2))+ " 分")
接著看例外狀況,沒想到在這些例外的場次中,防禦率高卻獲勝的隊伍,其非自責分僅0.08分,而防禦率低卻落敗的隊伍,其非自責分高達2.82分,可想而知,這幾場比賽的投手真的是衰,一整個被隊友的守備能力拖累,但究竟是甚麼原因造成這些比賽有如此高的非自責分出現,這部分我們以後有機會再做更深入的探討。
df_ nowin = df[df["more_ERA_win"] == 0]
win_notera = 0
lose_notera = 0
for i in range(len(df_ nowin)):
if df_win['W/L'][i] == 0:
win_notera += df_ nowin['Away_NotER'][i]
lose_notera += df_ nowin['Home_NotER'][i]
else:
win_notera += df_ nowin['Home_NotER'][i]
lose_notera += df_ nowin['Away_NotER'][i]
print("防禦率低獲勝的非自責分平均為 : " + str(round((win_notera/len(df_ nowin)),2)) + " 分")
print("防禦率高落敗的非自責分平均為 : " + str(round((lose_notera/len(df_ nowin)),2))+ " 分")
二、回測這麼說:防禦率和被打擊率很有關
看到這,應該大致了解防禦率是非野手失誤所造成對手擊球出去得分的呈現,但打擊出去就一定會得分嗎?有些球隊或許打擊率不高,但卻總能在關鍵時刻擊球得分,但照常理來說,被打擊率低的球隊,防禦率正常也會較低才對。不過沒數據的證實,終究只是我們紙上談兵,所以我們就來統計看看吧!!
被打擊率其實就是對手的打擊率,所以我們可以使用到上一篇研究打擊率的數值,我們分別將「主隊打擊率與客隊防禦率」、「客隊打擊率與主隊防禦率」做散點圖視覺化出來。
plt.rcParams['font.sans-serif'] = ['Microsoft JhengHei']
plt.rcParams['axes.unicode_minus'] = False
plt.figure(figsize=(10, 10), dpi=100)
plt.scatter(df['Away_Pitcher_ERA'],df['Home_Batting_AVG'], c='#FFA500', s=30, label='防禦率與被打擊率')
plt.xlabel("客隊防禦率", fontdict={'size': 10})
plt.ylabel("主隊打擊率", fontdict={'size': 10})
plt.title("防禦率與被打擊率關係", fontdict={'size': 20})
plt.legend(loc='best')
plt.show()
plt.rcParams['font.sans-serif'] = ['Microsoft JhengHei']
plt.rcParams['axes.unicode_minus'] = False
plt.figure(figsize=(10, 10), dpi=100)
plt.scatter(df[' Home_Pitcher_ERA'],df['Away_Batting_AVG'], c='#FFA500', s=30, label='防禦率與被打擊率')
plt.xlabel("主隊防禦率", fontdict={'size': 10})
plt.ylabel("客隊打擊率", fontdict={'size': 10})
plt.title("防禦率與被打擊率關係", fontdict={'size': 20})
plt.legend(loc='best')
plt.show()
由上圖可知,散點圖幾乎分布於左下角,且越右方有越高的趨勢,也就證明,防禦率與被打擊率的確呈現正向關係,但可以看到仍然有些許的例外案例。
防禦率低且獲勝的隊伍是否總眷顧主隊呢?
最終我們仍回歸到主場優勢身上,雖然上方我們統計出主客場誰的防禦率較低時,主隊僅略勝一籌,仍無法證實其有主場優勢,所以我們再來統計看看防禦率低且獲得勝利女神眷顧的隊伍究竟會是哪一方。
我們先將防禦率低且獲勝的隊伍取出放到「df_era_win」中。
df_era_win = df[df['more_Pitcher_ERA'] == df['W/L']]
df_era_win.head()
不過從下方的統計圖來看,藍色(1)為防禦率低且獲勝的隊伍為主隊,佔比53.4%,橘色(0)為防禦率低且獲勝的隊伍為客隊,佔比為46.6%。可以看出主客的佔比與第一點的主客防禦率高低分布圖相似,因此可以說,只要哪方防禦率低,幾乎就可以確定哪方可以獲勝。
trace0 = go.Pie(labels= df_era_win["W/L"].value_counts().index,
values= df_era_win["W/L"].value_counts().values,
hole=0.5,
opacity=0.9,
marker=dict(line=dict(color='white', width=1.3))
)
layout = go.Layout(title='防禦率勝負與主客關係')
data = [trace0]
fig = go.Figure(data, layout)
py.offline.plot(fig, filename=r'C:\Users\Guess365User\Desktop\IT邦寫文\圖表區\防禦率勝負與主客關係圖.xlsx')
不熟悉的球賽、可以先熟悉雙方的防禦率
根據今天的研究,防禦率真的是預測比賽勝負一個極其重要的因子,只要能擁有準確的防禦率將能夠大大提升預測勝負的準確度,而這正是將來要研究的議題之一,我們現階段就是希望能找到更多如同防禦率這樣明確區分勝負的重要因子,因此我們就繼續探討下去吧!!
【參考平台與資訊 & Python語言書籍】
[Guess官網平台-分析專欄] https://reurl.cc/yMOVE6
[資料視覺化 | 製作充滿說服力的資訊圖表]
[Python資料分析必備套件!Pandas資料清理、重塑、過濾、視覺化]
[Python 大數據專案 X 工程 X 產品 資料工程師的升級攻略]
好文 感謝分享👍
11/3/2022 1:38:26 PM