2022年MLB大谷翔平選手のスイーパーをPythonで調べてみた

## はじめに
先月のWBCで大谷翔平選手が大活躍したことは記憶に新しいですが、最近TVで大谷翔平選手が投げる**スイーパー**の曲がりが凄いと耳にします。

"スイーパー"って聞きなれないな？と思って調べたらどうやらMLBが今期から認定した新球種らしいということがわかりました。
https://news.yahoo.co.jp/byline/kikuchiyoshitaka/20230413-00345439

簡単に言うと、横に大きく曲がるスライダ―を"スイーパー"と呼ぶのだとか。
(縦のスライダ―と横のスライダ―を区別したという感じですかね。。)

おもしろいことにチャットGPTに聞いても答えてくれませんした笑
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3330349/034a4198-6416-fc24-3dcc-649de1c6c9fd.png)

サッカーでキーパーに張りついてディフェンスする人を"スイーパー"と呼ぶのですが、最近はこちらも全然聞きませんね。

さて、話が大きくそれましたが、今回はその大谷翔平選手が投げる"スイーパー"に興味が出たので、2022年のMLBでのデータを基にPythonを用いて簡単に調べてみました。

## データ取得
まず、2022年のMLBのデータですが、以下のサイトで手に入れました。
https://baseballsavant.mlb.com/statcast_search

検索画面で、Seasonを2022年、Grope ByをTeamにして検索を行うと
![mlb01_01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3330349/fa15f2a9-b420-4e02-739a-4c97f7cf6f4a.png)

メジャーリーグ全30球団が表示されます。この各球団をそれぞれ選択し、右のGraphsからDownload CSVをクリックすると、csvファイルをダウンロードすることができます。
![mlb01_02_csv保存.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3330349/1ea9f084-5eb4-63fa-018b-8bfed82f51b2.png)

以下のように、全30MLB球団のcsvファイルのダウンロードが完了したら
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3330349/c3a040b8-b1ba-e854-7ad5-5593d3b565cb.png)

今度はそれらを扱いやすいように、30個あるcsvファイルを1つのcsvファイルにまとめました。
(参照: https://webdesign-ginou.com/csv_matome)

このようにしてできたメジャーリーグ全30球団の投手データを"mlb_all_pitcher_data.csv"名前で保存。
以降では、そのファイルをGoogle Drive上にマウントし、実行環境はColabを用いることを前提として説明を行っていきます。

## Pythonコードの実行

まずは、csvファイルを読み込むのに必要なPolarsというPythonのライブラリで読み込みます。

Polarsは、以下のコマンドでインストールする必要があります。
```python
!pip install polars
```
インストールが完了したら、Polarsを読み込みます。
```python
import polars as pl
```
これでPolarsを利用することができるようになりました。

さて、いよいよ作成したMLBのデータの読み込みに入りますが、カラムについては92個もあり、正直不要なものがたくさんあったため、必要なカラムのみ読み込みを行いました。

※カラム情報は以下の公式の説明を参考にしました。
https://baseballsavant.mlb.com/csv-docs

上記をもとに、あらかじめ自分の主観で使えそうだと思ったものを選び、カラム名をリスト格納。
```python
columns = ["pitch_type","player_name","release_speed","release_pos_x","release_pos_z","events","stand","pfx_z","pfx_x"]
```
上記で選定したカラムのみ読み込みました。

```python
pl_mlb_pitch_data=pl.read_csv("./data/mlb_all_pitcher_data.csv",columns=columns)
pl_mlb_pitch_data.head(5) # 先頭の5行を表示
```
以下がその出力。
| release_speed | release_pos_x | release_pos_z | player_name         | events      | stand | pfx_x | pfx_z | pitch_name        |
|--------------|--------------|--------------|---------------------|-------------|-------|-------|-------|------------------|
| 93.4         | -1.06        | 5.9          | "Stephens, Jack…"   | "field_out" | "R"   | -1.23 | 0.7   | "Sinker"         |
| 93.3         | -1.01        | 5.97         | "Stephens, Jack…"   | null        | "R"   | -0.63 | 1.11  | "4-Seam Fastbal… |
| 91.6         | -1.41        | 5.91         | "Stephens, Jack…"   | null        | "R"   | -0.68 | 1.17  | "4-Seam Fastbal… |
| 84.1         | -1.45        | 5.8          | "Stephens, Jack…"   | null        | "R"   | -0.87 | 0.29  | "Changeup"       |
| 75.2         | -1.44        | 5.98         | "Stephens, Jack…"   | "field_out" | "L"   | 1.44  | -0.89 | "Curveball"      |


なお、全体の件数としては約70万8千でした。
```Python
len(pl_mlb_pitch_data) # 全体の件数を確認 
```

```Python
708540
```

さらにまた、読み込みんだデータフレームを今回の大谷翔平選手のスイーパーを調べるという目的を達成するために必要そうな利用するカラムだけに絞るということを行ったり、カラム名の日本語化、単位の変換(インチ→cmやマイル→km/h)などのデータの加工をPythonコードを用いて行いました。
```Python
df_mlb_pitch_processing_data = df_mlb_pitch_data.with_columns([(pl.col("pfx_x") * 30.48).alias("横の変化量")])
df_mlb_pitch_processing_data = df_mlb_pitch_processing_data.with_columns([(pl.col("pfx_z") * 30.48).alias("縦の変化量")])
df_mlb_pitch_processing_data = df_mlb_pitch_processing_data.with_columns([(pl.col("release_speed") * 1.609).alias("球速")])
df_mlb_pitch_processing_data = df_mlb_pitch_processing_data.with_columns([(pl.col("pitch_name")).alias("変化球名")])
df_mlb_pitch_processing_data = df_mlb_pitch_processing_data.with_columns([(pl.col("player_name")).alias("投手名")])
df_mlb_pitch_select_data = df_mlb_pitch_processing_data[["投手名","変化球名","球速","縦の変化量","横の変化量"]]
df_mlb_pitch_select_data.head() # 確認
```
結果は以下のように加工しました。

| 投手名               | 変化球名        | 球速     | 縦の変化量 | 横の変化量 |
| -------------------- | --------------- | -------- | ---------- | ---------- |
| Stephens, Jack…      | "Sinker"        | 150.2806 | 21.336     | -37.4904  |
| Stephens, Jack…      | "4-Seam Fastbal | 150.1197 | 33.8328    | -19.2024  |
| Stephens, Jack…      | "4-Seam Fastbal | 147.3844 | 35.6616    | -20.7264  |
| Stephens, Jack…      | "Changeup"      | 135.3169 | 8.8392     | -26.5176  |
| Stephens, Jack…      | "Curveball"     | 120.9968 | -27.1272   | 43.8912   |

さらに今回は変化球がスイーパーの場合を調べたいので、変化球を"スイーパー"のみに抽出し、さらに投手ごとのスイーパーの"球速"、"縦の変化量"、"横の変化量"の平均を集計するということを行いました。
```python
# Sweeperのとき
df_pitch_Sweeper = df_mlb_pitch_select_data.filter(pl.col("変化球名") == "Sweeper")
df_pitch_Sweeper = df_pitch_Sweeper.filter(pl.col("横の変化量") >0) # Sweeperの横の変化量が正のみ(負を除く)
df_pitch_Sweeper_ave = df_pitch_Sweeper[["投手名","球速","縦の変化量","横の変化量"]].groupby("投手名").mean() #MLB全投手のSweeperの平均値
df_pitch_Sweeper_ave.head() # 確認
```
結果は以下のようになりました。上手く投手ごとに集計されたようです。
| 投手名 | 球速 | 縦の変化量 | 横の変化量 |
| --- | --- | --- | --- |
| Feltner, Ryan | 132.072083 | 5.706533 | 29.142267 |
| Voth, Austin | 134.631247 | 18.620509 | 30.791727 |
| Murfee, Penn | 128.307379 | 6.599039 | 42.844641 |
| Nogosek, Steph… | 129.180353 | 8.339667 | 43.7896 |
| Sewald, Paul | 133.20547 | 21.820587 | 30.550239 |


MLB投手のスイーパーの横の変化量の平均が求まったので、次に上位から順に40位までの投手を確認しました。
```python
df_pitch_Sweeper_ave.select(pl.col("投手名","球速","横の変化量").sort_by("横の変化量",descending=True)).head(40)
```
大谷翔平選手はかなり上位に来るかなと思ったのですが、大谷翔平投手のスイーパーの横の曲がりの平均は約35.6cmで、32位でした。
| 投手名            | 球速        | 横の変化量 |
|---------------------|------------|------------|
| Roberts, Ethan… | 133.326637 | 53.67793 |
| Weissert, Greg… | 131.594904 | 49.382082 |
| Civale, Aaron  | 127.097592 | 49.3268   |
| Bassitt, Chris… | 120.95453  | 47.871681 |
| Espino, Paolo  | 125.023736 | 47.730611 |
| King, Michael  | 132.448892 | 47.161938 |
| Wesneski, Hayd… | 130.694589 | 46.04602  |
| Ottavino, Adam… | 130.347155 | 45.248639 |
| Maton, Phil    | 130.168921 | 45.096404 |
| Criswell, Coop… | 124.848344 | 44.40555  |
| Yacabonis, Jim… | 131.369683 | 44.274297 |
| Keller, Mitch  | 133.894186 | 44.102651 |
| ...             | ...        | ...        |
| Thornton, Tren… | 132.148064 | 37.656105 |
| Urquidy, José  | 128.879999 | 36.832134 |
| Marinaccio, Ro… | 129.305199 | 36.650507 |
| **Ohtani, Shohei…** | 137.306298 | 35.677104 |
| Watkins, Spens… | 126.197378 | 35.482306 |
| Tepera, Ryan   | 128.86036  | 34.286757 |
| Crowe, Wil     | 140.1439   | 32.6136   |
| Woodford, Jake… | 132.079922 | 32.432283 |
| Martinez, Seth… | 128.123142 | 32.131709 |
| Rasmussen, Dre… | 136.065054 | 31.381947 |
| Foley, Jason   | 133.80444  | 31.285543 |
| Voth, Austin   | 134.631247 | 30.791727 |


個人的には、平均で約35cm曲がるだけでもすごいと思うのですが、その上がゴロゴロいるなんて、さすがメジャーリーグですね。。


ん？ 大谷翔平投手のスイーパーってこんなものか？と思ったのですが、**大谷翔平投手のスイーパーは高速に曲がる**ということを思い出しました。

このため、MLBで平均球速が135km/h以上のスイーパー投手を洗い出してみました。
```python
df_pitch_high_speed_Sweeper = df_pitch_Sweeper_ave.filter(pl.col("球速") >135) # 平均球速が135km/h以上のスイーパー
df_pitch_high_speed_Sweeper.select(pl.col("投手名","球速","横の変化量").sort_by("横の変化量",descending=True))
```
その結果、大谷翔平選手はMLBのTop3に入っていました！！
| 投手名             | 球速       | 横の変化量 |
| ------------------ | ---------- | ---------- |
| Phillips, Evan…    | 137.316319 | 38.867229  |
| Holmes, Clay       | 136.607842 | 38.711963  |
| **Ohtani, Shohei…**    | 137.306298 | 35.677104  |
| Crowe, Wil         | 140.1439   | 32.6136    |
| Rasmussen, Dre…    | 136.065054 | 31.381947  |
| Almonte, Yency…    | 135.112709 | 29.233464  |
| Jax, Griffin       | 139.096039 | 28.861839  |
| White, Mitch       | 137.410319 | 23.366046  |
| Schmidt, Clark…    | 139.031274 | 21.239293  |

大谷翔平投手のスイーパーは**高速で、横の曲がりが大きい**という点でMLBトップクラスだということをデータが物語っていますね。
(大谷翔平選手よりも上位のHolmes Clay投手やPhillips Evan投手も大変すごいと感じました。。)


## まとめ

今回は簡単に大谷翔平選手のスイーパーをPythonで調べるということを行いました。

次回は今回調べた**スイーパー**の被打率をPythonを用いて求めていきたいと思います。