Lean Baseball

No Engineering, No Baseball.

野球データ分析を支えるPythonなノウハウ〜Jupyter notebookとpandas,SQLを添えて

f:id:shinyorke:20171219134352p:plain

※2017/12/19 20:45 この分析結果の詳細スライドを追加

Top写真(サムネイル)は雰囲気です,あまり気にしなくてOK.*1

Jupyter Advent Calendar 2017 19日目の記事です.

ここでは,本年私がやった野球ネタの主に分析環境まわりについての話をサンプルや選定理由を絡めて紹介します.

本日開催されたBaseball Play Study 2017冬の発表資料「うわっ...アイツの年俸、高すぎ...?」を作った時のコードスニペットから作成しています.

speakerdeck.com

Python初学者〜中級者および,私と同じく野球が好きでたまらないンゴな方の参考になると嬉しいです.

上級者および強者の方には是非もっといい方法があったらコメント頂けると嬉しいです.

申し遅れましたこんにちは,私が「野球の人」ことshinyorke(シンヨーク)です.

この記事のダイジェスト(言いたいこと)

  • データの中身をみてみたり,サマリーしたり軽いことをやるならJupyter notebook最強!
  • 分析でMySQL使うならPyMySQLがお手軽でオススメ
  • ひとまずデータはpandasに放り込んでから分析のあれこれを試す
  • 可視化はbokehでもseabornでもJSでも何でもいいがまあ手に合う道具で
  • ググったり迷ったりする時間は勿体無いので#Jupyterbookを手元においておこう!!

#Jupyterbookが何者かは最後にちゃんと紹介します.(我慢できない人はリンク先をどうぞ)

スターティングメンバー

野球データ分析を支える技術〜使ってる環境・ライブラリの紹介

今年のPyCon JP 2017発表でも言及しましたが,私は主に適当な実験的なネタを試す時にJupyterを使っています.

現時点(2017/12/19現在)では以下の構成で環境を作ってやっています.

  • ベースの環境はAnaconda(インストール時点の最新Ver.)で構築
  • Jupyterは迷わず最新版
  • 野球データ(前処理済み)はすべてMySQLに保存
  • MySQLのコネクタはPyMySQLを利用
  • 統計処理やちょっとしたデータのお掃除はpandas
  • 可視化は#Jupyterbookのお陰でこなれてきたbokehを利用

なお,PCは私自身が林檎信者なのでMac(High Sierra)を使っています&基本,Macなつもりでこのあとは紹介していきます.

※ちなみにDB(MySQL)はDockerです(Mac for Docker上に構築)

Jupyter環境について

最近は,#Jupyterbookや幾つかのPython本,Qiitaの記事などで紹介している数が多いAnacondaを使っています.

正直この環境周りの所は議論が多く,特に「Anacondaは良いか悪いか」的な話はところどころありますが,こんな理由でAnacondaにしてます

Anacondaを使う理由

  • (乱暴な言い方ですが)SQLをちょろっと書いてグラフを書く程度ならライブラリ・環境の管理に神経を使わないAnacondaで良い ※個人的な感想です
  • (もう昔の話かもですが)Windowsでscipyとか入れるのが辛いので,パッケージとして最初からいい感じにしてるAnacondaに頼った方がいい

実を言うと私は#Jupyterbookを読むまではAnaconda否定派*2だったのですが,

Anaconda否定派のワイが鞍替えしたゆるい理由

  • Pythonの環境変数や仮想環境周りの理解が去年以上に進んだ
  • Anacondaと通常のPython環境を同居させても特に問題が無かった&問題なときも自己解決できた
  • データ分析はAnaconda,ちょっとしたプロダクト(Webアプリやバッチ,ツールなど)を作る時はpipと切り分けたほうが柔軟に開発が進むことに気がついた

という状況と心境の変化があり,今はAnacondaとpipを仲良く同時並行して使っています.

というわけで, どっちがいい・悪いは知りませんが,自分が信じる方を使うと良いかなと思います.*3

MySQLとの接続(PyMySQL)

いろんなサイトからスクレイピングしたり,オープンデータとして入手した野球データは基本的にMySQLに突っ込んでいます.

使うバージョンはその時点の最新版,MySQLな理由もこだわりも特に無いですが...強いて言うなら,

  • 世の中にノウハウが沢山ある
  • 仕事でもずっと触ってる
  • ぶっちゃけリレーショナルデータベースならなんでも良い

そんなぐらいです,特定製品・OSSについてのアレルギーは特にありません.

ちなみに面倒くさい時はSQLite3も使ってます.

そんな理由でMySQLを使っていますが,コネクタ(DB API)だけはこだわりがあって,基本的にPyMySQLを使っています.

純正のmysql-clientに依存していない為,依存するライブラリ・資産がほぼ無いこと,すべてPythonでの実装で基本的にPythonが動く環境であればどこでも動くという利点が気に入っています.

ただ,純正のmysql-clientと異なるため意図しない動きをするかもしれない・新しいAPIやライブラリ仕様に追随できない可能性が高い,パフォーマンスが...と気になりそうなポイントがありますが,私自身はそれらを気にするシチュエーションじゃないこと,気にする用になったら純正の奴を使う!と決めているのでまあこれでいいかなと思っています.*4

なお,Jupyter上でやるときは

  • 予め環境変数を用意,host・user・password等必要な情報を保存しておく
  • notebookからは,環境変数に展開した情報を読み込んでconnectionを作る

これをやる程度なら数行で終わります.

環境変数ファイル(.env)

export ENCODING=utf8;
export DB_HOST=127.0.0.1;
export DB_USER=yakiu;
export DB_PASSWORD=334334334;
export DB_DATABASE=npb;
export DB_PORT=3306;

環境変数を読み込んでから起動

$ source .env
$ jupyter notebook

PyMySQLのconnectionを作る

作られたconnection(conn)は後述するpandasのread_sqlのconnectionとして使いまわします.

# notebookでやるときに書いてるおまじないです
from pymysql import connect

conn = connect(
    host=os.environ.get('DB_HOST'),
    user=os.environ.get('DB_USER'),
    db=os.environ.get('DB_DATABASE'),
    password=os.environ.get('DB_PASSWORD'),
    charset=os.environ.get('ENCODING')
)

pandasからMySQLのデータを拾う(read_sql)

pandasには「read_ほげほげ」という便利なメソッドからDataFrameを瞬殺で作ることができます.*5

(MySQLに限らず)リレーショナルデータベースの場合はread_sqlから恐ろしく簡単に作れちゃいます.

例えば私が「野手の年俸ランキングが欲しいンゴ」と思ったらこれだけで済みます.

select文の結果をそのままpandasのDataFrameにする

# pandasをimport

import pandas as pd

# バッター情報(player_batting)と年俸情報(salary)をjoinして表示,スキーマはなんとなく察してください
query_player_salary ="""
select p.name as `NAME`, p.team as `TEAM`, pf.position as `POSITION`, pf.age as `AGE`, pf.career_year as `CAREER`, p.ba as `AVG`, p.hr as `HOME RUN`, p.rbi as `RBI`, p.wraa as `wRAA`, s.salary / 1000000 as `Salary(million)`, s.up_down / 1000000 as `Salary Up/Down`
 from player_batting as p left outer join profile as pf on p.year = pf.year and p.name = pf.name left outer join salary as s on p.year = s.year and p.name = s.name and p.team = s.team where p.date = '2017-10-12' and pf.date = '2017-10-13' and s.salary > 0 order by `Salary(million)` desc
"""

# connはPyMySQLのconnection,他のconnectionでももちろんOK
df_player_salary = pd.read_sql(query_player_salary, conn)

結果はこんな感じになります,メヒアって年俸高いんですね(こなみ)*6

f:id:shinyorke:20171219143331p:plain

グラフ可視化について

基本はmatplotlib,簡単かつかっこよく出すならseabornが良いかなと思っていて,私自身は前まではseabornをよく使ってました.

が,最近はbokehをよく使っています.

まだ使いこなせていない面はありますが,デザイン表現が多彩かつ,インターフェースがmatplotlibよりわかりやすい利点が好きで使っています.

私はpandasのDataFrameからplotすることが多いです.

【例】プロ野球選手(野手)2017年度の年俸分布(散布図)

ラベル付きの散布図を出す例です.

DataFrameの中身およびスキーマは皆さんのフォースの力で脳内再生してくださいw

# notebook上で出すのでおまじない
output_notebook()

# メインの散布図,ポジション(Pitcher, Catcher, In Fielder, Out Fielder毎に色付け)
p = Scatter(
    df_player_salary, 
    x='wRAA', 
    y='Salary(million)', 
    color='POSITION',      
    title='年俸と得点能力の分布(X:得点能力(wRAA) Y:年俸(100万円単位))',
    plot_width=1200, 
    plot_height=800)

# 散布図と同じ座標位置のラベル(選手名)をつける
labels = LabelSet(
    x='wRAA', 
    y='Salary(million)', 
    text='NAME', 
    level='glyph',
    x_offset=5, 
    y_offset=5, 
    source=ColumnDataSource(df_player_salary), 
    render_mode='canvas')

p.add_layout(labels)

p.xaxis.formatter = NumeralTickFormatter(format='0,0')

# 表示
show(p)

このような散布図が得られます,いやあ綺麗ですね.

f:id:shinyorke:20171219144354p:plain

今後やりたいこと

前処理から簡単な分析まではできるようになったので,今後は仕組み化をやっていければと思っています.

  • Jupyter環境をどっからでも触れるオレオレServerに立てる
  • Google Drive等のクラウドストレージからいい感じに共有

まあこの手の奴はGoogleやAzureのサービスで既に合ったりしますが,いかんせんバージョン古いのと,自分なりにいじりたい欲あるので,オンプレでも何でも持ちたいなと思ってます,メンテは多分やれるので.

あと,野球データ分析的には,

  • pitch f/xのトラッキングデータで投球・打球分析をやる.MLBはデータがオープン化されているので可能!
  • 大谷翔平(エンジェルス)がカモにできそうな打者・投手を探す

みたいなテーマでもっと上を目指した分析をやりたいと思っています!

【補足】お仕事や業務での活用方法

さて,全編野球でお届けしたこのエントリーですが,

Jupyter notebookはちょっとしたお仕事の調査・分析でも絶大たる威力を発揮します!

拙作で恐縮ですが, Retty Inc. Advent Calendar 2017で紹介させてもらっていますので,是非ともご参考頂ければと思います.

qiita.com

Jupyterのインストールから簡単なpandasの使い方,requestsを使ったREST API呼び出しなど,すぐ使えるテクニック満載です!(手前味噌)

何度でも言う,「PythonユーザのためのJupyter[実践]入門」は必読やぞ!

今回のJupyterおよびbokehに関するノウハウ・知見は#Jupyterbookこと,「PythonユーザのためのJupyter[実践]入門」を参考に色々とやらせてもらいました.

PythonユーザのためのJupyter[実践]入門

PythonユーザのためのJupyter[実践]入門

書評は以下エントリーにも書きましたが,ちょっとした分析をする方から機械学習マンまで必読の一冊かと思います.

shinyorke.hatenablog.com

何度でも言う,「PythonユーザのためのJupyter[実践]入門」は必読やぞ!

...明日はそんな「PythonユーザのためのJupyter[実践]入門」の著者の一人である,「どりらん」さんですお楽しみに!

*1:Baseball Play Study 2017冬登壇資料の一部です

*2:pipで自前で管理出来る程度にはPython使えるので必要性がほぼゼロでした

*3:本でもブログでもキッカケは何でもいいですが,選んだ技術には自分で責任を持とう,という話です.エンジニア志望だったりTech LeadやCTO目指してる人は必須の考え方だからね!

*4:エンジニアが技術やライブラリを取捨選択するのはホント大事で,「何をとって何をすてるか」を決めるところまで鍛えるのはホント大事

*5:HTMLのTableタグからDataFrameを作る黒魔術的な方法「read_html」というのもあります(スクレイピングしてそのままやれる),詳しくは過去エントリーをどうぞshinyorke.hatenablog.com

*6:そろそろ劣化の懸念あるけどどうなんだろう?