カテゴリー

当サイトはアフィリエイトプログラムによる収益を得ています〈景品表示法に基づく表記です)

plt

【plt&棒グラフ】pythonのmatplotlibで棒グラフを作成してみる

2021年7月23日

こんな人にオススメ

matplotlib.pyplotpltで棒グラフを書くにはどうしたらいいんだ?

あと、どんな感じのグラフができるんだ?

ということで、今回はmatplotli.pyplotpltで棒グラフを作成する。これまで多く取り上げてきたのは折れ線グラフとか散布図とか言われるようなグラフ。

作り方についてはそこまで複雑さはないけど、やはり線と面では使えるオプションが異なる、棒グラフが使えるようになれば降水量とかのグラフを表示できるようになる(多分)。

python環境は以下。

  • Python 3.9.4
  • numpy 1.20.3
  • matplotlib 3.4.2
  • pandas 1.2.4

運営者のメガネです。YouTubeTwitterInstagramも運営中。自己紹介お問い合わせページあります。

運営者メガネ

下準備

import re
import sys
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.cm as cm
import pandas as pd

sys.path.append('../../')
import plt_layout_template as template

x = np.arange(5)
print(x)
# [0 1 2 3 4]

# 今回使用する棒グラフのyの値
height1 = np.array([3, 1.5, 5, 1.2, 2.4])
height2 = np.array([2.4, 2.1, 4.2, 0.8, 4.1])
height3 = np.array([3.2, 4.8, 1.0, 0.2, 4.4])
height4 = np.array([1.0, 1.4, 2.6, 4.9, 4.8])

まずは本記事で作成するグラフの下準備としてのimport関連とデータ定義。今回は横軸には5データを使用し、縦軸のデータは合計で4種類使用することにした。縦軸のデータheight1からheight4の値は以下。

print(height1)
# [3.  1.5 5.  1.2 2.4]
print(height2)
# [2.4 1.  4.2 0.8 1.1]
print(height3)
# [3.2 4.8 1.  0.2 4.4]
print(height4)
# [1.  1.4 2.6 4.9 4.8]

plt_layout_templateはこのコードのあるディレクトリから上に2ついったところに置いてあるので、sys.path.append('../../')で2つ戻っている。plt_layout_templateについては以下参照。

plt.rcParamsでデフォルトを変更した後のグラフ
【pltテンプレート】matplotlib.pyplotのグラフ作成テンプレート

続きを見る

シンプルな棒グラフの作成

まずはシンプルな棒グラフ。棒グラフはax.barで作成可能で、引数のxが横軸の配列、heightが縦軸の値を示す。必要ではないが、一応グリッドも表示している。コードは以下。

def bar_simple():
    fig, ax = plt.subplots(1, 1)
    ax.set_title('title')
    ax.set_xlabel('x')
    ax.set_ylabel('y')
    ax.bar(x=x, height=height1, label='height1',)
    ax.legend()

    ax.grid(which='major', ls='-')
    ax.grid(which='minor', ls='--', alpha=0.5)

    fig.savefig('bar_simple.png')

bar_simple()

オプションの設定

ax.barには数多くの引数が存在している。ここではその中から使いやすいものをピックアップして紹介する。

横軸ラベルを変更

横軸目盛に表示する値は変更することができる。変更はax.barの匹数tick_labelで可能で、Noneを指定すると目盛が消えるようだ。

# 横軸ラベルの変更
def bar_tick_label(tick_label: tuple):

    fig, ax = plt.subplots(1, 1)
    ax.set_title('title')
    ax.set_xlabel('x')
    ax.set_ylabel('y')
    ax.bar(
        x=x, height=height1, label='height1',
        tick_label=tick_label,  # 横軸ラベル
    )
    ax.legend()

    ax.grid(which='major', ls='-')
    ax.grid(which='minor', ls='--', alpha=0.5)

    fig.savefig('bar_tick_label.png')

bar_tick_label(
    tick_label=['A', 'bb', None, 1 == 2, 10]
)

棒グラフに枠線を追加

棒グラフの枠線の色と太さは変更可能で、引数はそれぞれedgecolor, linewidth。上の画像では枠線の色を'deeppink'、枠線の太さを3とした。

# 棒グラフの枠線の色と太さ
def bar_baredge(edgecolor: str, linewidth: int or float or tuple, name: str):

    fig, ax = plt.subplots(1, 1)
    ax.set_title('title')
    ax.set_xlabel('x')
    ax.set_ylabel('y')
    ax.bar(
        x=x, height=height1, label='height1',
        edgecolor=edgecolor,  # 棒グラフの枠線の色
        linewidth=linewidth,  # 棒グラフの枠線の太さ
    )
    ax.legend()

    ax.grid(which='major', ls='-')
    ax.grid(which='minor', ls='--', alpha=0.5)

    fig.savefig(f"bar_baredge_{name}.png")

# 棒グラフの枠線の太さを一括変更
bar_baredge(
    edgecolor='deeppink',
    linewidth=3,
    name=3,
)

また、色も太さも配列で指定することができる。以下の例では色はviolet系の色、太さは適当に選んだ配列を使って指定した。

# # 枠線の色と太さを別々に指定
color = (
    'violet', 'darkviolet', 'palevioletred',
    'mediumvioletred', 'blueviolet',
)
bar_baredge(
    edgecolor=color,
    linewidth=(10, 8, 5, 3, 1),
    name='each',
)

棒グラフ間隔の変更

棒グラフ自体の太さも変更可能で、デフォルトでは0.8の太さのようだ。棒グラフ同士をくっつけるには、横軸の間隔と同じ値を引数widthで指定すればいい。ここでは横軸の間隔が1なので、width=1とするとくっつく。

# 棒グラフ自体の太さ
def bar_width(width: int or float or tuple, name: str):

    fig, ax = plt.subplots(1, 1)
    ax.set_title('title')
    ax.set_xlabel('x')
    ax.set_ylabel('y')
    ax.bar(
        x=x, height=height1, label='height1',
        width=width,  # 棒グラフの太さ(xの間隔が1なので棒グラフはくっつく)
    )
    ax.legend()

    ax.grid(which='major', ls='-')
    ax.grid(which='minor', ls='--', alpha=0.5)

    fig.savefig(f"bar_width_{name}.png")

# 全棒グラフの太さを一括変更
bar_width(
    width=1,
    name=1,
)

また、棒グラフの太さも配列を指定することでバラバラにすることができる。

# tupleでそれぞれの棒グラフの太さを変更
bar_width(
    width=(1, 0.1, 1.5, 0.3, 0.8),
    name='each',
)

棒グラフの色を変更

先ほどは枠線自体の色を変更したが、もちろん棒グラフ自体の色も変更可能。線グラフだと線の色しか変更できないが、棒グラフだと面なので、線の情報に加えて面の情報もいじることができる。

色を一括変更

棒グラフの色を変更するには引数としてcolorを使用すればいい。上の例では'violet'に設定している。

# 棒グラフの色(全棒グラフの色を変更)
def bar_color(color: 'str'):

    fig, ax = plt.subplots(1, 1)
    ax.set_title('title')
    ax.set_xlabel('x')
    ax.set_ylabel('y')
    ax.bar(
        x=x, height=height1, label='height1',
        color=color,  # 棒グラフ色
    )
    ax.legend()

    ax.grid(which='major', ls='-')
    ax.grid(which='minor', ls='--', alpha=0.5)

    fig.savefig('bar_color.png')

bar_color(
    color='violet',
)

色を個別変更

もちろん色も個別で設定可能。設定は案の定、配列。今回は'violet'系で攻めようと思う。ただし、凡例に適用される色は初めの棒グラフの色のようだ。

# 棒グラフの色(それぞれの棒グラフの色を個別に変更)
def bar_color_each(color: tuple, name: str):

    fig, ax = plt.subplots(1, 1)
    ax.set_title('title')
    ax.set_xlabel('x')
    ax.set_ylabel('y')
    ax.bar(
        x=x, height=height1, label='height1',
        color=color,  # 棒グラフ色
    )
    ax.legend()  # 凡例は初めの棒グラフの色が反映

    ax.grid(which='major', ls='-')
    ax.grid(which='minor', ls='--', alpha=0.5)

    fig.savefig(f"bar_color_each_{name}.png")

color = (
    'violet', 'darkviolet', 'palevioletred',
    'mediumvioletred', 'blueviolet',
)
bar_color_each(
    color=color,
    name='violet',
)

また、カラーマップからも作成することが可能。この時はカラーマップの配列を予め作成しないといけない。

# 連続色で色を作成
color = []
for num in range(len(x)):
    cmap = cm.jet(num / len(x))
    color.append(cmap)
print(color)
# [(0.0, 0.0, 0.5, 1.0), (0.0, 0.3, 1.0, 1.0), (0.16129032258064513, 1.0, 0.8064516129032259, 1.0), (0.8064516129032256, 1.0, 0.16129032258064513, 1.0), (1.0, 0.40740740740740755, 0.0, 1.0)]
bar_color_each(
    color=color,
    name='jet',
)

色を一部変更

さっきの棒グラフの色変えだと、大量の棒グラフの中の一部の色だけを変更したいときも大変。イメージは以下。

color = [
    'violet', 'violet', 'violet', 'violet', 'violet', 'violet', 'violet',
    'violet', 'violet', 'violet', 'violet', 'violet', 'violet', 'blueviolet',
    'violet', 'violet', 'blueviolet', 'violet', 'violet', 'violet', 'violet',
]

もちろん予めlistにデフォルトの色の配列を作って、それから変更するのもいいだろう。

color = ['violet'] * 21
color[-5] = 'blueviolet'
color[13] = 'blueviolet'

しかし、デフォルトの棒グラフの色を使用しつつ一部の色だけを変更したい。デフォルトの色も調べたら出てくるけど面倒。そんな時は色をセットすればいい。

ax.barを変数に代入し、その変数の指定のインデックスの色を.set_colorで変更することで、デフォルトの色を保ったまま一部の色を変更することができる。

# 棒グラフの色(それぞれの棒グラフの色を個別に変更)
def bar_color_index(**kwargs):

    fig, ax = plt.subplots(1, 1)
    ax.set_title('title')
    ax.set_xlabel('x')
    ax.set_ylabel('y')
    bar_lst = ax.bar(x=x, height=height1, label='height1',)
    for index, color in kwargs.items():
        bar_lst[int(index)].set_color(color)
    ax.legend()

    ax.grid(which='major', ls='-')
    ax.grid(which='minor', ls='--', alpha=0.5)

    fig.savefig('bar_color_index.png')

# kwargsのkeysは文字じゃないといけない かつ 直接入れられないので一旦dictにする
kwargs = {'1': 'blueviolet', '3': 'palevioletred', }
bar_color_index(
    **kwargs
)

なお、ここでは一括管理ということでkwargs引数で対応したが、もちろん引数を2つに増やすなど他の方法も可能。kwargs引数にすることで、好きな数だけ指定することができる。

ここまでの設定オプション全部載せ棒グラフ

ここまでのグラフのオプションを全部盛り込んだグラフが上のグラフ。横軸は棒グラフのそれぞれの色を示しつつ、棒グラフ同士が離れないようにwidth1とした。さらに境界線として黒色を選択。

# 上記オプション全部載せ
def bar_option(color: tuple, edgecolor: str,
               linewidth: int or float, width: int or float):

    fig, ax = plt.subplots(1, 1)
    ax.set_title('title')
    ax.set_xlabel('x')
    ax.set_ylabel('y')
    ax.bar(
        x=x, height=height1, label='height1',
        tick_label=color,
        edgecolor=edgecolor,
        linewidth=linewidth,
        width=width,
        color=color,
    )
    ax.legend()

    ax.grid(which='major', ls='-')
    ax.grid(which='minor', ls='--', alpha=0.5)

    fig.savefig('bar_option.png')

color = (
    'violet', 'darkviolet', 'palevioletred',
    'mediumvioletred', 'blueviolet',
)
bar_option(
    color=color,
    edgecolor='black',
    linewidth=2,
    width=1,
)

棒グラフの上に値を表示

棒グラフの上にテキストを入れるには複数種類の方法がある。簡単なものから難しいものまである。

ax.textで表示

棒グラフとは別に、特立したテキストとして値を表示するにはax.textを使用すればいい。しかし、ax.textでは配列で渡せないので、forループで1つずつテキストの表示をする。

# ax.textとサクッと値を表示
def bar_text():
    fig, ax = plt.subplots(1, 1)
    ax.set_title('title')
    ax.set_xlabel('x')
    ax.set_ylabel('y')
    ax.bar(x=x, height=height1, label='height1',)

    for xval, yval in zip(x, height1):
        ax.text(xval, yval, yval, ha='center', va='bottom')

    ax.legend()

    ax.grid(which='major', ls='-')
    ax.grid(which='minor', ls='--', alpha=0.5)

    fig.savefig('bar_text.png')

bar_text()

ax.annotateで表示(面倒)

ax.barの値の表示で調べると結構な確率でこのax.annotateの記事が見つかる。出典元はReferenceなんだけど、このサイトだとmatplotlibのバージョンが古いらしく

「You are reading an old version of the documentation (v3.1.1). For the latest version see https://matplotlib.org/stable/gallery/lines_bars_and_markers/barchart.html

と言われる。まあできるからやってみる。

# referenceにある書き方(古め)
# <https://matplotlib.org/3.1.1/gallery/lines_bars_and_markers/barchart.html>
def bar_autolabel():
    fig, ax = plt.subplots(1, 1)
    ax.set_title('title')
    ax.set_xlabel('x')
    ax.set_ylabel('y')
    rects1 = ax.bar(x=x, height=height1, label='height1',)

    for rect in rects1:
        # 置きたいテキスト=棒グラフの高さ
        hght = rect.get_height()
        print(hght)
        # 1本目の棒グラフ: 3.0

        # テキストを置く座標位置
        xy = (rect.get_x() + rect.get_width() / 2, hght)
        print(xy)
        # 1本目の棒グラフ: (0.0, 3.0)

        ax.annotate(
            hght,
            xy=xy,  # 矢印の終端
            xytext=(0, 3),  # ラベルの位置((0, 3)にする意味がよくわからん)
            textcoords="offset points",  # xytextはこれに依存するらしい
            ha='center', va='bottom',
        )

    ax.legend()

    ax.grid(which='major', ls='-')
    ax.grid(which='minor', ls='--', alpha=0.5)

    fig.savefig('bar_autolabel.png')

bar_autolabel()

ax.annotateは矢印を作成するための関数だったが、矢印のやじりを消すことができたりテキストを入れることができるので、ここで流用されている。

ax.bar_labelで表示(楽ちん)

じゃあax.textで独立して作成するしかないのかというとそういうわけでもない。実はax.bar_labelというコードも存在しており、ここにax.barの情報を入れることで自動的に値を表示してくれる。

しかも、ax.textでは位置を自分でわざわざ決めないといけなかったが、ax.bar_labelだと自動で中心にも上部にも配置することができる。場所が決まっているなら楽ちんだ。

# ax.textとサクッと値を表示(新しめ)
# <https://matplotlib.org/stable/gallery/lines_bars_and_markers/barchart.html?highlight=grouped%20bar%20chart%20labels>
def bar_barkabel(label_type='edge'):
    fig, ax = plt.subplots(1, 1)
    ax.set_title('title')
    ax.set_xlabel('x')
    ax.set_ylabel('y')
    rects1 = ax.bar(x=x, height=height1, label='height1',)

    # 棒グラフに値を書き込む
    ax.bar_label(rects1, label_type=label_type)

    ax.legend()

    ax.grid(which='major', ls='-')
    ax.grid(which='minor', ls='--', alpha=0.5)

    fig.savefig(f"bar_barkabel_{label_type}.png")

# 棒グラフの上に値を書き込む
bar_barkabel(
    label_type='edge'
)

値を棒グラフの中心に持ってきたい場合はlabel_type='center'とすればいい。超簡単。

2つ以上の棒グラフを並べる

棒グラフも折れ線グラフや散布図と同じように複数データを並べることがあるだろう。ここではそのように複数グラフを表示する方法を解説する。

シンプルに2本の棒グラフを並べる

ax.plotのように普通に並べてax.barを書いてしまうとグラフ同士が重なってしまう。なので、複数本のグラフを描くときには位置をずらす必要がある。

# シンプルに2本並べる = 棒グラフが重なる
def bar_2bar_simple():
    fig, ax = plt.subplots(1, 1)
    ax.set_title('title')
    ax.set_xlabel('x')
    ax.set_ylabel('y')
    ax.bar(x=x, height=height1, label='height1',)
    ax.bar(x=x, height=height2, label='height2', alpha=0.5)  # 透明度を0.5に
    ax.legend()

    ax.grid(which='major', ls='-')
    ax.grid(which='minor', ls='--', alpha=0.5)

    fig.savefig('bar_2bar_simple.png')

bar_2bar_simple()

位置を調節して棒グラフを並べる

それぞれの棒グラフの位置を調節する。両者の棒グラフの合計太さが太すぎると他の棒グラフと干渉するので、今回はwidthで指定した棒の太さを最大値として、太さを分割することにする。

1つのxに対する棒グラフ全体の太さをwidthとすると、個々の棒グラフの太さはwidth / 2(今は2データ)。個々の棒グラフの中心が棒グラフの位置する座標値なのでさらに/ 2してあげる。この値をxから引くと左側に、足すと右側に棒グラフが作成される。

# 2本の棒グラフを並べる
def bar_2bar_width(width=0.8):

    bar_wid = width / 2  # それぞれの棒グラフの太さ
    bar_center = bar_wid / 2  # 棒グラフの開始位置のズレ幅

    new_x = x - bar_center  # ズレ幅を考慮したx
    new_x2 = x + bar_center  # ズレ幅を考慮したx2

    fig, ax = plt.subplots(1, 1)
    ax.set_title('title')
    ax.set_xlabel('x')
    ax.set_ylabel('y')
    ax.bar(x=new_x, height=height1, label='height1', width=bar_wid)
    ax.bar(x=new_x2, height=height2, label='height2', width=bar_wid, alpha=0.5)
    ax.legend()

    ax.grid(which='major', ls='-')
    ax.grid(which='minor', ls='--', alpha=0.5)

    fig.savefig('bar_2bar_width.png')

bar_2bar_width(
    width=0.8  # 2本棒グラフのトータル太さ
)

棒グラフ群の太さは1でもいいが1だとくっついてわかりにくいので0.8とした。

複数本の棒グラフを自動調節して並べる

しかし、いつでもデータ数が2つとは限らない。3つかもしれないし4つかもしれない。はたまた1つかもしれない。状況が変わるたびにコードを変更するのは面倒なので自動的に調節するようにした。

よくわからんが上手いこといったのでそのまま示す。

def bar_nbar_width(width=0.8, **kwargs):

    fig, ax = plt.subplots(1, 1)
    ax.set_title('title')
    ax.set_xlabel('x')
    ax.set_ylabel('y')

    for num, (name, hght) in enumerate(kwargs.items()):
        wid_each = width / len(kwargs)  # 棒グラフ1本の太さ
        # よくわからんけど以下の処理で複数本棒グラフの位置決めがうまくいく
        odd_x = (2 * num + 1) / len(kwargs)  # 奇数番目の棒グラフの右端の位置
        shift_x = (odd_x - 1) / 2  # 棒グラフ群中心から測った各棒グラフの中心位置
        adjust = width * shift_x  # 棒グラフ群全体の幅で調節
        new_x = x + adjust  # 調節後のx

        bar = ax.bar(x=new_x, height=hght, label=name, width=wid_each)
        ax.bar_label(bar)
    ax.legend()

    ax.grid(which='major', ls='-')
    ax.grid(which='minor', ls='--', alpha=0.5)

    # どのheightを使用したのかがわかるように文字列を作成
    lst = []
    for key in kwargs:
        pick = re.findall(r'\\d', key)  # 数字部分だけ抽出
        lst.append(*pick)  # listで出力されるので展開して格納
    name = ''.join(lst)  # list内の要素を結合
    fig.savefig(f"bar_nbar_width_{name}.png")

# kwargsの本数を変更しても自動的に調節される
kwargs = {
    'height1': height1,
    'height2': height2,
    'height3': height3,
    'height4': height4,
}
bar_nbar_width(
    **kwargs,
    width=0.8  # 2本棒グラフのトータル太さ
)

グラフを保存する際にはre.findallで数字部分のみを抽出し、文字列として結合してファイル名に組み込んだ。また、プロットする順番を入れ替えたりデータ数を変えたりしてもうまくいく。

色は特に設定していないのでズレているが、ちゃんとheight1が各xの値の中心に位置している。すごい。色は指定したかったら指定すればいい。

# kwargsの本数を変更しても自動的に調節される
kwargs = {
    'height4': height4,
    'height1': height1,
    'height2': height2,
}
bar_nbar_width(
    **kwargs,
    width=0.8  # 2本棒グラフのトータル太さ
)

積み上げ式の棒グラフ

上で横に棒グラフを並べる方法について解説した。しかし、xの数、heightの数が増えたりするとギチギチになってしまう。また、どれくらいの割合を占めるのかというようなこともわかりにくかったりするl。

そんな時は積み上げ式の棒グラフを使うと便利。上の画像では100%で描いているが、もちろん%表示じゃなくてもいい。

シンプル積み上げ

積み上げるには引数bottomを設定すればいい。bottomでは描こうとしているプロットの下にどのプロットがあるのかを指定する。したがって、積み上げが増えると面倒になる。forか何かで簡略化が必要。今は平文で書く。

また、ax.bar_labellabel_type='edge'とすることでそのプロットまでの合計値を棒グラフの上に出してくれる。以下ではheight3'edge'を設定しているので最終的な合計値が表示されている。

# simpleに積み上げ
def bar_stack():
    fig, ax = plt.subplots(1, 1)
    ax.set_title('title')
    ax.set_xlabel('x')
    ax.set_ylabel('y')

    bottom12 = height1  # height2を描くときに下になるデータ
    bottom123 = height1 + height2  # height3を描くときに下になるデータ

    bar1 = ax.bar(x=x, height=height1, label='height1')
    bar2 = ax.bar(x=x, height=height2, label='height2', bottom=bottom12)
    bar3 = ax.bar(x=x, height=height3, label='height3', bottom=bottom123)

    ax.bar_label(bar1, label_type='center')  # height1の値
    ax.bar_label(bar2, label_type='center')  # height2の値
    ax.bar_label(bar3, label_type='center')  # height3の値
    ax.bar_label(bar3, label_type='edge')  # 積み上げの合計値表示
    ax.legend()

    ax.grid(which='major', ls='-')
    ax.grid(which='minor', ls='--', alpha=0.5)

    fig.savefig('bar_stack.png')

bar_stack()

100%積み上げ

上での積み上げは値を足していった場合だったが、各値が全体の何%を占めているのかで表示することもあるだろう。しかし、pltだけではこれはできないようなので、わざわざ計算することにする。仕方ない。

まずは一旦、height達を2次元配列に格納する。

# height配列を1つの2次元配列に
height_all = np.array([height1, height2, height3, height4])
print(height_all)
# [[3.  1.5 5.  1.2 2.4]
#  [2.4 2.1 4.2 0.8 4.1]
#  [3.2 4.8 1.  0.2 4.4]
#  [1.  1.4 2.6 4.9 4.8]]

その後、列方向に合計し、各値をこの合計値で割って100をかけることで割合を計算することができる。

# 各xに対して合計
height_sum = np.sum(height_all, axis=0)
print(height_sum)
# [ 9.6  9.8 12.8  7.1 15.7]

# heightの割合を計算
height_ratio = 100 * (height_all / height_sum)
print(height_ratio)
# [[31.25       15.30612245 39.0625     16.90140845 15.2866242 ]
#  [25.         21.42857143 32.8125     11.26760563 26.11464968]
#  [33.33333333 48.97959184  7.8125      2.81690141 28.02547771]
#  [10.41666667 14.28571429 20.3125     69.01408451 30.57324841]]

あとは作成した2次元配列を各データとして割り振る。

# データの割り振り
height1_per, height2_per, height3_per, height4_per = height_ratio
print(height1_per)
# [31.25       15.30612245 39.0625     16.90140845 15.2866242 ]
print(height2_per)
# [25.         21.42857143 32.8125     11.26760563 26.11464968]
print(height3_per)
# [33.33333333 48.97959184  7.8125      2.81690141 28.02547771]
print(height4_per)
# [10.41666667 14.28571429 20.3125     69.01408451 30.57324841]

データができたら先ほど同様、積み上げ式の棒グラフを作成する。

# 100%積み上げ
def bar_stack_100():
    fig, ax = plt.subplots(1, 1)
    plt.subplots_adjust(right=0.85)
    ax.set_title('title')
    ax.set_xlabel('x')
    ax.set_ylabel('y [%]')

    bottom12 = height1_per
    bottom123 = bottom12 + height2_per
    bottom1234 = bottom123 + height3_per

    bar1 = ax.bar(x=x, height=height1_per, label='height1')
    bar2 = ax.bar(x=x, height=height2_per, label='height2', bottom=bottom12)
    bar3 = ax.bar(x=x, height=height3_per, label='height3', bottom=bottom123)
    bar4 = ax.bar(x=x, height=height4_per, label='height4', bottom=bottom1234)

    ax.bar_label(bar1, label_type='center')
    ax.bar_label(bar2, label_type='center')
    ax.bar_label(bar3, label_type='center')
    ax.bar_label(bar4, label_type='center')
    ax.bar_label(bar4, label_type='edge')
    ax.legend(bbox_to_anchor=(1.0, 1.0))

    ax.grid(which='major', ls='-')
    ax.grid(which='minor', ls='--', alpha=0.5)

    fig.savefig('bar_stack_100.png')

bar_stack_100()

横棒グラフ

いつだって縦に棒グラフを書くわけではない。横に描きたいこともあるだろう。基本的にはコードは同じだが、縦か横かの違いでコードが異なる。

シンプルな横棒グラフ

縦の棒グラフはax.barだったが横の場合はax.barhとなる。多分horizontalのhだろう。グラフが横向きになったので、グラフが横に伸びるとyの値が大きいということになる。

ということで、今まで棒グラフの太さを示していたwidthheightの代わりになる。また、xではなくyが横軸のパラメータとなる。ややこしい。

# シンプルな横棒グラフ
def barh_simple():
    fig, ax = plt.subplots(1, 1)
    ax.set_title('title')
    ax.set_xlabel('y')
    ax.set_ylabel('x')
    # 引数が変わる
    ax.barh(y=x, width=height1, label='height1',)
    ax.legend()

    ax.grid(which='major', ls='-')
    ax.grid(which='minor', ls='--', alpha=0.5)

    fig.savefig('barh_simple.png')

barh_simple()

オプション適用済みの横棒グラフ

オプションの適用もの縦の時と同じように行うことができるが、heightwidthの代わりになることに注意。

# オプション適用済み
def barh_option(color: tuple, edgecolor: str,
                linewidth: int or float, height: int or float):
    fig, ax = plt.subplots(1, 1)
    ax.set_title('title')
    ax.set_xlabel('y')
    ax.set_ylabel('x')
    # 引数が変わる
    ax.barh(
        y=x, width=height1,
        color=color,
        edgecolor=edgecolor,
        linewidth=linewidth,
        height=height,
        label='height1',
    )
    ax.legend()

    ax.grid(which='major', ls='-')
    ax.grid(which='minor', ls='--', alpha=0.5)

    fig.savefig('barh_option.png')

color = (
    'violet', 'darkviolet', 'palevioletred',
    'mediumvioletred', 'blueviolet',
)
barh_option(
    color=color,
    edgecolor='black',
    linewidth=2,
    height=1,
)

線グラフとの組み合わせで真価が発揮?

今回はpltで棒グラフを作成する方法について解説した。今回は棒グラフしか使用していなかったが、使用用途としては気温と降水量など2種類のデータを使用する際に使われるだろう。

そんな中でさらによく使われるのが、棒グラフと線グラフの2軸グラフだ。この2軸グラフができるようになればもっと表現の手法が広がり、相手に伝わりやすくなるだろう。

関連記事

【plt&マーカー一覧】matplotlibのマーカーをグラフ化

続きを見る

【plt&subplot】pythonのpltで複数グラフを1つの画像に描く

続きを見る

【plt&mpld3】pltで作ったグラフを後から編集できるようにhtmlで保存

続きを見る

(9 < x y2)の条件に合った塗りつぶし
【plt&fill_between】matplotlibで領域を塗りつぶし

続きを見る

ガジェット

2023/9/18

【デスクツアー2022下半期】モノは少なく、でも効率的に Desk Updating #0

今回はガジェットブロガーなのにデスク環境を構築していない執筆者の ...

ライフハック

2023/9/16

【Audible vs YouTube Premium】耳で聴く音声学習コンテンツを比較

ワイヤレスイヤホンが普及し耳で学習することへのハードルが格段に下 ...

完全ワイヤレスイヤホン(TWS)

2023/9/18

【SENNHEISER MOMENTUM True Wireless 3レビュー】全てが整ったイヤホン

今回は高音質・高機能なSENNHEISERのフラグシップ完全ワイヤレスイヤホン「SENNH ...

ライフハック

2023/3/11

【YouTube Premiumとは】メリットしかないから全員入れ

今回はYouTube Premiumを実際に使ってみてどうなのか、どんなメリット/デメリット ...

マウス

2023/8/17

【Logicool MX ERGOレビュー】疲れない作業効率重視トラックボールマウス

こんな人におすすめ トラックボールマウスの王道Logicool MX ERGOが気になるけどऩ ...

ベストバイ

2023/9/18

【ベストバイ2022】今年買って良かったモノのトップ10

2022年ベストバイ この1年を振り返って執筆者は何を買ったのか。ガジェッ& ...

スマホ

2023/1/15

【楽天モバイル×povo2.0の併用】月1,000円の保険付きデュアルSIM運用

こんな人におすすめ 楽天モバイルとpovo2.0のデュアルSIM運用って実際のとこ ...

マウス

2023/9/16

【Logicool MX ERGO vs MX Master 3】ERGOをメインにした決定的な理由

こんな疑問・お悩みを持っている人におすすめ 執筆者はLogicoolのハイエンӠ ...

macOSアプリケーション

2022/9/30

【Chrome拡張機能】便利で効率的に作業できるおすすめの拡張機能を18個紹介する

こんな人におすすめ Chromeの拡張機能を入れたいけど、調べても同じような ...

macOSアプリケーション

2023/5/3

【Automator活用術】Macで生産性を上げる作業の自動化術

今回はMacに標準でインストールされているアプリ「Automator」を使ってできる ...

Pythonを学びたいけど独学できる時間なんてない人へのすゝめ

執筆者は大学の研究室・大学院にて独学でPythonを習得した。

でも社会人になったら独学で行うには時間も体力もなくて大変だ。

時間がない社会人だからこそプロの教えを乞うのが効率的。

ここでは色んなタイプに合ったプログラミングスクールの紹介をする。

  • この記事を書いた人

メガネ

Webエンジニア駆け出し。独学のPythonで天文学系の大学院を修了。常時金欠のガジェット好きでM2 Pro MacBook Pro(30万円) x Galaxy S22 Ultra(17万円)使いの狂人。自己紹介と半生→変わって楽しいの繰り返しレビュー依頼など→お問い合わせ運営者情報、TwitterX@m_ten_pa、 YouTube@megatenpa、 Threads@megatenpa

-plt
-, , ,