Lean Baseball

No Engineering, No Baseball.

ホームランのひみつ(MLB編)〜バレルゾーンをPythonとBigQueryで可視化してみた

f:id:shinyorke:20180311175057p:plain

このグラフは2017年MLB(メジャーリーグベースボール)の打球データ約11万レコード(球)を打球速度×打球角度で可視化したものです.

ちょっとした傾向が見えますね,,,それを解説するのがこのエントリーのゴールです.

こんにちは,野球エンジニアです.

TL;DR

  • 「ホームランになりやすい打球速度と打球角度」の組み合わせを「Barrel Zone(バレル・ゾーン)」と呼ぶ
  • 長打を飛ばす上で,打球速度と打球角度を意識して飛ばすが重要!というのが今のトレンド
  • 打球を転がす(抜ける)ような当たりを目指すのはもう昔のお話(ただし否定はしない)
  • この手のデータの楽しみを知ってほしい!!!...のでみんなBaseball Geeksを読んでね!(宣伝)

なお,弊社「ネクストベース」が運営しているメディア「Baseball Geeks」の応援コンテンツであり,

先日(3/10)に開催しました「Pythonもくもく自習室 #8」の成果発表でもあります.

Baseball Geeks | Think logically, move emotionally

おしながき

免責事項

  • データはこちらのオープンデータ(MLB公式)を活用しています
  • 都合上,詳しいカラムの説明・実際のコードは省略します&詳しい質問には答えられません,あしからず*1

データの取得方法と扱い方(PythonとBigQueryを使う場合)

データの出処と取得方法

まずデータですが,こちらはMLBが公式に公開しているトラックマン*2およびPitch f/xのデータサイト「baseballsavant」のデータを用います.

こちらはCSVでのデータ取得が可能で,実際にアメリカの方がPythonで取得するためのコードを公開しています(これは非公式)

github.com

ちょっとPythonを使える人ならすぐデータを取れると思います*3.

なお私は,ダウンロードに関しては若干改造して別コードに仕立てて行いました.

※コードは雰囲気です(一部省略)

    URL = 'https://baseballsavant.mlb.com/statcast_search/csv'

    def __init__(self, output_dir='./data',):
        self.output_dir = output_dir

    @staticmethod
    def _get_params(team, year, player_type, **kwargs) -> dict:

        return {
            # 省略
        }

    def download(self, team, year, player_type, output_file='{year}_{player_type}_{team}.csv', **kwargs):
        params = self._get_params(team, year, player_type, **kwargs)

        url = '{url}?{params}'.format(
            url=self.URL,
            params='&'.join(['{k}={v}'.format(k=k, v=v) for k, v in params.items()])
        )
        successful = False
        while not successful:
            try:
                df = pd.read_csv(url, low_memory=False)
                df.to_csv(
                    '/'.join([self.output_dir, output_file.format(year=year, player_type=player_type, team=team)]),
                    index=False
                )
                successful = True
            except (HTTPError,) as e:
                logging.warning('Error:{}({})'.format(url, e))
                # エラーハンドリング的な処理

if __name__ == '__main__':
    ss = StatcastSearch(output_dir='適当な出力先')
    ss.download('MIA', 2017, 'pitcher')

なお,打球のみでなく,投球データすべてが取得できます(というか元は投球データ).

データの保存先

データの総量ですが,

  • 1ファイル68列
  • 1シーズンあたり72〜73万レコード(球)
  • ファイルサイズ290〜300MB(csvの場合)

となります.

5年集めたらGB超えます.

気軽にクエリ書いたり保存したりしたかったので今回もGoogle BigQueryのちからを借りました.

やったことはシンプルで,

  • クラウドストレージにcsvをアップロード
  • そのままBigQueryのテーブルを作成

です.

この辺の雰囲気は以前公開したブログで似たようなことをしているのでどうぞご参考にしてください.

shinyorke.hatenablog.com

可視化する(Jupyter notebook + Bokeh)

これはいつもどおりJupyter notebookとBokehを使いました.

最初の画像(全打球データ可視化)はこんなコードでできます.

# データフレームを取得(クエリはひみつ)
import pandas as pd
query = "select * from baseball-data where hoge='fuga' "  # ここは内緒
df = pd.read_gbq(query, 'my-project-name')

# 角度(launch_angle) ×速度(launch_speed)で可視化,結果(ホームラン・アウトetc...)ごとに色付け
from bokeh.charts import Scatter, output_notebook, show
from bokeh.models import Range1d, LabelSet, ColumnDataSource
output_notebook()

# 横(x):スピード, 縦(y):角度
p = Scatter(
    df,
    x='launch_speed',
    y='launch_angle',
    color='events',
    plot_width=800, 
    plot_height=400,
)

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

# p.add_layout(labels)
p.x_range=Range1d(120, 200)
p.y_range=Range1d(-10, 90)
p.xaxis.axis_label = '打球速度(km/hに変換)'
p.yaxis.axis_label = '打球角度(-10〜90度)'
show(p)

このコードでこんな感じに表示ができます.

f:id:shinyorke:20180311175057p:plain

ここまでできると,MLBにおけるホームラン性打球の秘訣「バレルゾーン」の可視化が可能となります.

バレルゾーン #とは

メジャーリーグをご覧になってる方であれば,昨年流行った「フライボールレボリューション」という言葉をご存知の方も多いかと思います.

「バレルゾーン(Barrel Zone)」はそんなフライボールレボリューションを指標化した新指標です.

大雑把に言うと,

打球が一定の速度(99mile/h以上)かつ,一定の打球角度になるとホームラン・長打が出やすくなる

という考え方に基づいた指標です.

詳しい理論・具体例については「Baseball Geeks」の紹介記事もしくはMLB公式記事(英語)を御覧ください.

www.baseballgeeks.jp

m.mlb.com

ここではBaseball Geeksに掲載されている以下の3つの区分でバレルゾーンを可視化してみました.

  • 158〜161km/h, 26〜30度
  • 161〜187km/h, 24〜33度
  • 187km/h以上, 8〜50度

打球速度が上がれば上がるほど,角度のレンジ(幅)が広くなります.

バレルゾーンその1(158-161km/h)

最初の散布図から打球速度の幅だけフィルターして出してみました.

参考としてバレルゾーン外の打球も出しています(以下の例も同じ).

まず161km/hまでの傾向です.

f:id:shinyorke:20180311184151p:plain

home_run(緑色,もちろんホームラン),double/triple(赤,二塁打・三塁打)を表すプロットがBarrel Zone周辺に集まってるように見えます.

この速度帯でも打球角度が44度を超えた当たりからアウト(青色)になるリスクが増えています.

そして面白いのが,バレルからちょこっと上のゾーン(32〜40度)あたりにもホームランが集中しています.

バレルゾーンその2(161-187km/h)

同じ方法で161〜187km/hのグラフを見てみます.

f:id:shinyorke:20180311184647p:plain

面白いように,バレルゾーン近辺にホームランが増えています!

対象の打球が多いゆえ,角度から外れたものとの明確な差が見えているような気がします.

バレルゾーンその3(187km/h以上)

この辺になると,筋骨隆々のパワーヒッター・バケモノがひしめく...と同時に対象の打球が減ります.

f:id:shinyorke:20180311184849p:plain

ほぼほぼホームランですね(驚愕)

中身が気になるのでデータフレームを見てみます.

f:id:shinyorke:20180311185249p:plain

わかっちゃいることですが,アーロン・ジャッジ(ヤンキース)とジャンカルロ・スタントン(昨年マーリンズ,今年からヤンキース)ばっかりです(すごい)

面白いのが,スタントンの打球でfield_out(つまりアウト)になってるものが一個だけありました笑.

今回は結構簡単な分析・可視化でしたがどうやらバレルゾーンは結構面白そうです!

データと科学,ITの力で未来の野球を観よう!Baseball Geeksで

手前味噌で恐縮ですが!

こういった分析とデータ・科学そしてITを駆使して私がJOINしたチーム「ネクストベース」では野球の新しい見方・未来の野球を追求して日々情報発信をしております.

www.baseballgeeks.jp

先日スポナビでも上原浩治投手の可能性についてのコラムも寄稿させてもらっています.

sports.yahoo.co.jp

今後も情報を発信しつつ,今度は私もBaseball Geeksで記事をかけるように頑張るので何卒よろしくお願いいたします!

&野球Hackもやれる限りこのブログで発信しますのでよろしくお願いいたします!

【おまけ】打球速度ランキング

ついでに打球速度ランキングも出しました.

f:id:shinyorke:20180311185846p:plain

わかりやすいぐらいにパワーヒッター多いですね笑

個人的にはもう40歳近いネルソン・クルーズ(マリナーズ)が頑張ってるのにすごいなと思っています.

【おまけ】イチロー選手の打球速度 by 2017年

つい先日6年半の時を越えてマリナーズに復帰したイチロー選手の2017年打球速度ランキングです(Top20).

もちろん,数字はすべて昨年所属のマーリンズのものです.

f:id:shinyorke:20180311190044p:plain

全3本のホームランがランク入り,二塁打も6本中3本が入ってます.

今年はどういったスタイルを取るんでしょうねえ?気になります.

【おまけ】参考書籍(理解を深めたい方へ)

いつもどおり,Jupyter notebook本を元に可視化・分析しました.

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

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

トラッキングデータについて文章で知りたい方はぜひビッグデータ・ベースボールを!

ビッグデータ・ベースボール 20年連続負け越し球団ピッツバーグ・パイレーツを甦らせた数学の魔法

ビッグデータ・ベースボール 20年連続負け越し球団ピッツバーグ・パイレーツを甦らせた数学の魔法

*1:大人の事情です察してください

*2:投球・打球のデータを取得するためのシステム.詳細はBaseball Geeks「「トラックマン」とは?最先端の計測機器で取れるデータを紹介!! | Baseball Geeks」に詳しく載ってます

*3:PythonスクリプトもしくはJupyter notebookでコードがあります