プロ野球

ゆうき( @BASEBALLY15 )です^^

プロ野球選手って,お金持ちのイメージがあるけれど,全員,そうなの・・・?

どうなんでしょうか?

実際に,検証してみましょう^^

今回は,プロ野球選手の中で,年俸が1億円を超えている人と,そうでない人にはどのような関係があるのかを
ロジスティック回帰』検証してみます.
検証してみると,年功序列なのか?と一瞬疑ってしまいました.

プロ野球選手って,みんな稼いでるんじゃないの?

プロ野球選手と聞くと,有名でお給料も高いのでは?と感じるのではないでしょうか.

子どもからも人気があり,なりたい職業ランキングでもに上位にくるほどです!

(画像をクリックすると,引用元を確認できます.)

さらに,選手名鑑やサイトを見てみると,1億円プレイヤーどころか,2億3億円プレイヤーまで存在します.

そこで,今回は,ロジスティック回帰を使って,年俸が高い選手には,どのような関係があるのかを分析してみました.

ロジスティック回帰とは?

ロジスティック回帰とは,簡単に言うと,ある事柄に対して『はい』か『いいえ』の2択で答えることを言います.

例えば,「私はプロ野球選手になれますか?」という質問に対して,その人の身長・体重・能力などから判断し,

「はい.あなたはプロ野球選手になれます.」と答えることです.

以下の動画がロジスティック回帰について分かりやすく説明されているので,視聴してみてください^^

それでは,Pythonを使って検証してみましょう^^

ロジスティック回帰を使ったデータ分析

使ったデータ

今回のロジスティック回帰で使ったデータは,以下のサイトを参考にしました.

プロ野球データFreakより

このデータを扱いやすいようにまとめたのが,以下のcsvファイルです.

ダウンロードして使ってみてください.

今回は,年俸上位100人と下位100人のデータを使いました.

それでは,ロジスティック回帰でデータ分析を行っていきましょう^^

まずは,データ分析を行うためのライブラリを用意します.

ライブラリ

import numpy as np

import pandas as pd

from pandas import Series, DataFrame

import matplotlib.pyplot as plt

import seaborn as sns

sns.set_style("whitegrid")

%matplotlib inline

そして,ロジスティック回帰を行うためのライブラリと,検証を行うためのライブラリを用意します.

#ロジスティック回帰を行うためのライブラリ
from sklearn.linear_model import LogisticRegression


#学習用とテスト用に分けるためのライブラリ
from sklearn.model_selection import train_test_split


#精度を求めるためのライブラリ
from sklearn.metrics import accuracy_score

コード

ライブラリを用意した後は,csvファイルを読み込みます.

#csvファイルを読み込み
baseball_df = pd.read_csv("a professional baseball player_data.csv")

#実行
baseball_df

すると,このように表示されます.

player’s nameannual salary(yen)Years (years)Age (Year)Height (cm)Weight (kg)
0菅野 智之65000000073018695
1柳田 悠岐57000000093118791
2浅村 栄斗500000000112918290
3サファテ500000000938193102
4坂本 勇人500000000133118683
195益子 京右470000011917687
196遠藤 淳志480000022018478
197卓丸480000052318076
198鈴木 裕太480000011918293
199牧 丈一郎480000022018187

今回は,年俸が1億円を超えているか,そうでないかに分けたいので,

1億円を超えている場合を1,超えていない場合を0としたいと思います.

#1億円以上の時1,それ以外を0とする
def over_1oku(x):
    if x>=100000000:
        return 1
    else:
        return 0


#"1億円以上"という項目を追加
baseball_df["over_1oku"] = baseball_df["annual salary(yen)"].apply(over_1oku)


#実行
baseball_df

すると,このように『over_1oku』という項目が追加されています.

player’s nameannual salary(yen)Years (years)Age (Year)Height (cm)Weight (kg)over_1oku
0菅野 智之650000000730186951
1柳田 悠岐570000000931187911
2浅村 栄斗5000000001129182901
3サファテ5000000009381931021
4坂本 勇人5000000001331186831
195益子 京右4700000119176870
196遠藤 淳志4800000220184780
197卓丸4800000523180760
198鈴木 裕太4800000119182930
199牧 丈一郎4800000220181870

『 over_1oku 』がどんなデータなのか,見てみましょう.

#データを可視化
baseball_df.groupby("over_1oku").mean()
annual salary(yen)Years (years)Age (Year)Height (cm)Weight (kg)
over_1oku
03140600.02.3822.25181.0882.65
1226421000.08.6331.98183.4891.00

これを見ると,1億円を超えているかどうかは,年齢と年数が影響するのではないか,

ということが推測できますね^^

追記ココから(2020/4/20現在)

このデータをseabornを使って可視化してみます.

#ヒストグラムを描く(年数)
sns.countplot("Years (years)", data=baseball_df.sort_values("Years (years)"), hue="over_1oku")
ロジスティック回帰(年数)
#ヒストグラムを描く(年齢)
sns.countplot("Age (Year)", data=baseball_df.sort_values("Age (Year)"), hue="over_1oku")
ロジスティック回帰(年齢)

追記ココまで

では,実際にロジスティック回帰を使って,検証してみたいと思います.

ロジスティック回帰で検証してみよう!

まずは,予測に使うデータX(説明変数)と予測したいデータY(目的変数)に分けます.

今回は,1億円を超えているかそうでないかを検証したいので,以下のコードを記述します.

#"player's name"と"annual salary(yen)"と"over_1oku"を取り除いたデータをX(説明変数)
X = baseball_df.drop([ "player's name", "annual salary(yen)", "over_1oku"], axis=1)

#"over_1oku"をY(目的変数)
Y = baseball_df["over_1oku"]

次に,ロジスティック回帰のモデルを用意し,モデルを作成します.

#ロジスティックモデルを準備
baseball_log = LogisticRegression()

#XとYのロジスティックモデルを作成
baseball_log.fit(X, Y)

そして,1億円プレイヤーにはどのような関係があるのかをデータフレームで示したいと思います.

#関係性をデータフレームにする
baseball_coeff_df = DataFrame([X.columns, baseball_log.coef_[0]]).T

#実行
baseball_coeff_df

すると,このように表示されます.

01
0Years (years)0.332022
1Age (Year)0.639506
2Height (cm)0.052844
3Weight (kg)0.0640881

この表は,プラスの場合は年俸1億円との関係性が高く,

マイナスの場合は関係性が低いことを示しています.

これを見ると,やはり,『年数』と『年齢』が年俸1億に深く関係していることが分かります.

そして,『身長』と『体重』はあまり年俸と関係がないことが分かります.

プロ野球は,経験がものを言う世界なのでしょうか^^

今回の検証の精度は?

最後に,今回のロジスティック回帰の精度を求めたいと思います.

#学習用とテスト用に分ける
X_train, X_test, Y_train, Y_test = train_test_split(X, Y, test_size=0.2, shuffle=True)
#ロジスティックモデルを準備
money_log = LogisticRegression()

#XとYのロジスティックモデルを作成
money_log.fit(X_train, Y_train)
#予測する
Y_pred = money_log.predict(X_test)

#精度を表示する
print("精度=", accuracy_score(Y_pred, Y_test))

実行すると,

精度= 0.925

高精度な結果となりました^^

追記(2020/4/20現在)

『標準化』して精度を求めてみよう!(読者からのご提案)

読者の方から,データを『標準化』するとどのような精度になるのか,

というご質問を頂いたので,追記させて頂きました^^

標準化とは?

平均を0,分散を1に変換すること.

引用元:具体例で学ぶ数学

それでは,コードを見ていきましょう⤵

SciPy』をインポートしよう!

上で紹介したライブラリに加えて,

標準化を行うことが出来る『SciPy』というライブラリをインポートします.

#標準化するためのライブラリを用意
import scipy.stats

scipy.stats.zscore』で標準化しよう!

まず,全体のデータフレームを表示させておきます.

#データフレームを表示
baseball_df
player’s nameannual salary(yen)Years (years)Age (Year)Height (cm)Weight (kg)over_1oku
0菅野 智之650000000730186951
1柳田 悠岐570000000931187911
2浅村 栄斗5000000001129182901
3サファテ5000000009381931021
4坂本 勇人5000000001331186831
195益子 京右4700000119176870
196遠藤 淳志4800000220184780
197卓丸4800000523180760
198鈴木 裕太4800000119182930
199牧 丈一郎4800000220181870

それでは,以下のコードを記述し,年数・年齢・身長・体重の値を標準化します.

#標準化
#年数
sta_years = scipy.stats.zscore(baseball_df["Years (years)"], ddof=1)

#年齢
sta_age = scipy.stats.zscore(baseball_df["Age (Year)"], ddof=1)

#身長
sta_height = scipy.stats.zscore(baseball_df["Height (cm)"], ddof=1)

#体重
sta_weight = scipy.stats.zscore(baseball_df["Weight (kg)"], ddof=1)

scipy.stats.zscore関数を使うと,値を標準化することが出来ます.

また,今回使うデータはあくまでも標本集団なので,

ddof=1』と書くことで,『n-1で割る』標準偏差を使います.

※母集団の場合は,nで割るが,標本集団の場合は,n-1で割る.

標準化した値を入れ替えよう!

次に,データフレーム内に,標準化した値を代入します.

#データフレームの値を入れ替える
baseball_df.iloc[:,2] = sta_years

baseball_df.iloc[:,3] = sta_age

baseball_df.iloc[:,4] = sta_height

baseball_df.iloc[:,5] = sta_weight

実行してみましょう^^

#表示
baseball_df
player’s nameannual salary(yen)Years (years)Age (Year)Height (cm)Weight (kg)over_1oku
0菅野 智之6500000000.3063220.4917890.5876550.7521071
1柳田 悠岐5700000000.7161180.6622540.7456270.3841041
2浅村 栄斗5000000001.1259140.321325-0.0442320.2921031
3サファテ5000000000.7161181.8555041.6934581.3961141
4坂本 勇人5000000001.5357100.6622540.587655-0.3519031
195益子 京右4700000-0.923065-1.383318-0.9920630.0161000
196遠藤 淳志4800000-0.718167-1.2128530.271712-0.8119080
197卓丸4800000-0.103473-0.701461-0.360176-0.9959100
198鈴木 裕太4800000-0.923065-1.383318-0.0442320.5681060
199牧 丈一郎4800000-0.718167-1.212853-0.2022040.0161000

予測に使うデータ(説明変数)と予測するデータ(目的変数)に分けよう!

次に,説明変数と目的変数に分けて,データフレームで表示します.

#予測に使うデータ(説明変数)と予測するデータ(目的変数)に分ける
X2 = baseball_df.drop([ "player's name", "annual salary(yen)", "over_1oku"], axis=1)

Y2 = baseball_df["over_1oku"]

ロジスティック回帰で精度を求めてみよう!(標準化編)

説明変数と目的変数に分けたデータを,さらに学習用とテスト用に分けます.

#学習用とテスト用に分ける
X2_train, X2_test, Y2_train, Y2_test = train_test_split(X2, Y2, test_size=0.2, shuffle=True)

そして,ロジスティックモデルを使い学習させます.

#ロジスティックモデルを準備する
money_log2 = LogisticRegression()

#学習する
money_log2.fit(X2_train, Y2_train)

それでは,『標準化』することで精度がどのようになるのか見てみましょう⤵

#精度を求める
pre = money_log2.predict(X2_test)

print("精度=", accuracy_score(pre, Y2_test))
精度= 0.975
ロジスティック回帰_標準化する前と後の精度の違い

このように,『標準化』することで,精度が向上しました^^

最後に

今回は,プロ野球選手のデータを使って,ロジスティック回帰分析を行いました.

今後は,他の分野のデータや分析方法を使っていきたいと思います^^

それでは・・・

Q &A

参考資料

https://note.nkmk.me/python-list-ndarray-dataframe-normalize-standardize/

コメントを残す

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

CAPTCHA