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)になります。左端には統計項目が表示されており、それぞれ下記の意味になります。
項目 | 意味 |
---|---|
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つの変数が独立であるなら、点の集まりに傾向は見られないはずです。グラフから読み取ることは不可能ではありませんが、難しい場合もあります。ここでは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での機械学習の実践に挑戦したいと思います。