見出し画像

便利ライブラリ matplotlib③ 棒グラフを並べたり、積んだり、倒したり

matplotlibの3回目は棒グラフについてです。折れ線グラフに並んでよく使用するグラフだと思います。基本的には折れ線グラフと同じように書いていきますが、見栄えを良くするコツを覚え書としてまとめています。


基本的な書き方

サンプルデータとして以下を使用します。

import pandas as pd

df = pd.DataFrame(
    [['Jan', 10, 20, 50], 
     ['Feb', 10, 30, 40], 
     ['Mar', 10, 40, 10],
     ['Apr', 10, 50, 5]], 
    columns=['month', 'a', 'b', 'c'], 
)
df.set_index('month', inplace=True)

基本として、月ごとのaの値を棒グラフにします。matplotlibをimportし、plt.bar(x軸, y軸)というようにデータを指定します。
df.indexでDataFrameのインデックスがリストとして取得できる(['Jan', 'Feb', 'Mar', 'Apr'])ので、x軸として使用します。y軸データにはa列のデータを指定すれば良いので、df['a']を入力します。

import matplotlib.pyplot as plt
plt.bar(df.index, df['a'])

素の棒グラフを作成することができました。plt.bar()の引数に以下のようなパラメータを指定することで棒グラフの設定を変えることができます。

  • width:棒グラフの幅

  • color:棒の色(色の名前やカラーコード、RGBなどで指定可能。詳細は以下のサイトに分かりやすくまとめられています)

  • alpha:透明度(0~1の範囲で指定)

  • label:凡例

plt.bar(df.index, df['b'], width=0.5, color='lime')

棒グラフを並べる

先程は1つの系列データのみをグラフ化しましたが、大抵は複数の系列があります。並べるためにx軸を工夫します。
前項ではx軸の引数にdf.indexを使用しましたが、複数系列を並べる場合は、棒グラフを配置するポジションを指定します。
ここで、numpyを使用し配列として準備します。

import numpy as np
position = np.arange(len(df.index))
print(position)

> array([0, 1, 2, 3])
作成したポジションに1つ目の系列の棒グラフを配置します。棒グラフの幅を0.2とした場合、2つ目の系列は1つ目のポジションから0.2だけ右にズレれば良いので[0.2, 1.2, 2.2, 3.2]というポジションを作成すれば良いことになります。同様に3つ目の系列はさらに0.2ずつズレれば良いので、以下のように記述します。

position = np.arange(len(df.index))
gap = 0.2
# 2つ目の系列のポジション
print(position+gap)
# 3つ目の系列のポジション
print(position+gap*2)

> array([0.2 1.2 2.2 3.2])
  array([0.4, 1.4, 2.4, 3.4])
numpyを使用することで、意図した配列を簡単に作成することができました。これらをそれぞれのx軸に指定します。
x軸ラベルはplt.xticks(位置, ラベルリスト)を使用して別途設定する必要があります。

position = np.arange(len(df.index))
gap = 0.2

plt.bar(position, df['a'], width=0.2, color='darkturquoise', label='a')
plt.bar(position+gap, df['b'], width=0.2, color='skyblue', label='b')
plt.bar(position+gap*2, df['c'], width=0.2, color='dodgerblue', label='c')
plt.xticks(position+gap, df.index)  #2つ目の系列の中心にラベルが表示される 
plt.legend(loc='center left', bbox_to_anchor=(1, 0.5))

これを応用すれば、グラフを少し重ねておしゃれ(?)にすることもできます。棒グラフ幅よりもズレ幅を小さくすれば良さそうですね。

position = np.arange(len(df.index))
gap = 0.2

plt.bar(position, df['a'], width=0.3, color='darkturquoise', label='a')
plt.bar(position+gap, df['b'], width=0.3, color='skyblue', label='b')
plt.bar(position+gap*2, df['c'], width=0.3, color='dodgerblue', label='c')
plt.xticks(position+gap*2/3, df.index)
plt.legend(loc='center left', bbox_to_anchor=(1, 0.5))

棒グラフを積む

各系列の変化だけではなく総量の変化も見たいときには積み上げ棒グラフが描けると便利です。
積み上げる時には、棒グラフを配置するベースライン(bottom)を変更します。例えば1月のデータを見るとaの値が10なので、その上にbを積み上げるにはベースラインは10となり、そこから20の棒グラフが配置されます。さらにcを積み上げるためには10+20をベースラインとします。

plt.bar(df.index, df['a'], width=0.5, color='darkturquoise', label='a')
plt.bar(df.index, df['b'], width=0.5, color='skyblue', label='b', bottom=df['a'])
plt.bar(df.index, df['c'], width=0.5, color='dodgerblue', label='c', bottom=df['a']+df['b'])

plt.legend(loc='center left', bbox_to_anchor=(1, 0.5))

グラフを倒す

これまでは縦棒グラフでしたが、横棒グラフにすることも出来ます。やり方は簡単で、plt.bar()をplt.barh()に変えるだけです。水平を意味するhorizontalのhが付いています。
注意点としては、棒グラフ幅を設定するwidthはheightへ、積み上げの時にベースラインを設定するbottomはleftへ置換する必要があります。
また、y軸は下から上方向の順番に並ぶので今回の例のように月や時間の場合は表示順も考慮する必要があります。以下のコードでは、dfのデータの順番を逆順に並べ替えて対処しています。

# dfを逆順にソート(index番号を降順にソート)
df.reset_index(inplace=True)
df.sort_index(axis='index', ascending=False, inplace=True)
df.set_index('month', inplace=True)
position = np.arange(len(df.index))
gap = 0.2

plt.barh(position, df['a'], height=0.2, color='darkturquoise', label='a')
plt.barh(position+gap, df['b'], height=0.2, color='skyblue', label='b')
plt.barh(position+gap*2, df['c'], height=0.2, color='dodgerblue', label='c')
plt.yticks(position+gap, df.index)
plt.legend(loc='center left', bbox_to_anchor=(1, 0.5))
plt.barh(df.index, df['a'], height=0.5, color='darkturquoise', label='a')
plt.barh(df.index, df['b'], height=0.5, color='skyblue', label='b', left=df['a'])
plt.barh(df.index, df['c'], height=0.5, color='dodgerblue', label='c', left=df['a']+df['b'])

plt.legend(loc='center left', bbox_to_anchor=(1, 0.5))

おまけ(一部のみ色を変えて強調)

プレゼン資料などで一部のみ強調したい場合もあります。そんな時に使える小技です。
plt.bar()を適当な変数に格納すると、棒グラフをインデックス番号で指定することができるので、指定した棒グラフに対してset_color()で色を設定します。

position = np.arange(len(df.index))
gap = 0.2

a = plt.bar(position, df['a'], width=0.3, color='lightgrey', label='a')
b = plt.bar(position+gap, df['b'], width=0.3, color='darkgrey', label='b')
c = plt.bar(position+gap*2, df['c'], width=0.3, color='grey', label='c')
plt.xticks(position+gap*2/3, df.index)
plt.legend(loc='center left', bbox_to_anchor=(1, 0.5))

# 一部のみ色を変える
b[3].set_color('salmon')
c[0].set_color('orangered')

いい感じにおしゃれです(笑)。

この記事が気に入ったらサポートをしてみませんか?