Pythonでグラフを作成する場合に問題が発生しました。
その問題とは、色に関することです。
早速ですが、以下のグラフを見てください。
内容は、オリックス山本由伸投手の投球に関する分析結果です。
違和感を感じませんか?
全投球のストレートは、青色です。
それに対して、決め球のストレートはオレンジ色となります。
なお、決め球のフォークが青色となっています。
この配色は、とてもわかりずらくないでしょうか?
ストレートは、青色で統一して欲しいと思いませんか?
思いますよね。
この記事では、この色バラバラ問題を解決する方法を説明していきます。
本記事の内容
- 解決方法は辞書型の永続データを用意すること
- 辞書型データの作成
- 辞書型データの保存(永続化)
- 辞書型データから色リストの作成
- 色を統一した円グラフ
それでは、上記に沿って解説していきます。
解決方法は辞書型の永続データを用意すること
結論は、辞書型の永続データを用意することです。
Pythonでは辞書型は、よく出てくるデータ型ですね。
もし理解が曖昧な場合は、次の記事で内容を確認してください。
永続データとは、簡単に言えば保存するデータと言う事ですね。
外部ファイルやデータベースに保存するのが、一般的でしょう。
もちろん、定数という形でコードにべた書きでも問題はありません。
でも、今回はそれを取り上げません。
べた書きは、スキル的には何も広がりませんからね。
以上より、解決方法の方向性については決まりました。
ここから先では、具体的な方法を示しながら問題解決に取り組んでいきます。
辞書型データの作成
具体例とともに辞書型データを説明していきます。
ただ、その前に対象とするデータと分析内容に関して説明しておきます。
対象データ
2020年プロ野球におけるピッチャーの全投球を対象としています。
期間は、2020年06月19日~2020年10月10日となります。
全投球数は、173373球。
MongoDBに173373件のレコードを登録している状態です。
レコードは、以下のような形式となります。
{ "_id" : ObjectId("5f81e24e465c99e3d94e6add"), "game_id" : "2020101006", "ball_count" : "1", "ball_no" : "1", "ball_type" : "ストレート", "batter_id" : "1800050", "batter_name" : "藤原 恭大", "catcher_id" : "1200096", "catcher_name" : "田村 龍弘", "pitcher_id" : "1800107", "pitcher_name" : "杉山 一樹", "result" : "空振り", "speed" : "154", "x" : "64", "y" : "54" },
分析内容
冒頭に挙げた円グラフが、分析内容となります。
簡単に言うと、投手ごとの決め球を調査しています。
山本由伸投手の場合であれば、フォークが決め球だと明らかです。
また、普段からフォークが多いということもわかります。
このような分析をするために、全投球と決め球の円グラフを並べています。
そこで、今回の色バラバラ問題がクローズアップされたと言うことです。
そして、今回は球種がグラフを構成する要素になりますね。
球種ごとに色を指定する(辞書型データの対象)
やっと、本題です。
イメージはできましたか?
球種ごとに色(カラーコード)が関連付いていれば、OKと言えます。
その関連付けを辞書型データで行おうと言うことです。
そのためには、まずは全球種の洗い出しから行います。
合計は、16種(173373球)です。
ball_type | count |
ストレート | 74714 |
スライダー | 27944 |
カットボール | 14157 |
フォーク | 13470 |
ツーシーム | 10602 |
チェンジアップ | 10350 |
カーブ | 8767 |
シュート | 4555 |
ナックルカーブ | 2508 |
シンカー | 2318 |
スプリット | 2003 |
縦スライダー | 1266 |
パワーカーブ | 412 |
スローカーブ | 111 |
スクリュー | 102 |
スラーブ | 94 |
球種(ball_type)をキーにした辞書型データを作成します。
作成した辞書型データは以下。
{'ストレート': (0.12156862745098039, 0.4666666666666667, 0.7058823529411765), 'スライダー': (0.6823529411764706, 0.7803921568627451, 0.9098039215686274), 'カットボール': (1.0, 0.4980392156862745, 0.054901960784313725), 'フォーク': (1.0, 0.7333333333333333, 0.47058823529411764), 'ツーシーム': (0.17254901960784313, 0.6274509803921569, 0.17254901960784313), 'チェンジアップ': (0.596078431372549, 0.8745098039215686, 0.5411764705882353), 'カーブ': (0.8392156862745098, 0.15294117647058825, 0.1568627450980392), 'シュート': (1.0, 0.596078431372549, 0.5882352941176471), 'ナックルカーブ': (0.5803921568627451, 0.403921568627451, 0.7411764705882353), 'シンカー': (0.7725490196078432, 0.6901960784313725, 0.8352941176470589), 'スプリット': (0.5490196078431373, 0.33725490196078434, 0.29411764705882354), '縦スライダー': (0.7686274509803922, 0.611764705882353, 0.5803921568627451), 'パワーカーブ': (0.8901960784313725, 0.4666666666666667, 0.7607843137254902), 'スローカーブ': (0.9686274509803922, 0.7137254901960784, 0.8235294117647058), 'スクリュー': (0.4980392156862745, 0.4980392156862745, 0.4980392156862745), 'スラーブ': (0.7803921568627451, 0.7803921568627451, 0.7803921568627451)}
色は、RGBで指定しています。
なお、このRGBはプログラムで作成(設定)しました。
今回は、話が逸れてしまうので、この部分の説明は省略します。
辞書型データの保存(永続化)
上記で作成した辞書型データを保存します。
このことをPythonでは、オブジェクトを永続化すると言うようです。
そして、オブジェクトの永続化で有名なのは、pickleです。
ただ、今回はjoblibを使います。
理由は、joblibの方が若干速いらしいからです。
いや、それ以上に新しいこと(知識)を試したいというだけですね。
正直、どっちでもいいです。
肝心の永続化方法は、以下のコードとなります。
import joblib joblib.dump(color_dic, "color_dic.jb", compress=3)
color_dicは、上記で作成した球種をキーにした辞書型データです。
これだけで、バイナリ化された「color_dic.jb」が作成されます。
今後は、これをもとに色リストを作成するということになります。
そうすれば、色バラバラ問題を解決できます。
辞書型データから色リストの作成
ここの部分は、プログラミングの説明がメインになります。
永続化した辞書型データをもとに色リスト(list型)を作成していきます。
まずは、「color_dic.jb」の読み込みです。
color_dic = joblib.load("color_dic.jb")
これだけで終わりです。
辞書型データのまま保存されています。
ただし、Pythonでグラフの色を指定するには一工夫が必要です。
色を指定する際には、リスト型が基本です。
そのため、辞書型からリスト型のデータを作成する必要があります。
また、データ(ラベル含む)との順序が一致していないといけません。
抽象的な説明より、具体的な説明をします。
円グラフは次のコードで表示できます。
matplotlib.pyplot.pie(data_list, labels=label_list, colors=color_list)
円グラフ自体の説明は、公式サイトをご覧ください。
(まだ、円グラフの記事は投稿していませんでしたね。。。)
何が言いたいかと言うと、以下の3つのデータは順序が一致していないダメということです。
- data_list(球数)
- label_list(球種名)
- color_list(色)
そこで、次のようなプログラミングで対応しています。
color_list = [] for key in data_list: try: color_code = color_dic[key] except: color_code = "#cccccc" color_list.append(color_code)
data_listの順序に合わせて、color_listを作成しています。
その際、color_dicが辞書型データであることを利用しています。
色を統一した円グラフ
色を統一した円グラフを表示しておきます。
比較してどうでしょうか?
明らかに、わかりやすくなりました。
ストレートは、青色と固定されています。
フォーク、カーブなど他の球種も色が固定されています。
これは、他の投手の分析結果でも言えることです。
以下は、千賀 滉大投手の分析結果となります。
千賀投手の場合でも、ストレートは青色です。
全投球、決め球の両方において。
つまり、一人の投手の分析内(全投球・決め球)における統一だけではないのです。
全分析内において、球種の色を統一できたということになります。
これもすべては、オブジェクトを永続化したおかげです。
それにしても、千賀投手はシンプルですね。
あと、カットボールがイメージより多いです。
メジャーを意識して、練習しているのでしょうか?