[PYTHON] Überprüfen Sie die Richtigkeit der Bewertungsformel "RC" anhand der tatsächlichen professionellen Baseballdaten

  1. Introduction

US-amerikanischer Sportjournalist und Pionier der Baseball-Spar-Metriken [Bill James](https://ja.wikipedia.org/wiki/%E3%83%93%E3%83%AB%E3%83 % BB% E3% 82% B8% E3% 82% A7% E3% 83% BC% E3% 83% A0% E3% 82% BA) hat eine Formel erstellt, um die Punktzahl des Teams vorherzusagen.

Anzahl der Punkte=  (Anzahl der Treffer+Anzahl von vier Bällen)× Anzahl der Basistreffer ÷(Anzahl der Striche+Anzahl von vier Bällen)

Die durch diese Formel geschätzte Punktzahl wurde ** RC (Runs Created) ** genannt. James ersetzte die Rekorde der vergangenen Saison verschiedener MLB-Teams auf der rechten Seite dieser Formel, um festzustellen, ob sie mit der tatsächlichen Punktzahl übereinstimmten. Infolgedessen war diese Formel unabhängig von der angewandten Mannschaft wirksam, und die Punktzahl konnte mit extrem hoher Genauigkeit vorhergesagt werden. Aber es gibt eine Frage.

Daher haben wir dieses Mal die Genauigkeit dieser Bewertungsformel RC anhand der tatsächlichen NPB-Teamdaten überprüft.

  1. Data and Program 2.1. Data Die verwendeten Daten sind die Saisonergebnisse der 12 Teams von Japan Professional Baseball (NPB) von 2005 bis 2016. Data ist die Homepage der Japan Baseball Organization http://npb.jp/ Erhalten von. Zum Beispiel die Ergebnisse der Se League-Saison 2016 http://npb.jp/bis/2016/stats/tmb_c.html Erhalten von, verarbeitet das Format wie folgt und gespeichert.

2016C_bat.csv


Carp, .272, 143, 5582, 4914, 684, 1338, 203, 35, 153, 2070, 649, 118, 52, 91, 29, 500, 13, 47, 1063, 85, .421, .343
Yakult, .256, 143, 5509, 4828, 594, 1234, 210, 20, 113, 1823, 565, 82, 24, 85, 33, 524, 10, 39, 907, 117, .378, .331
Giants, .251, 143, 5356, 4797, 519, 1203, 217, 19, 128, 1842, 497, 62, 26, 112, 23, 389, 11, 35, 961, 100, .384, .310
DeNA, .249, 143, 5364, 4838, 572, 1205, 194, 21, 140, 1861, 548, 67, 34, 81, 18, 373, 7, 54, 1049, 92, .385, .309
Dragons, .245, 143, 5405, 4813, 500, 1180, 209, 21, 89, 1698, 473, 60, 28, 108, 28, 410, 7, 46, 1001, 103, .353, .309
Tigers, .245, 143, 5401, 4789, 506, 1171, 204, 17, 90, 1679, 475, 59, 25, 88, 38, 435, 17, 51, 1149, 99, .351, .312

(Die Daten sind https://github.com/AnchorBlues/python/tree/master/baseballdata Ich habe den verarbeiteten eingelegt

2.2. Program Die Programmiersprache Python wurde zum Lesen, Analysieren und Visualisieren der Daten verwendet.

NPB.py


#coding:utf - 8

import numpy as np
import matplotlib.pyplot as plt
from scipy import stats

fy = 2005
ly = 2016
Yn = ly - fy + 1

Bat_Column = ['Average', 'Game', 'PA', 'AB', 'Score', 'Hit', \
			  'TwoBase', 'ThreeBase', 'HR', 'TB', 'RBI', 'Steel', \
			  'MissSteal', 'Bunt', 'SF', 'BB', 'IntentionalWalk', \
			  'DeadBall', 'StrikeOut', 'DoublePlay', 'SLG', 'OBP']

# PA :Plattenauftritt Anzahl der Sitzplätze
# AB :Bei Fledermausschlägen
# TB :Gesamtbasis Anzahl der Basen
# RBI :Punktpunkt
# SF :Opferfliege Opferfliege
# IntentionalWalk :Absichtlich vier Bälle

N = len(Bat_Column)

class Bat_Data():
	def __init__(self, Data, Year, Team):
		self.Year = Year
		self.Team = Team
		for i in range(0, N):
			setattr(self, Bat_Column[i], Data[:, i])

		self.OPS = self.SLG + self.OBP
		self.NOI = (self.SLG / 3.0 + self.OBP) * 1000
		self.BABIP = (self.Hit - self.HR) / (self.AB + self.SF - self.HR - self.StrikeOut)
		self.RC = (self.Hit + self.BB) * self.TB / (self.AB + self.BB)
		self.IsoP = self.SLG - self.Average
		self.IsoD = self.OBP - self.Average



class TEAM:
	def __init__(self, ID, Name, maker):
		self.ID = ID
		self.Name = Name
		self.maker = maker


team = [0] * 12
team[0] = TEAM(0, 'Carp', '>')
team[1] = TEAM(1, 'Tigers', '<')
team[2]= TEAM(2, 'Giants', '^')
team[3] = TEAM(3, 'Dragons', 'v')
team[4] = TEAM(4, 'DeNA', 'd')
team[5] = TEAM(5, 'Yakult', 'D')
team[6] = TEAM(6, 'Fighters', '8')
team[7] = TEAM(7, 'Lotte', 'H')
team[8] = TEAM(8, 'Lions', 'h')
team[9] = TEAM(9, 'Eagles', '*')
team[10] = TEAM(10, 'Orix', 'p')
team[11] = TEAM(11, 'Hawks', 's')


#Zwei Fledermäuse_Konsolidieren Sie Dateninstanzen zu einer Instanz
def Docking(Data1, Data2):

	data = np.zeros((Data1.Average.shape[0] + Data2.Average.shape[0], N))
	for i in range(0, N):
		data[:, i] = np.r_[getattr(Data1, Bat_Column[i]), getattr(Data2, Bat_Column[i])]

	year = np.r_[Data1.Year, Data2.Year]
	team = np.r_[Data1.Team, Data2.Team]
	Data_new = Bat_Data(data, year, team)
	return Data_new


def get_data(League, year):
	fname = './baseballdata/' + str(year) + League + '_bat.csv'
	Data = np.loadtxt(fname, delimiter = ',', usecols = range(1, N + 1))
	Year = np.ones(6) * year
	Team = np.loadtxt(fname, delimiter = ',', usecols = range(0, 1), dtype = str)
	Data = Bat_Data(Data, Year, Team)
	return Data


def get_all_data(League):
	for i in range(Yn):
		year = i + fy
		tmp = get_data(League, year)
		if i == 0:
			Data = tmp
		else:
			Data = Docking(Data, tmp)

	return Data

# Data.Column_Nach dem Namen lautet der Teamname Team_Extrahieren Sie nur den mit dem Namen.
def PickUp_Data_of_a_team(Data, Column_name, Team_name):
	return getattr(Data, Column_name)[np.where(getattr(Data, 'Team') == Team_name)]


def draw_scatter(plt, Data, X_name, Y_name, regression_flg = 0, Y_eq_X_line_flg = 0, \
				 title = 'Scatter plot', fsizex = 10, fsizey = 8):

	fig, ax = plt.subplots(figsize = (fsizex, fsizey))
	plt.rcParams['font.size'] = 16

	for i in range(0, len(team)):
		x = PickUp_Data_of_a_team(Data, X_name, team[i].Name)
		y = PickUp_Data_of_a_team(Data, Y_name, team[i].Name)
		year = PickUp_Data_of_a_team(Data, 'Year', team[i].Name)
		if x != np.array([]):
			CF = ax.scatter(x, y, c = year, s = 50, marker = team[i].maker, \
							label = team[i].Name, vmin = fy, vmax = ly)

		if i == 0:
			X = x
			Y = y
		else:
			X = np.r_[X, x]
			Y = np.r_[Y, y]

	plt.colorbar(CF, ticks = list(np.arange(fy, ly + 1)), label = 'year')
	plt.legend(bbox_to_anchor = (1.35, 1), loc = 2, borderaxespad = 0., scatterpoints = 1)
	ax.set_title(title)
	ax.set_xlabel(X_name)
	ax.set_ylabel(Y_name)

	#Zeichnen Sie eine Regressionslinie
	if regression_flg == 1:
		slope, intercept, r_value, _, _ = stats.linregress(X, Y)
		xx = np.arange(450, 750, 1)
		yy = slope * xx + intercept
		ax.plot(xx, yy, linewidth = 2)

	# y=Zeichnen Sie eine gerade Linie von x
	if Y_eq_X_line_flg == 1:
		xx = np.arange(450, 750, 1)
		yy_d = xx
		ax.plot(xx, yy_d, color = 'k')

	print 'Correlation=', np.corrcoef(X, Y)[0, 1]
	return plt

Wenn Sie beispielsweise die SE League-Daten für 2016 abrufen möchten, gehen Sie wie folgt vor.

In [1]:import NPB
In [2]:Data_2016C=NPB.get_data('C',2016)   #Wenn du eine Pa-Liga sein willst'C'Zu'P'Zu.
In [3]:Data_2016C.Average  #Geben Sie die Team-Trefferquote jedes der 6 Teams in der Central League 2016 aus

Out[3]: array([ 0.272,  0.256,  0.251,  0.249,  0.245,  0.245])
  1. Result 3.1. Average vs Score Betrachten wir zunächst die Korrelation zwischen dem häufigsten Trefferindex, der "Trefferquote" und der Anzahl der erzielten Punkte. Nehmen Sie die Teamdaten (insgesamt 144 Stichproben) aller 12 Teams von 2005 bis 2016 heraus und zeichnen Sie ein Streudiagramm mit "Durchschnitt" auf der horizontalen Achse und "Punktzahl" auf der vertikalen Achse. Versuchen.
In [1]:import matplotlib.pyplot as plt
In [2]:Data_C=NPB.get_all_data('C')   #Extrahieren Sie alle Daten der Liga
In [3]:Data_P=NPB.get_all_data('P')   #Extrahieren Sie alle Daten von Pa League
In [4]:Data=NPB.Docking(Data_C,Data_P) #Integrieren Sie Daten aus beiden Ligen
In [5]:plt=NPB.draw_scatter(plt,Data,'Average','Score') #Zeichnen Sie ein Streudiagramm mit Schlagrate und Punktzahl
In [6]:plt.show()

Die Ausgabezahl ist wie folgt. image

Auch der Korrelationskoeffizient ist Correlation= 0.825987845723 Das Ergebnis war das.

3.2. RC vs Score Zeichnen Sie für die gleichen Daten wie 3.1. Jetzt ein Streudiagramm mit "RC" auf der horizontalen Achse und "Score" auf der vertikalen Achse.

In [7]:plt=NPB.draw_scatter(plt,Data,'RC','Score',regression_flg=1,Y_eq_X_line_flg=1) #Zeichnen Sie ein Streudiagramm von RC und Scores. Weiterhin sind die Regressionsgerade und y=Zeichnen Sie eine gerade Linie von x.
In [8]:plt.show()

Die Ausgabezahl ist wie folgt. image

Auch der Korrelationskoeffizient ist Correlation= 0.953524104544 Das Ergebnis war das. Aus dem Wert des Korrelationskoeffizienten ist ersichtlich, dass eine extrem starke Korrelation zwischen RC und der Bewertung besteht. Darüber hinaus liegt die Regressionslinie (blaue Linie in der obigen Abbildung) sehr nahe an der geraden Linie von "y = x" (schwarze Linie in der obigen Abbildung). (Die Regressionslinie war "y = 0,95 * x-6,3")

  1. Conclusion Als Ergebnis der Überprüfung mit den früheren Teamdaten von NPB wurde festgestellt, dass der offizielle Bewertungs-RC die Anzahl der Punkte des NPB-Teams mit extrem hoher Genauigkeit vorhersagen kann. Die von Bill James entwickelte RC-Formel wurde jetzt verbessert, beispielsweise der Wert des Koeffizienten, und die Anzahl der gestohlenen Basen wird auch als erklärende Variable verwendet (siehe Wikipedia-Seite [siehe unten]). Das Tolle an der von Bill James entwickelten Bewertungsformel ist jedoch, dass die Punktzahl nur durch ** Grundfähigkeit (= Anzahl der Treffer + Anzahl der vier Bälle) x Vorausfähigkeit (= Anzahl der Grundtreffer) ** genau geschätzt werden kann. Ich denke. Jede erklärende Variable hat keinen Koeffizienten und die Form der Formel ist sehr einfach. Die Tatsache, dass wir entdeckt haben, dass wir die Anzahl der Punkte mit einer so einfachen Formel schätzen können, ist immer noch erwähnenswert.

References

Recommended Posts

Überprüfen Sie die Richtigkeit der Bewertungsformel "RC" anhand der tatsächlichen professionellen Baseballdaten
Bestimmen Sie die Anzahl der Klassen mithilfe der Starges-Formel
Übergang von Baseball aus Daten gesehen
Überprüfen Sie den Status der Daten mit pandas_profiling
Scraping der Gewinndaten von Zahlen mit Docker
Ich habe versucht, die API von Sakenowa Data Project zu verwenden
[Python] Ich habe versucht, Daten mit der API von Wikipedia zu sammeln