3度目の正直
今週は3つの起こったことのおかげで、データ分析の楽しさを思い出しました。
最初はThinking ElixirポッドキャストのゲストChris GrangerさんはElixirのNx Explorerのライブラリを説明しました。このライブラリーはRの「Tidyverse」の「dplyr」関数をElixirに持ってます。グレインジャーさんと同じく、NxとLiveViewを初めて聞いたときに、R Studioより使いやすいかExploratoryのスクリプトのみのことができるかなと思い出しました。早く使ってみたいと思いましたが、まぁ、仕事に集中して、週末にしましょう。
次は@RyoWakabayashiさんは「Elixir でデータ分析 Explorer を使ってみた」の記事をここに書きました。いきなり、
Mix.install([
{:explorer, "~> 0.2.0"}
])
をで初期化して、いろんな例を書きました。filter
, select
, transform
、group_by
などの機能のれいを次々書いてくれました。これが最高です。やりたいことの例が全てあります。
昼時間に、昔 R Studioでやった分割を探してみました。うん、今コンピュータにないので、仕事の後にバックアップで探してみようと思いました。
でも、その午後に「Japan Baseball Weekly Podcast」の John E. Gibsonさんは「今年、阪神の大山悠輔選手はよく一球目の投球を打ってないですか?」と聞きました。もう、週末までに待てられない。
その聞いたの質問を2021年と2022年のデータで文献しましたが、まぁ、平均の選手より早いカウントで打ってると確認しましたが、例外のようではなかった。今度の12.18のショーにその結果を発表します。
その結果のMP3を送った後に、ギブソンさんは「一球目にホームランは?」と聞きました。うん、面白そうですね。「ちょっとお待ち下さい」と返事して、フィルターを追加して、結果で驚きました。
以下にその結果を最初から再現しましょう。
準備
最初はデータが必要です。データベースから安打の結果のレコードのみを取得して、何球の投球を含まれます。
LiveBookに「:explorer, "=> 0.2.0"}
でExplorerをロードして、新しい「Elixir」分を作成します。その中に、
import Explorer.DataFrame
alias Explorer.Series
df = from_csv!(
"/path/to/2022-batters-pitches-to-hits.tsv",
delimiter: "\t"
)
若林さんはimport Explorer.DataFrame
ではなくて、alias Explorer.DataFrame
を使用しました。うん、何度も何度も「DataFrame.関数名
を打ちたくないので、直接関数を使ってます。例えば、from_csv!
はDataFrame
モジュールの関数ですが、DataFrame
を抜くとよりわかりやすいかなと思います。
データフレームの構造が見えるとは好きですが、本当に表で表示してほしいです。DataFrame.table()
でできるよ。
df
|> table()
右にスクロールすると「home-run
」の結果が見えます。よっしゃー。
フィルター
今のデータが多すぎる。実際に「投球の数が1」と「打類がホームラン」だけを利用したいです。
df
|> filter(&Series.equal(&1["Pitches"], 1))
|> filter(&Series.equal(&1["HitType"], "home-run"))
|> table()
でも、グラシアル選手のセルが槙原選手より幅が広いです。これを見ると1980年代のShift_JISがわからないsprintf
関数の時代とか1990後半のUnicode関連ライブラリーが思い出します。うん、ElixirのString.pad_leading
とString.pad_trailing
関数がCJK互換性が必要ですか? どうやってその幅を計算していますか? もっと時間があったらPRを書きたくなります。
グループ化して要約する
では、引き続き、選手とチームをグループ化して、ホームランの数を計算しましょう。
df
|> filter(&Series.equal(&1["Pitches"], 1))
|> filter(&Series.equal(&1["HitType"], "home-run"))
|> group_by(["選手", "Team"])
|> summarise("Pitches": [:count])
|> table()
牧原選手の2つレコードが一つの集まって、2本塁を打ちました。よし。
名前の変更と配置(並べ替え)
次はPitches_count
という項目名を「本塁打」に変更して、「チーム」も入れましょう。そうして、最多の本塁打を上から並び替えましょう。
df
|> filter(&Series.equal(&1["Pitches"], 1))
|> filter(&Series.equal(&1["HitType"], "home-run"))
|> group_by(["選手", "Team"])
|> summarise("Pitches": [:count])
|> rename("Pitches_count": "本塁打", "Team": "チーム")
|> arrange(desc: "本塁打")
|> table()
うん、あのHAN
、YOM
、などより神
、巨
、などになるはずです。チーム列名をリネームするよりmutate
しましょう。
最初は、変更したいマップを作成して、
teams = %{
"CHU" => "中", "HAN" => "神", "HIR" => "広", "YAK" => "ヤ", "YOK" => "De", "YOM" => "巨",
"LOT" => "ロ", "NIP" => "日", "ORX" => "オ", "RAK" => "楽", "SEI" => "西", "SFT" => "ソ"
}
そうして、mutate
は新しい「チーム」列を作成して、リネームが必要なくなります。
df
|> filter(&Series.equal(&1["Pitches"], 1))
|> filter(&Series.equal(&1["HitType"], "home-run"))
|> mutate("チーム": &Series.transform(&1["Team"], fn team -> Map.get(teams, team) end))
|> group_by(["選手", "チーム"])
|> summarise("Pitches": [:count])
|> rename("Pitches_count": "本塁打")
|> arrange(desc: "本塁打")
|> table()
よっしゃー。ギブソンさんは正しかった。大山選手は一球目の本塁打がかんなり多いでしょう。巨人の岡本さんも昨日(6月24日にも一球目に打ちました。
テーブルの全体
あっ、最後にtable()
は最初の5つレコードしか表示していません。全部を見たいので、これに変更しましょう:
|> table(limit: :infinity)
すると、
+--------------------------------------------+
| Explorer DataFrame: [rows: 75, columns: 3] |
+-------------------+-------------+----------+
| 選手 | チーム | 本塁打 |
| <string> | <string> | <nil> |
+===================+=============+==========+
| 大山 悠輔 | 神 | 6 |
+-------------------+-------------+----------+
| 岡本 和真 | 巨 | 6 |
+-------------------+-------------+----------+
| 村上 宗隆 | ヤ | 5 |
+-------------------+-------------+----------+
| 万波 中正 | 日 | 4 |
+-------------------+-------------+----------+
| 柳田 悠岐 | ソ | 4 |
+-------------------+-------------+----------+
| 中田 翔 | 巨 | 4 |
+-------------------+-------------+----------+
| 牧 秀悟 | De | 4 |
+-------------------+-------------+----------+
| 山川 穂高 | 西 | 3 |
+-------------------+-------------+----------+
| 佐藤 輝明 | 神 | 3 |
+-------------------+-------------+----------+
| ポランコ グレゴリー | 巨 | 3 |
+-------------------+-------------+----------+
| 丸 佳浩 | 巨 | 3 |
+-------------------+-------------+----------+
| ウォーカー アダム | 巨 | 3 |
+-------------------+-------------+----------+
| 佐野 恵太 | De | 3 |
+-------------------+-------------+----------+
| 塩見 泰隆 | ヤ | 3 |
+-------------------+-------------+----------+
| 牧原 大成 | ソ | 2 |
+-------------------+-------------+----------+
| 中村 奨吾 | ロ | 2 |
+-------------------+-------------+----------+
| レアード ブランドン | ロ | 2 |
+-------------------+-------------+----------+
| マーティン レオネス | ロ | 2 |
+-------------------+-------------+----------+
| 淺間 大基 | 日 | 2 |
+-------------------+-------------+----------+
| 石井 一成 | 日 | 2 |
+-------------------+-------------+----------+
| 浅村 栄斗 | 楽 | 2 |
+-------------------+-------------+----------+
| 三森 大貴 | ソ | 2 |
+-------------------+-------------+----------+
| ロハス・ジュニア メル | 神 | 2 |
+-------------------+-------------+----------+
| 大城 卓三 | 巨 | 2 |
+-------------------+-------------+----------+
| 長岡 秀樹 | ヤ | 2 |
+-------------------+-------------+----------+
| 濱田 太貴 | ヤ | 2 |
+-------------------+-------------+----------+
| 西川 龍馬 | 広 | 2 |
+-------------------+-------------+----------+
| 鵜飼 航丞 | 中 | 2 |
+-------------------+-------------+----------+
| ビシエド ダヤン | 中 | 2 |
+-------------------+-------------+----------+
| 石川 昂弥 | 中 | 2 |
+-------------------+-------------+----------+
| 京田 陽太 | 中 | 2 |
+-------------------+-------------+----------+
| グラシアル ユリスベル | ソ | 1 |
+-------------------+-------------+----------+
| 中村 剛也 | 西 | 1 |
+-------------------+-------------+----------+
| バレラ ブレイビック | オ | 1 |
+-------------------+-------------+----------+
| 紅林 弘太郎 | オ | 1 |
+-------------------+-------------+----------+
| 杉本 裕太郎 | オ | 1 |
+-------------------+-------------+----------+
| 佐藤 都志也 | ロ | 1 |
+-------------------+-------------+----------+
| エチェバリア アデイニー | ロ | 1 |
+-------------------+-------------+----------+
| 近藤 健介 | 日 | 1 |
+-------------------+-------------+----------+
| 松本 剛 | 日 | 1 |
+-------------------+-------------+----------+
| 今川 優馬 | 日 | 1 |
+-------------------+-------------+----------+
| ヌニエス レナート | 日 | 1 |
+-------------------+-------------+----------+
| 宇佐見 真吾 | 日 | 1 |
+-------------------+-------------+----------+
| 山口 航輝 | ロ | 1 |
+-------------------+-------------+----------+
| 清宮 幸太郎 | 日 | 1 |
+-------------------+-------------+----------+
| アルカンタラ アリスメンディ | 日 | 1 |
+-------------------+-------------+----------+
| 島内 宏明 | 楽 | 1 |
+-------------------+-------------+----------+
| 鈴木 大地 | 楽 | 1 |
+-------------------+-------------+----------+
| マルモレホス ホセ | 楽 | 1 |
+-------------------+-------------+----------+
| 辰己 涼介 | 楽 | 1 |
+-------------------+-------------+----------+
| 中野 拓夢 | 神 | 1 |
+-------------------+-------------+----------+
| 小幡 竜平 | 神 | 1 |
+-------------------+-------------+----------+
| 糸井 嘉男 | 神 | 1 |
+-------------------+-------------+----------+
| 立岡 宗一郎 | 巨 | 1 |
+-------------------+-------------+----------+
| 倉本 寿彦 | De | 1 |
+-------------------+-------------+----------+
| 宮﨑 敏郎 | De | 1 |
+-------------------+-------------+----------+
| 山田 哲人 | ヤ | 1 |
+-------------------+-------------+----------+
| サンタナ ドミンゴ | ヤ | 1 |
+-------------------+-------------+----------+
| 小園 海斗 | 広 | 1 |
+-------------------+-------------+----------+
| 坂倉 将吾 | 広 | 1 |
+-------------------+-------------+----------+
| 會澤 翼 | 広 | 1 |
+-------------------+-------------+----------+
| 阿部 寿樹 | 中 | 1 |
+-------------------+-------------+----------+
| 木下 拓哉 | 中 | 1 |
+-------------------+-------------+----------+
| 宇草 孔基 | 広 | 1 |
+-------------------+-------------+----------+
| マルティネス アリエル | 中 | 1 |
+-------------------+-------------+----------+
| 大田 泰示 | De | 1 |
+-------------------+-------------+----------+
| 山崎 晃大朗 | ヤ | 1 |
+-------------------+-------------+----------+
| 梶原 昂希 | De | 1 |
+-------------------+-------------+----------+
| ソト ネフタリ | De | 1 |
+-------------------+-------------+----------+
| マッカーシー ジョー | オ | 1 |
+-------------------+-------------+----------+
| 西 純矢 | 神 | 1 |
+-------------------+-------------+----------+
| 中村 悠平 | ヤ | 1 |
+-------------------+-------------+----------+
| 岡田 貴弘 | オ | 1 |
+-------------------+-------------+----------+
| 川島 慶三 | 楽 | 1 |
+-------------------+-------------+----------+
| 安田 悠馬 | 楽 | 1 |
+-------------------+-------------+----------+
すべて一球目の本塁打を打った選手が表示されます。
まとめ
数年間ぶりデータをこんなに楽しんで分析してます。テンサーなどのMLではなくて、NxとLiveBookを初めてみたときにこんなデータで遊びの使い方でやりたい気持ちがありました。今週、グレインジャーさん、若林さん、とギブソンさんのおかげで未来のデータ分析が楽しいそうです。