【Python】【Seaborn】複数の棒グラフを並べて表示する
棒グラフでグループ毎に値を並べて表示したい場合などがある。
matplotlibだと多少面倒だが、seabornのbarplotの引数hueを使うと、少しデータ整形が必要になるが、簡単にグラフを作成することができる。
ポイントは、hueを使えるようにするために、x軸となる列をインデックスに設定し、並べたい列をstackで積み上げることである。
データ作成
以下のデータを対象とする。
1import pandas as pd
2
3data1 = [30, 35, 40]
4data2 = [24, 28, 31]
5data3 = [20, 25, 25]
6index = ["Aさん", "Bさん", "Cさん"]
7df = pd.DataFrame(data={"額面": data1, "手取り": data2, "支出": data3}, index=index)
8print(df)
9# 額面 手取り 支出
10# Aさん 30 24 20
11# Bさん 35 28 25
12# Cさん 40 31 25
Aさん、Bさん、Cさん毎に、額面、手取り、支出を並べて棒グラフに表示する。
データ整形
seabornのbarplotのhueを指定できるような形に整形する。
一気にやると以下のようなコードになる。
1# 以下の処理を行う
2# stack
3# index名の設定
4# nameの設定
5# reset_index
6
7data = df.stack().rename_axis(["name", "category"]).reset_index().rename(columns={0: "金額(万円)"})
8# 以下のようなコードでも可能
9data = df.stack().rename("金額(万円)").rename_axis(["name", "category"]).reset_index()
10# index名はreset_index前にしておく
11# nameの設定はreset_indexの前後どちらでもOK
12
13print(data)
14# name category 金額(万円)
15# 0 Aさん 額面 30
16# 1 Aさん 手取り 24
17# 2 Aさん 支出 20
18# 3 Bさん 額面 35
19# 4 Bさん 手取り 28
20# 5 Bさん 支出 25
21# 6 Cさん 額面 40
22# 7 Cさん 手取り 31
23# 8 Cさん 支出 25
これで、hueにcategoryを指定することで、Aさん、Bさん、Cさん毎に棒グラフを並べて表示することが可能となる。
上記の処理を細かく分解すると以下のようになる。
stackでデータを縦にする
stackでインデックスに対し、列を全て縦にする。
1df.stack()
2# Aさん 額面 30
3# 手取り 24
4# 支出 20
5# Bさん 額面 35
6# 手取り 28
7# 支出 25
8# Cさん 額面 40
9# 手取り 31
10# 支出 25
df.stack()の結果はマルチインデックスのSeriesとなる。
「Aさん、Bさん、Cさん」の列と「額面、手取り、支出」の列は両方ともインデックス列。
数値の列が値の列となる。
列名を全て変更する
rename_axisでインデックス名を変更する。
1df.stack().rename_axis(["name", "category"])
2# name category
3# Aさん 額面 30
4# 手取り 24
5# 支出 20
6# Bさん 額面 35
7# 手取り 28
8# 支出 25
9# Cさん 額面 40
10# 手取り 31
11# 支出 25
なお、この時もまだ、Seriesであることに注意。
インデックスをリセットする
reset_indexでインデックスを解除する。
1df.stack().rename_axis(["name", "category"]).reset_index()
2# name category 0
3# 0 Aさん 額面 30
4# 1 Aさん 手取り 24
5# 2 Aさん 支出 20
6# 3 Bさん 額面 35
7# 4 Bさん 手取り 28
8# 5 Bさん 支出 25
9# 6 Cさん 額面 40
10# 7 Cさん 手取り 31
11# 8 Cさん 支出 25
ここでようやく型がDataFrameになる。
Seriesの時にname属性を設定していない場合、reset_indexすると列名は「0」になる。
値の列名を変更する
「0」となっている列名を変更する。
1df.stack().rename_axis(["name", "category"]).reset_index().rename(columns={0: "金額(万円)"})
2# name category 金額(万円)
3# 0 Aさん 額面 30
4# 1 Aさん 手取り 24
5# 2 Aさん 支出 20
6# 3 Bさん 額面 35
7# 4 Bさん 手取り 28
8# 5 Bさん 支出 25
9# 6 Cさん 額面 40
10# 7 Cさん 手取り 31
11# 8 Cさん 支出 25
もちろん、reset_index前のSeriesの状態でnameを設定してから、reset_indexしてもOK。
1df.stack().rename("金額(万円)").rename_axis(["name", "category"]).reset_index()
これで上記と同じ形に整形される。
棒グラフを並べて表示
seabornのbarplotにhueを指定して棒グラフを並べて表示する。
1# 日本語の文字化けを防ぐ
2sns.set(font="meiryo")
3# グラフサイズ設定。
4# facecolor="w"に設定しておくことで、グラフ保存時にグラフ外部分が見えなくなるのを防ぐ。
5plt.figure(figsize=(16, 9), facecolor="w")
6sns.barplot(data=data, x="name", y="金額(万円)", hue="category")
7title = "額面と手取と支出"
8plt.title(title)
9plt.legend(loc="upper left", bbox_to_anchor=(1,1))
10plt.show()
Aさん、Bさん、Cさん毎にまとまって棒グラフが表示される。