前回までに「データ確保」と「データ分析」をそれぞれ試してみました。
今回はより多くのデータを確保して、代表的な分析手法を試してみたいと思います。


今回の環境
今回利用するデータ
今回は「一般社団法人日本野球機構」の公式サイトより、「 2021年度 セントラル・リーグ セントラル・リーグ 個人打撃成績(規定打席以上)」のデータをスクレイピングしてみたいと思います。
情報元は下記のページになります。
今回試す分析手法
DATA VIZ LAB様のこちらのページに記載されている手法をそれぞれ試してみたいと思います。
データの確保
以下のコードで掲載されている情報をデータフレームとして保存します。
# 必要なライブラリを読み込み
from bs4 import BeautifulSoup
import requests
import csv
import pandas as pd
# 指定したURLからデータを取得
res = requests.get("https://npb.jp/bis/2021/stats/bat_c.html")
# 取得したデータをsoup変数に代入
soup = BeautifulSoup(res.content,"html.parser")
# 取得したデータから目的の「表」を検索
table = soup.select("#stdivmaintbl")
table = soup.find("table")
# 表中の行を検索
rows = table.find_all("tr")
# 表のヘッダ行を探して、データフレームの列名とする。
columns = [v.text.replace(" ","") for v in rows[1].find_all("th")]
columns.insert(2,"所属")
df = pd.DataFrame(columns=columns)
# ヘッダ行以外の行からデータを取り出して、データフレームに追加していく。
for i in range(len(rows)-2):
tds = rows[i + 2].find_all("td")
if len(tds) == len(columns):
values = [td.text.replace(" ","") for td in tds]
df = df.append(pd.Series(values, index=columns),ignore_index= True)
# 作成したデータフレームを出力する。
print(df)
# 作成したデータフレームをcsvファイルとして出力する。
df.to_csv("2021_batter.csv",encoding="utf-8")
データ分析
DATA VIZ LAB様のサイトに掲載されている手法を1つずつ試して参ります。
カイ二乗検定
カイ二乗検定とは
名義尺度1から得られた質的データに対する検定で、標本で得られた結果で母集団を推測できるかどうかを判断する方法である。具体的には期待度数(期待値・理論値)を求め、その期待度数から観測度数(測定された値)がどの程度の割合でずれているか(観測度数と期待度数の差=残差)を検定する。
1 単に区別するために用いられている尺度。例えば、血液型のA型、B型、O型、AB型をそれぞれ1、2、3、4という数値に対応させたもの。平均、分散、標準偏差を求めても意味がない。
出典:ニッセイ基礎研究所
今回の分析対象は「名義尺度」に該当せず、有効な分析手法とは言えそうにありませんので、カイ二乗検定の実装は割愛します。
カイ二乗検定を行う際はオープンソースの数値解析ソフトウェア「SciPy」を利用します。利用するサブモジュールは「chisquare」です。
t検定
t検定とは
t-test は、2つ以下の集団の平均の差を検定する方法であり、1)1サンプルの検定、2)対応のないt検定、3)対応のあるt 検定が代表的である。それぞれの例を以下に示す。
1) 1サンプルの検定
例)中学校1年生の平均身長が150Cmであるかどうかを検定する。2) 対応のないt 検定
例) ある会社の男性と女性の賃金に差があるかどうかを検定する。3) 対応のあるt 検定
例)授業前と授業後のテスト点数に差があるかどうかを検定する。出典:ニッセイ基礎研究所
今回は巷でもっとも使いどころが多いと聞く「対応のないt検定」を行ってみます。
使用するライブラリ
SciPyのサブモジュール「stats.ttest_ind」を使用します。
仮説・コードの実装
今回の仮説
「本塁打」を20本以上打った選手と20本未満の選手では、「打率」に差がある。
コードの実装
import pandas as pd
from scipy import stats
# データの読み込み
df = pd.read_csv("2021_batter.csv")
# 本塁打が20本以上の選手を抜き出す
df_over20 = df[df["本塁打"] >= 20]
# 本塁打が20本未満の選手を抜き出す
df_under20 = df[df["本塁打"] < 20]
# 本塁打が20本以上の選手の平均打率
print(df_over20["打率"].mean())
# 本塁打が20本未満の選手の平均打率
print(df_under20["打率"].mean())
# t検定を行う
print(stats.ttest_ind(df_over20["打率"], df_under20["打率"], equal_var= False))
なお、t検定の結果求められるp値の有意水準は一般的な値である5%(0.05)とします。
実行結果・考察
実行結果
0.2680909090909091 #本塁打が20本以上の選手の平均打率
0.28038095238095234 #本塁打が20本未満の選手の平均打率
Ttest_indResult(statistic=-1.29805195815971, pvalue=0.21131353516294832)
考察
数字上は本塁打が20本以上の選手と20本未満の選手の間には1分以上の打率の差がありますが、t検定の結果、pvalue(=p値)が0.05より圧倒的に大きい値になっていますので、この差は「誤差」と言えます。
データが少なすぎることが原因と思われます。
まとめ
いよいよデータ分析らしくなってきましたが、まだまだデータが足りないようです。
次回はDATA VIZ LAB様のサイトを参考に「相関分析」から試してみたいと思います。