Wizard Notes

Python, JavaScript を使った音楽信号分析の技術録、作曲活動に関する雑記

matplotlib: 棒グラフの色を階級ごとに度数に応じてグラデーション

やりたいこと

シンプルで綺麗なグラフは、得なことが多いです。

見た人の思考や感性に訴えかけ、新たな発見や次のステップへの道筋を示してくれます。または、相手によってはグラフ自体に価値がある場面もあります。

しかし、そんなグラフを人手で作りこむのは工数がかかってしまいます。そこで、なるべく自動で、綺麗なグラフを作ることは、ビジネスのあらゆるシーンで需要があります。

この記事では、matplotlib.pyploy.bar()棒グラフの色を階級ごとに度数に応じてグラデーションで描画する方法を紹介します。このような色の描画をすることで、棒グラフ(ヒストグラム)の内容が分かりやすくなります。特にヒストグラムでは、偏りがあるか(特定の分布か)どうかが分かりやすくなります。

実装と出力結果

matplotlib.pyploy.bar() は、引数colorに、各棒の(縦軸の)値が格納された配列 heightを同じサイズのリストを与えることで、棒ごとに色を設定できます。

また、matplotlib では 0 から1.0のスカラー値に応じて 決められた2色間の色に対応した配列を返す get_cmap という関数があります。従って各階級ごとに度数を加工し、get_cmapの引数とすることで、任意のカラーマップ上の色が階級ごとに決定できます。

matplotlib のカラーマップはこちらをご参考ください。

以下、実装例です。

def plot_bar(hist, colormap):
    hist_max = np.max(hist) 
    cmap = plt.get_cmap(colormap)
    colorlist = [cmap(value/hist_max * 0.5) for value in hist]
    plt.bar(np.arange(0, len(hist)), hist, color=colorlist, width=1.0)
   
plt.clf()
np.random.seed(1)
colormaps = ['Greys', 'Purples', 'Blues', 'Greens', 
             'Oranges', 'Reds','YlOrBr', 'YlOrRd', 
             'OrRd', 'PuRd', 'RdPu', 'BuPu',
             'GnBu', 'PuBu', 'YlGnBu', 'BuGn'
            ]
N = 4
NN = N*N
for n in range(0, NN):
    # Make data
    mean, std = np.random.normal(0.0, 1.0), np.random.random(3).sum()+0.1
    print(mean, std)
    data = np.random.normal(mean, std, 3000)
    hist, _ = np.histogram(data, bins=50, range=(-2., 2.))
    
    # Plot
    plt.subplot(N, N, n+1)
    plot_bar(hist, colormaps[n])
    plt.title(f"plot ({N}, {N}, {n+1})")
    
plt.tight_layout()
plt.show()

f:id:Kurene:20191021005412p:plain
図1: 度数に応じて色が変わる棒グラフ

補足

上記コード中の、データの標準偏差std を 算出する ```np.random.random(3).sum()は、乱数にコクをつけています