RのWeb制作

Webサービス制作のための技術情報を。データ分析(Python、機械学習コンペ他)や自作野球ゲームMeisyoのこと中心。

Web制作 Meisyo Python

[Meisyo]ビッグデータから学ぶ試合の基礎設計4

投稿日:2018年12月17日 更新日:

ここでは、「どのパラメータが打率等にどれくらい関係するのか」を理解することで強いチームを作る指針を記載しておきます。

機械学習(重回帰分析)を使って本気で遊んでます。

実際のデータセットはこちら
野手データ 2018.12.17.csv
投手データ 2018.12.17.csv
*公平を期すために使用したデータセットを公開しています

計:146141打席
多くなりましたね。

結果

野手編
打率(AVE)、出塁率(OBP)、長打率(SLG)、OPS(OPS)
に対し・・・ミート(MT)、パワー(PW)、走力(SP)、肩力(SF)、守備力(DF)、反応速度(SS)が相関しています。

とはいえ、速球投手が全然居ないのでミート王者は変わりそうにありませんが。
昔は速球投手が猛威を奮っており、反応高くないと死ぬゲームでした。

投手編
防御率(ERA)、WHIP
に対し・・・コントロールが高ければ高いほど、ERAとWHIPは落ちる傾向。
速球とスタミナがあるとERAとWHIPが上がる・・・だと?

相手投手との相関性を全く考えていないデータなので、水物ではあります。日々変化しそう。
守備もデータ取ってないから説明できないのが悲しいところですね。

詳細分析

AVE

平均: 0.22
中央値: 0.22
分散: 0.01
標準偏差: 0.12

OPS

平均: 0.63
中央値: 0.64
分散: 0.08
標準偏差: 0.29

ERA(防御率)

平均: 4.20
中央値: 3.91
分散: 18.28
標準偏差: 4.28
・・・こいつだけエラいばらばらやな?

WHIP

平均: 0.46
中央値: 0.50
分散: 0.09
標準偏差: 0.30

※注意:各選手の結果をリスト化して、単純に平均、中央値等を出しているだけなので、投球回数等は反映されていないデータです。ご注意ください。

分析スクリプト

コマンドプロンプトでpython他をインストールしてみてください。
グラフの出力は100行目くらいにある

sys.exit()

をコメントアウトしてくださいませ。

投手用

# -*- coding: utf-8 -*-

import os, sys, csv
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt

# 基礎設定
file_name = 'meisyo_p 20181217.csv'

# CSV読み込み
df = pd.read_csv(file_name, encoding='utf-8')

# Null値を把握
# print(df.isnull().sum())

# 基礎設定
team = pd.DataFrame(index=[], columns=[])

# 投手能力結合・削除
for i in ['sp', 'co', 'st', 'bb1n', 'bb2n', 'bb3n']:
    df['p_'+i] = df['p_'+i] + df['pt_p_'+i] + df['pw_p_'+i]
    df = df.drop(['pt_p_'+i, 'pw_p_'+i], axis=1)
#for i in ['bb1', 'bb2', 'bb3', 'bb0k', 'bb1k', 'bb2k', 'bb3k']:
#    df = df.drop(['p_'+i], axis=1)

# 野手能力結合・削除
for i in ['mt', 'pw', 'sp', 'sf', 'df', 'er', 'ss']:
    df['b_'+i] = df['b_'+i] + df['pt_b_'+i] + df['pw_b_'+i]
    df = df.drop(['b_'+i, 'pt_b_'+i, 'pw_b_'+i], axis=1)

team = df

# 不必要品削除
df = df.drop(['mn_id', 'name', 'side_p', 'type', 'type_p', 'hp', 'cond', 'cond_b', 'img', 'exp', 'time', 'skill', 'game.1', 'id.1', 'g_bench', 'g_pos', 'g_sb', 'game', 'pc_type', 'bt_type', 'grow_type'], axis=1)

# 欠損値のある行を削除
df = df.dropna()

# 変化球(チェンジアップ=0)ありか
df['p_bb'] = 0
if df['p_bb1'].empty or df['p_bb2'].empty or df['p_bb3'].empty:
    df['p_bb'] = 1

# データセット
df = df.drop(['type_b', 'side_b', 'lv'], axis=1)
df = df.drop(['p_bb1', 'p_bb2', 'p_bb3'], axis=1)

# データ確認
#print(df.isnull().sum())

# 結果データ作成
rs = pd.DataFrame(index=[], columns=[])
rs['id'] = df['id']
rs['era'] = (df['er'] * 9) / (df['ip'] / 3)
rs['whip'] = (df['h'] + df['bb']) / (df['ip'])

# 結果削除(結果に直接相関する)
df = df.drop(['pa', 'ab', 'h', 'risp_b', 'risp_h', '1b', '2b', '3b', 'hr', 'tb', 'sh', 'sf', 'bb', 'hbp', 'so', 'e_er'], axis=1)
df = df.drop(['er', 'r', 'ip', 'wp', 'win', 'lose', 'save', 'cg', 'sho', 'gs'], axis=1)

# データ欠損値の埋め合わせ
rs = rs.fillna(0)

# データ設定
x_col = df.drop('id', axis=1)
x = x_col.values
y_era = rs.values[:, 1]
y_whip = rs.values[:, 2]

#必要なパッケージのインポート
from sklearn import linear_model
model_era = linear_model.LinearRegression()
model_whip = linear_model.LinearRegression()

# 学習する
model_era.fit(x, y_era)
model_whip.fit(x, y_whip)

# 偏回帰係数
print("era")
print(pd.DataFrame({"Name":x_col.columns, "Coefficients":model_era.coef_}).sort_values(by='Coefficients') )
print(model_era.intercept_)

print("whip")
print(pd.DataFrame({"Name":x_col.columns, "Coefficients":model_whip.coef_}).sort_values(by='Coefficients') )
print(model_whip.intercept_)

# 相関
myteam = {}
for key, row in team.iterrows():
    if row['mn_id'] == 'れい' and row['type'] == 'P':
        sum = 0
        for i in x_col.columns:
            if i is not 'p_bb':
                sum += row[i]
        myteam[row['name']] = '{:.0f}'.format(sum);

for k, v in sorted(myteam.items(), key=lambda x: x[1]):
    print(str(k) + ": " + str(v))

# stop
sys.exit()

# グラフ用
y_eraV = ['{:.2f}'.format(n) for n in y_era]
y_whipV = ['{:.2f}'.format(n) for n in y_whip]

# plot
data = y_whipV

import collections
list = collections.Counter(data)
x = np.arange(200) / 100
values = []
for i in x:
    i = '{:.2f}'.format(i)
    print(str(i) + ":" + str(list[i]))
    if list[i]:
        values.append(list[i])
    else:
        values.append(0)
values[0]=0 # 0を無視

# 計算
from statistics import mean, median,variance,stdev
print(data)
data = [float(s) for s in data]
m = mean(data)
median = median(data)
variance = variance(data)
stdev = stdev(data)
print('平均: {0:.2f}'.format(m))
print('中央値: {0:.2f}'.format(median))
print('分散: {0:.2f}'.format(variance))
print('標準偏差: {0:.2f}'.format(stdev))

plt.bar(x, values, width=0.1)
plt.xlabel("result")
plt.ylabel("num")
plt.show()

野手用

# -*- coding: utf-8 -*-

import os, sys, csv
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt

# 基礎設定
file_name = 'meisyo_b 20181217.csv'

# CSV読み込み
df = pd.read_csv(file_name, encoding='utf-8')

# Null値を把握
# print(df.isnull().sum())

# 基礎設定
team = pd.DataFrame(index=[], columns=[])

# 投手能力結合・削除
for i in ['sp', 'co', 'st', 'bb1n', 'bb2n', 'bb3n']:
#    df['p_'+i] = df['p_'+i] + df['pt_p_'+i] + df['pw_p_'+i]
    df = df.drop(['pt_p_'+i, 'pw_p_'+i], axis=1)
for i in ['bb1', 'bb2', 'bb3', 'bb0k', 'bb1k', 'bb2k', 'bb3k']:
    df = df.drop(['p_'+i], axis=1)

# 野手能力結合・削除
for i in ['mt', 'pw', 'sp', 'sf', 'df', 'er', 'ss']:
    df['b_'+i] = df['b_'+i] + df['pt_b_'+i] + df['pw_b_'+i]
#    df = df.drop(['b_'+i, 'pt_b_'+i, 'pw_b_'+i], axis=1)

team = df

# 不必要品削除
df = df.drop(['mn_id', 'name', 'side_p', 'type', 'type_p', 'hp', 'cond', 'cond_b', 'img', 'exp', 'time', 'skill', 'game.1', 'id.1', 'g_bench', 'g_pos', 'g_sb', 'game', 'pc_type', 'bt_type', 'grow_type'], axis=1)

# 欠損値のある行を削除
df = df.dropna()

# 不必要分削除
df = df.drop(['type_b', 'side_b', 'lv'], axis=1)
df = df.drop(['b_er'], axis=1)

# データ確認
#print(df.isnull().sum())

# 結果データ作成
rs = pd.DataFrame(index=[], columns=[])
rs['id'] = df['id']
rs['ave'] = df['h'] / df['ab']
rs['obp'] = (df['h'] + df['bb'] + df['hbp']) / (df['ab'] + df['bb'] + df['hbp'] + df['sf'])
rs['slg'] = df['tb'] / df['ab']
rs['ops'] = rs['obp'] + rs['slg']

# 野手結果削除(結果に直接相関する)
df = df.drop(['pa', 'ab', 'h', 'risp_b', 'risp_h', '1b', '2b', '3b', 'hr', 'tb', 'rbi', 'rs', 'sh', 'sf', 'bb', 'hbp', 'so', 'dp', 'e_er', 'tc', 'm_er', 'sb', 'cb', 'c_sb', 'c_cs'], axis=1)

# データ欠損値の埋め合わせ
rs = rs.fillna(0)

# データ設定
x_col = df.drop('id', axis=1)
x = x_col.values
y_ave = rs.values[:, 1]
y_obp = rs.values[:, 2]
y_slg = rs.values[:, 3]
y_ops = rs.values[:, 4]

print(df.isnull().any())
print(rs.isnull().any())

#必要なパッケージのインポート
from sklearn import linear_model
model_ave = linear_model.LinearRegression()
model_obp = linear_model.LinearRegression()
model_slg = linear_model.LinearRegression()
model_ops = linear_model.LinearRegression()

# 学習する
model_ave.fit(x, y_ave)
model_obp.fit(x, y_obp)
model_slg.fit(x, y_slg)
model_ops.fit(x, y_ops)

# 偏回帰係数
print("ave")
print(pd.DataFrame({"Name":x_col.columns, "Coefficients":model_ave.coef_}).sort_values(by='Coefficients') )
print(model_ave.intercept_)

print("obp")
print(pd.DataFrame({"Name":x_col.columns, "Coefficients":model_obp.coef_}).sort_values(by='Coefficients') )
print(model_obp.intercept_)

print("slg")
print(pd.DataFrame({"Name":x_col.columns, "Coefficients":model_slg.coef_}).sort_values(by='Coefficients') )
print(model_slg.intercept_)

print("ops")
print(pd.DataFrame({"Name":x_col.columns, "Coefficients":model_ops.coef_}).sort_values(by='Coefficients') )
print(model_ops.intercept_)

# 結果表示
print(x_col.columns)
print(model_ops.coef_)

# 相関図
myteam = {}
for key, row in team.iterrows():
    if row['mn_id'] == 'れい' and row['type'] == 'B':
        sum = 0
        for i in x_col.columns:
            sum += row[i]
        myteam[row['name']] = '{:.0f}'.format(sum);

for k, v in sorted(myteam.items(), key=lambda x: x[1]):
    print(str(k) + ": " + str(v))

# stop
sys.exit()

# グラフ用
y_aveV = ['{:.2f}'.format(n) for n in y_ave]
y_obpV = ['{:.2f}'.format(n) for n in y_obp]
y_slgV = ['{:.2f}'.format(n) for n in y_slg]
y_opsV = ['{:.2f}'.format(n) for n in y_ops]

# plot
data = y_aveV

import collections
list = collections.Counter(data)
x = np.arange(100) / 100
values = []
for i in x:
    i = '{:.2f}'.format(i)
    print(str(i) + ":" + str(list[i]))
    if list[i]:
        values.append(list[i])
    else:
        values.append(0)
values[0]=0 # 0を無視

# 計算
from statistics import mean, median,variance,stdev
print(data)
data = [float(s) for s in data]
m = mean(data)
median = median(data)
variance = variance(data)
stdev = stdev(data)
print('平均: {0:.2f}'.format(m))
print('中央値: {0:.2f}'.format(median))
print('分散: {0:.2f}'.format(variance))
print('標準偏差: {0:.2f}'.format(stdev))

plt.bar(x, values, width=0.1)
plt.xlabel("result")
plt.ylabel("num")
plt.show()

-Web制作, Meisyo, Python

執筆者:


  1. […] [Meisyo]ビッグデータから学ぶ試合の基礎設計4から早4か月。 「球速の上方修正してほしいな」というコメントが届きました。 […]

comment

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

関連記事

no image

SSH、SSHクライアントって何?

SSH?SSHクライアント?となり挫折しそうな、または挫折してしまった方への案内書になります。私がさくらサーバーにopenPNEとそのプラグインを入れる時に陥ったので、後学のためにも書き残しておきます …

for内で選手個人データをSQLで呼び出すより、辞書型を利用した方が読み込みは早い

for内でSQLを呼び出すと遅い…。 自作野球ゲームMeisyoでは、明示的にデータを呼び出すためにfor内でSQLを利用していました。 CDs = {} # Cardデータ(選手id, 選手データ) …

[Meisyo]第7回公式戦結果

平成最後の公式戦がありました。 これまで優勝2回の強豪、ジャガ畑 vs 並みいる強豪を倒してきたダークホース、ふたもじ その結果はこちら 優勝おめでとうございます!

no image

iPhoneアプリを開発してみよう

最近ずっとiPhoneアプリで遊んでて、 「なんか頭使うゲームないな?」と思い(”本質的には育成ゲー”が多すぎてゲンナリ) 「複数人でのRTS」があればな~と。 「他ゲーに文句 …

no image

cakePHP2.*で簡単にデータベース(database.php)設定を切り替える方法

cakePHP2.0で実験しました。 内容はhttp://blog.imho.jp/2014/05/cakephp-2xdatabasephp.htmlを改良しました。ありがとうございます。といっても …