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

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

関連記事

[Meisyo]ゲームのUIを改善し続ける意味とは

1ヶ月に3回はUIが変わっているMeisyo。 何故変え続けているのか。 説明しよう! 今悪いポイント 簡単に言うと新規登録ユーザーさんが定着しない! チュートリアルでも最終ステップまでの到達率が75 …

[Meisyo]Androidアプリ版 作成案1

「アンドロイドアプリの基本」的な本が届いて3日。だいたいわかった(わかってない)ので一応完成予想図を考えておきましょう。 [トップページ]→[ログイン画面]or[ゲーム画面] ・アプリの利用メリット …

[Meisyo] 別バージョン「栄光の世代」原案

システムのベースはMeisyoを流用するが、コンセプトが異なる別バージョンを出してみたい。 コンセプト 高校野球監督視点のゲーム 選手の卒業あり(リアル時間3か月を想定)  リアル1か月=ゲーム1年を …

no image

まとめ読み バージョン1.1.0のリリース

フリーソフト「まとめ読み」バージョン1.1.0のリリースを行いました。 まとめ読み ダウンロードページ 変更点 対象をPHP5.3.7以上に変更 読み込み速度および安全性の確保 SplClassLoa …

(VPSでつくる) セキュリティ設定

連載第十四回目です。 セキュリティ設定について何もわからん状態なので色々と漁っていました。 PythonやFlaskなどの個別のモノに対してのセキュリティ設定の書籍は中々多くないので、Linuxなどの …