matplotlib – 積み上げ棒グラフを作成する方法

目次

概要

matplotlib で積み上げ棒グラフを作成する方法について解説します。

積み上げ棒グラフ

項目ごとに棒グラフを積み上げて描画した棒グラフの一種です。

積み上げ棒グラフ

積み上げ縦棒グラフ

In [1]:
import numpy as np
import pandas as pd
from matplotlib import pyplot as plt


def get_data():
    data = np.array(
        [[156, 128, 285], [286, 220, 297], [218, 235, 137], [160, 298, 112]]
    )
    row_labels = ["2017", "2018", "2019", "2020"]
    col_labels = ["Android", "iOS", "Windows"]

    return pd.DataFrame(data, index=row_labels, columns=col_labels)


get_data()
Android iOS Windows
2017 156 128 285
2018 286 220 297
2019 218 235 137
2020 160 298 112
In [2]:
df = get_data()

n_rows, n_cols = df.shape
positions = np.arange(n_rows)
offsets = np.zeros(n_rows, dtype=df.values.dtype)
colors = plt.get_cmap("tab20c")(np.linspace(0, 1, n_cols))

fig, ax = plt.subplots()
ax.set_xticks(positions)
ax.set_xticklabels(row_labels)

for i in range(len(df.columns)):
    # 棒グラフを描画する。
    bar = ax.bar(positions, df.iloc[:, i], bottom=offsets, color=colors[i])
    offsets += df.iloc[:, i]

    # 棒グラフのラベルを描画する。
    for rect in bar:
        cx = rect.get_x() + rect.get_width() / 2
        cy = rect.get_y() + rect.get_height() / 2
        ax.text(cx, cy, df.columns[i], color="k", ha="center", va="center")

積み上げ縦棒グラフ (割合)

In [3]:
df = get_data()

# 正規化する
df = df.div(df.sum(axis=1), axis=0)

n_rows, n_cols = df.shape
positions = np.arange(n_rows)
offsets = np.zeros(n_rows, dtype=df.values.dtype)
colors = plt.get_cmap("tab20c")(np.linspace(0, 1, n_cols))

fig, ax = plt.subplots()
ax.set_xticks(positions)
ax.set_xticklabels(row_labels)

for i in range(len(df.columns)):
    # 棒グラフを描画する。
    bar = ax.bar(positions, df.iloc[:, i], bottom=offsets, color=colors[i])
    offsets += df.iloc[:, i]

    # 棒グラフのラベルを描画する。
    for rect in bar:
        cx = rect.get_x() + rect.get_width() / 2
        cy = rect.get_y() + rect.get_height() / 2
        ax.text(cx, cy, df.columns[i], color="k", ha="center", va="center")

積み上げ横棒グラフ

In [4]:
df = get_data()

n_rows, n_cols = df.shape
positions = np.arange(n_rows)
offsets = np.zeros(n_rows, dtype=df.values.dtype)
colors = plt.get_cmap("tab20c")(np.linspace(0, 1, n_cols))

fig, ax = plt.subplots()
ax.set_yticks(positions)
ax.set_yticklabels(df.index)

for i in range(len(df.columns)):
    # 棒グラフを描画する。
    bar = ax.barh(positions, df.iloc[:, i], left=offsets, color=colors[i])
    offsets += df.iloc[:, i]

    # 棒グラフのラベルを描画する。
    for rect in bar:
        cx = rect.get_x() + rect.get_width() / 2
        cy = rect.get_y() + rect.get_height() / 2
        ax.text(cx, cy, df.columns[i], color="k", ha="center", va="center")

積み上げ横棒グラフ (割合)

In [5]:
df = get_data()

# 正規化する
df = df.div(df.sum(axis=1), axis=0)

n_rows, n_cols = df.shape
positions = np.arange(n_rows)
offsets = np.zeros(n_rows, dtype=df.values.dtype)
colors = plt.get_cmap("tab20c")(np.linspace(0, 1, n_cols))

fig, ax = plt.subplots()
ax.set_yticks(positions)
ax.set_yticklabels(df.index)

for i in range(len(df.columns)):
    # 棒グラフを描画する。
    bar = ax.barh(positions, df.iloc[:, i], left=offsets, color=colors[i])
    offsets += df.iloc[:, i]

    # 棒グラフのラベルを描画する。
    for rect in bar:
        cx = rect.get_x() + rect.get_width() / 2
        cy = rect.get_y() + rect.get_height() / 2
        ax.text(cx, cy, df.columns[i], color="k", ha="center", va="center")

数値を表示する (値)

In [6]:
df = get_data()

n_rows, n_cols = df.shape
positions = np.arange(n_rows)
offsets = np.zeros(n_rows, dtype=df.values.dtype)
colors = plt.get_cmap("tab20c")(np.linspace(0, 1, n_cols))

fig, ax = plt.subplots()
ax.set_yticks(positions)
ax.set_yticklabels(df.index)

for i in range(len(df.columns)):
    # 棒グラフを描画する。
    bar = ax.barh(
        positions, df.iloc[:, i], left=offsets, color=colors[i], label=df.columns[i]
    )
    offsets += df.iloc[:, i]

    # 棒グラフのラベルを描画する。
    for rect, value in zip(bar, df.iloc[:, i]):
        cx = rect.get_x() + rect.get_width() / 2
        cy = rect.get_y() + rect.get_height() / 2
        ax.text(cx, cy, value, color="k", ha="center", va="center")

ax.legend(bbox_to_anchor=(1, 1))
<matplotlib.legend.Legend at 0x7f7c1b3c9070>

数値を表示する (パーセント)

In [7]:
df = get_data()

# 正規化する
df = df.div(df.sum(axis=1), axis=0)

n_rows, n_cols = df.shape
positions = np.arange(n_rows)
offsets = np.zeros(n_rows, dtype=df.values.dtype)
colors = plt.get_cmap("tab20c")(np.linspace(0, 1, n_cols))

fig, ax = plt.subplots()
ax.set_yticks(positions)
ax.set_yticklabels(df.index)

for i in range(len(df.columns)):
    # 棒グラフを描画する。
    bar = ax.barh(
        positions, df.iloc[:, i], left=offsets, color=colors[i], label=df.columns[i]
    )
    offsets += df.iloc[:, i]

    # 棒グラフのラベルを描画する。
    for rect, value in zip(bar, df.iloc[:, i]):
        cx = rect.get_x() + rect.get_width() / 2
        cy = rect.get_y() + rect.get_height() / 2
        ax.text(cx, cy, f"{value:.0%}", color="k", ha="center", va="center")

ax.legend(bbox_to_anchor=(1, 1))
<matplotlib.legend.Legend at 0x7f7c238cdf70>

コメント

コメントする

目次