こんにちは。6月に入りさっそく蒸し暑い日が続いています。そろそろエアコンをつけても良い時期ですね。今回はMatplotlibの棒グラフの制御方法に関して紹介します。
はじめに
本ブログの記事でもたまに登場しますが、棒グラフを書く機会は業務・趣味問わずたびたび訪れます。そのたびに細かい調整方法をググっており、非効率だと感じていました。個人的によく使う、このような棒グラフを書くためのテクニックをまとめたのでご覧ください。
この図を描くためのソースコードは以下になります。それぞれの要素を見てきましょう。
import matplotlib.pyplot as plt import matplotlib.cm as cm import japanize_matplotlib acc = [88, 90, 98] acc_comp = [66, 72, 94] fig, ax = plt.subplots(figsize = (8, 6)) #グラデーションで表現するためのカラーリストの定義 color_list = [cm.winter_r(i/3) for i in range(3)] rect = ax.bar([1, 2, 3], acc, color = color_list, width = 0.5, alpha = 0.80) ax.set_ylim(80, 105) ax.set_yticks(range(60, 110, 10)) #軸ラベル(tick)の変更とサイズ変更 ax.set_xticks([1, 2, 3]) ax.set_xticklabels(["50枚", "100枚", "1000枚"]) ax.tick_params(labelsize = 15) ax.set_ylabel("正解率", fontsize = 18) ax.set_xlabel("教師あり画像の枚数", fontsize = 18) #数字の挿入(アノテーション) def autolabel(rects): for rect in rects: height = rect.get_height() #annotationで文字やその位置を定義。文字を改行したいときは\nを挟む。 ax.annotate('{}%\n(SGAN)'.format(height), xy=(rect.get_x() + rect.get_width() / 2, height), xytext=(0, 3), textcoords="offset points", ha='center', va='bottom', fontsize=14) autolabel(rect) plt.show()
棒グラフへの数値の挿入
棒グラフを書いていると、各棒の頭にその具体的な数値を挿入したくなることがあります。その場合にはannotationを使うのがおススメです。Matplotlibの公式ドキュメントの方法ですが、グラフオブジェクトをrectなどと定義しそれをループをかけると各棒ごとに文字を挿入することができます。グラフのサイズはrectから取得できるので便利です。
Grouped bar chart with labels — Matplotlib 3.1.0 documentation
#対応箇所 fig, ax = plt.subplots(figsize = (8, 6)) rect = ax.bar([1, 2, 3], acc, color = color_list, width = 0.5, alpha = 0.80) def autolabel(rects): for rect in rects: height = rect.get_height() #annotationで文字やその位置を定義。文字を改行したいときは\nを挟む。 ax.annotate('{}%\n(SGAN)'.format(height), xy=(rect.get_x() + rect.get_width() / 2, height), xytext=(0, 3), textcoords="offset points", ha='center', va='bottom', fontsize=14) autolabel(rect)
軸ラベルの調整
各棒に、日付や条件などの適当なラベルを与えたいことがあります。これにはax.set_xticksとax.set_xticklabelsをセットで使うのが良さそうです。ax.set_xticklabelsでラベルを定義しますが、これだけではエラーが出るので注意が必要です。
#対応箇所 fig, ax = plt.subplots(figsize = (8, 6)) rect = ax.bar([1, 2, 3], acc, color = color_list, width = 0.5, alpha = 0.80) #軸ラベル(tick)の変更とサイズ変更 ax.set_xticks([1, 2, 3]) ax.set_xticklabels(["50枚", "100枚", "1000枚"]) ax.tick_params(labelsize = 15)
グラデーションの追加
これは趣味の問題かもしれませんが、数値に伴ってグラデーションを付けると見栄えが良くなる気がします。カラーマップをインポートし、ここから好きなグラデーションを選択します(Maptlolibの公式ドキュメントをご覧ください)。プロットするデータ数だけの色データを含んだ配列を定義し、それをax.barに渡します。ここではwinterグラデーションを反転させたものを使っています。
Choosing Colormaps in Matplotlib — Matplotlib 3.1.0 documentation
#対応箇所 import matplotlib.cm as cm color_list = [cm.winter_r(i/3) for i in range(3)] fig, ax = plt.subplots(figsize = (8, 6)) rect = ax.bar([1, 2, 3], acc, color = color_list, width = 0.5, alpha = 0.80)
適宜、必要個所をコピペしてお使いください!