SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

Pythonによるデータ解析入門

Pythonではじめての統計~基本情報の確認から検定まで

Pythonによるデータ解析入門 第3回

  • X ポスト
  • このエントリーをはてなブックマークに追加

Pythonではじめての統計(2)

平均・標準偏差など基本的な統計情報を確認する

 データが準備されたら、統計を用いたデータ解析に進みます。まずデータを整えます。

 今回も特定のプレイヤーに注目してデータ解析をします。錦織圭選手のデータに注目していきます。

player = 'Kei Nishikori'
df_nishikori = df_raw[(df_raw['winner_name'] == player) | ( df_raw['loser_name'] == player)]

 データの列の項目を確認します。columns.valuesメソッドを使います。

df_nishikori.columns.values

 結果はこのように表示されます。

array(['tourney_id', 'tourney_name', 'surface', 'draw_size',
       'tourney_level', 'tourney_date', 'match_num', 'winner_id',
       'winner_seed', 'winner_entry', 'winner_name', 'winner_hand',
       'winner_ht', 'winner_ioc', 'winner_age', 'winner_rank',
       'winner_rank_points', 'loser_id', 'loser_seed', 'loser_entry',
       'loser_name', 'loser_hand', 'loser_ht', 'loser_ioc', 'loser_age',
       'loser_rank', 'loser_rank_points', 'score', 'best_of', 'round',
       'minutes', 'w_ace', 'w_df', 'w_svpt', 'w_1stIn', 'w_1stWon',
       'w_2ndWon', 'w_SvGms', 'w_bpSaved', 'w_bpFaced', 'l_ace', 'l_df',
       'l_svpt', 'l_1stIn', 'l_1stWon', 'l_2ndWon', 'l_SvGms',
       'l_bpSaved', 'l_bpFaced'], dtype=object)

 読み込んだデータには多くの項目がありますが、必要なものだけに絞ります。必要な項目だけを指定して、列を絞り込み、これをdfに代入します。

df = df_nishikori[['winner_name','winner_ht','w_df','w_1stWon','w_2ndWon',
            'w_ace','l_ace','loser_name','loser_ht','l_df','l_1stWon','l_2ndWon','minutes']]

 いくつか注目する項目をピックアップして説明します。

  • winner_name:勝者の名前
  • w_1stWon:勝者の1stサーブからの得点数
  • w_2ndWon:勝者の2ndサーブからの得点数

 敗者のデータも同様で、例えば'l_1stWon'は敗者の1stサーブからの得点数になります。

 では統計情報を確認しましょう。前回の記事でも紹介しましたが、describeメソッドによりデータの統計情報を確認することができます。

df.describe()

 結果は下記のようになります。

統計項目
統計項目

 統計項目としていくつかのデータがでてきました。統計の対象はデータ型が数値のもの(intやfloat)になります。左端には統計項目が表示されており、それぞれ下記の意味になります。

表:describeメソッドによる統計情報
項目 意味 
count 行数(要素の数)
mean 平均
std 標準偏差
min 最小値
25% 1/4分位数
50% 中央値
75% 3/4分位数
max 最大値

 例えばw_ace(勝者のエース数)に注目してみます。mean、stdはそれぞれ約4.1、3.9です。勝者のエース数が正規分布にしたがっているとすると、4.1±3.9の範囲でデータの68%が含まれることになります。

 次に'win'の項目にはPlayerが勝ったか負けたかを入れます。

df['win'] = df['winner_name'] == player

 DataFrameのdfに「points_total」カラムを追加し、相手の得点も含む試合の総得点を入れておきます。ここでは総得点に占めるPlayerの得点の割合と、1stサービスからの得点の割合を考えます。

df['points_total']  = df['w_1stWon'] + df['w_2ndWon']+df['l_1stWon']+ df['l_2ndWon']
df['points']  = df['win']*(df['w_1stWon'] + df['w_2ndWon'])+ ~df['win']*(df['l_1stWon']+ df['l_2ndWon'])

 得点をpoints_totalとして格納します。

points_total =df['points_total'] 
points_count =  df['points']
points = points_count/points_total
won_1st_count = df['win']*(df['w_1stWon'])+ ~df['win']*(df['l_1stWon'])
won_1st = won_1st_count/points_total

 won_1stには1stサービスからの得点の割合を格納しました。この中身を確認してみましょう。

won_1st.head()

 結果は下記になります。

    0      0.367347
    2      0.420455
    5      0.375000
    12     0.401709
    154    0.372222
    dtype: float64

 では図にプロットしてみましょう。matplotlibで描画します。

fig, ax = plt.subplots(1, 1)
ax.plot(points, won_1st, '.')
ax.set_xlabel('% of points won')
ax.set_ylabel('% of won_1st')
2変数の散布図
2変数の散布図

 もし2つの変数が独立であるなら、点の集まりに傾向は見られないはずです。グラフから読み取ることは不可能ではありませんが、難しい場合もあります。ここではPandasのメソッドで相関係数(相関の度合いを表す指標)を計算してみましょう。

 pointsとwon_1stだけに絞ります。またdropna()で値の入っていない行を除きます。

df_bis = pd.DataFrame({'points': points,
                       'won_1st': won_1st}).dropna()

 DataFrameのcorrメソッドにより、相関係数を表にした相関表を作成できます。

df_bis.corr()
相関表
相関表

 各数値は、変数間の相関係数を表しています。相関表では対角線(acesとaces)は必ず1になります。acesとpointsの相関係数は0.81なので正の相関があると考えられます。

 つまり1stサーブからの得点を多く取ったときには、ゲーム全体においても多くの得点を取っていることになります。

統計的検定を用いて相関を確認する

 では、データ間に検定を用いて統計的にも本当に相関が見られるか確認してみましょう。分割表の変数が独立であるか、カイ二乗検定を適用して検証していきます。まず変数を2値化します。いつもより多く得点を取っている(中央値より多い)場合にTrue、そうでなければFalseにします。

df_bis['result'] = (df_bis['points'] >df_bis['points'].median())
df_bis['manywon_1st'] = (df_bis['won_1st'] > df_bis['won_1st'].median())

 次に、2変数の組み合わせで4つの可能性(True-TrueやTrue-Falseなど)のそれぞれの頻度からなる分割表を作ります。

crossed  = pd.crosstab(df_bis['result'], df_bis['manywon_1st'])
crossed
分割表
分割表

 最後にカイ二乗検定の統計値とP値を計算します。統計的検定では否定されることを期待されるような仮説を立て、それが否定されるかどうかを確認します。この仮説は帰無仮説と呼ばれます。ここでの帰無仮説は「変数はそれぞれ独立である」とします。SciPy.statsにあるchi2_contingencyメソッドでこの検定を実行できます。

st.chi2_contingency(crossed)

 下記の結果が得られます。

    (19.54792240587695,
     9.810737324137886e-06,
     1,
     array([[11.25581395, 10.74418605],
            [10.74418605, 10.25581395]]))

 2番目の値がP値です。P値は帰無仮説が統計的に起こる確率を表しています。一般的には0.05(=5%)という値をしきい値として設定されます。

 ここではP値は0.05と比較して非常に小さいため、帰無仮説は否定(棄却)されました。「変数はそれぞれ独立である」が否定されたため、1stサーブからの得点の割合と、最終的な得点の割合の間には統計的に明確な相関があると示されました。

まとめ

 今回はPythonによる統計に挑戦しました。Pythonでは他にも、豊富なライブラリの力を借りてさまざまな統計処理が可能です。データ解析の目的に合わせて、必要に応じて統計を活用してみてください。

 次回以降ではPythonでの機械学習の実践に挑戦したいと思います。

この記事は参考になりましたか?

  • X ポスト
  • このエントリーをはてなブックマークに追加
Pythonによるデータ解析入門連載記事一覧

もっと読む

この記事の著者

WINGSプロジェクト 西 潤史郎(ニシ ジュンシロウ)

WINGSプロジェクトについて>有限会社 WINGSプロジェクトが運営する、テクニカル執筆コミュニティ(代表 山田祥寛...

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

山田 祥寛(ヤマダ ヨシヒロ)

静岡県榛原町生まれ。一橋大学経済学部卒業後、NECにてシステム企画業務に携わるが、2003年4月に念願かなってフリーライターに転身。Microsoft MVP for Visual Studio and Development Technologies。執筆コミュニティ「WINGSプロジェクト」代表。主な著書に「独習シリーズ(Java・C#・Python・PHP・Ruby・JSP&サーブレットなど)」「速習シリーズ(ASP.NET Core・Vue.js・React・TypeScript・ECMAScript、Laravelなど)」「改訂3版JavaScript本格入門」「これからはじめるReact実践入門」「はじめてのAndroidアプリ開発 Kotlin編 」他、著書多数

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

  • X ポスト
  • このエントリーをはてなブックマークに追加
CodeZine(コードジン)
https://codezine.jp/article/detail/11201 2018/11/15 14:00

おすすめ

アクセスランキング

アクセスランキング

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー

アクセスランキング

アクセスランキング