HOWTO · Seaborn

Seaborn 円グラフの作成方法

Matplotlib の plt.pie と Seaborn のカラーパレットで円グラフを作成し、ラベル、パーセンテージ、間隔、スタイルを追加します。

このページの内容

Python で円グラフを作成するには、Matplotlib の plt.pie で描画し、スライスの色を Seaborn の sns.color_palette で選びます。Seaborn には円グラフ専用の関数は用意されておらず、このワークフローでは 2 つのライブラリの役割は分かれています。Seaborn が色を提供し、Matplotlib がグラフを描画します。両方のライブラリがインストールされている必要があります(pip install matplotlib seaborn)。以下の例では、少数のカテゴリに数値を使い、各スライスにラベルを付けて全体に占める割合を表示します。2 つ目の例ではグラフを凡例付きのドーナツグラフに変形し、最後の例ではラベルと値の数が一致しない場合に Matplotlib が発生させるエラーを示します。

Seaborn で円グラフを作成する

import matplotlib.pyplot as plt
import seaborn as sns

values = [35, 21, 29, 39, 11]
labels = ["A", "B", "C", "D", "E"]
colors = sns.color_palette("pastel", n_colors=len(values))
explode = [0.08, 0, 0, 0, 0]

plt.pie(
    values,
    labels=labels,
    colors=colors,
    autopct="%1.1f%%",
    explode=explode,
    startangle=90,
    counterclock=False,
    textprops={"fontsize": 10},
    wedgeprops={"linewidth": 1, "edgecolor": "white"},
)
plt.show()

AからEのラベルが付いた5つのスライスを持つ円グラフ。各スライスにパーセンテージが表示され、スライスAは中心から外側にずれている。

このコードは上記のグラフを生成します。5 つの値の合計は 135 になるため、スライスに表示されるパーセンテージは A が 25.9%、B が 15.6%、C が 21.5%、D が 28.9%、E が 8.1% です。スライス A は explode のオフセットにより、他のスライスから少し離れています。

値とラベルは位置で対応させます。最初のラベルが最初の値を、2 番目のラベルが 2 番目の値を表し、以下同様です。カテゴリ別の件数のように、1 つの全体の一部を表す数値のリストを使います。パーセンテージはそれらの数量から計算されるため、別途与えられたパーセンテージではなく、各カテゴリの割合を表します。カテゴリ名が長い場合は、短いラベルにするか、テキストにより多くのスペースを割けるグラフの種類を選びます。

values として渡されたリストが、各スライスの相対的な大きさを決めます。plt.pie がグラフを描画し、sns.color_palette がスライスの色を返します。パレット名は文字列です。"pastel" を "deep"、"muted"、"colorblind"、"bright"、"dark" など、別の Seaborn パレットに変更します。n_colors をデータの長さから設定すると、値ごとに 1 色が要求されます。

labels リストは、値と同じ順序でカテゴリ名を提供します。autopct 形式は、すべての値の合計に対する各値のパーセンテージを表示します。たとえば、"%1.1f%%" はパーセンテージを小数第 1 位まで表示します。表示精度を変えるには、別の形式文字列を使います。ラベルはカテゴリを特定し、パーセンテージはその割合を比較しやすくします。

スライスを視覚的に分離するには、値ごとに 1 つの項目を持つシーケンスを explode に渡します。各項目が対応するスライスのオフセットを制御するため、最初の 0.08 はカテゴリ A を外側に移動させ、残りのゼロはスライスをその位置に留めます。これらの項目を調整して別のカテゴリを強調したり、全体にゼロを使ってオフセットのないグラフにしたりします。

円グラフをカスタマイズする

グラフの向きと外観は、plt.pie のさらなる引数で調整できます。startangle は開始位置を回転させ、counterclock=False はスライスが描かれる方向を設定します。影を追加するには shadow=True を、ラベルとパーセンテージのテキストプロパティを設定するには textprops を、スライスの境界をスタイルするには wedgeprops を使います。便利な wedgeprops の設定に width があります。これは各ウェッジを縁の方向へ縮小し、次の例のように円グラフをドーナツグラフに変えます。その他の引数には、軸の枠を追加する frame=True、円の中心を配置する center=(x, y)、ラベルをスライスに沿って回転させる rotatelabels=True があり、これらのブール値オプションは引用符なしで Python の値 True または False を取ります。

import matplotlib.pyplot as plt
import seaborn as sns

values = [58, 33, 6, 3]
labels = ["Desktop", "Mobile", "Tablet", "Other"]
colors = sns.color_palette("colorblind", n_colors=len(values))

wedges, texts = plt.pie(
    values,
    colors=colors,
    startangle=90,
    counterclock=False,
    wedgeprops={"width": 0.45, "linewidth": 1, "edgecolor": "white"},
)
plt.legend(wedges, labels, title="Device", loc="center left", bbox_to_anchor=(1, 0.5))
plt.title("Sessions by Device")
plt.show()

「Sessions by Device」というタイトルのドーナツグラフ。Desktop、Mobile、Tablet、Other の4つのリングセグメントを示す凡例付き。

ここでは wedgeprops={"width": 0.45, ...} により各ウェッジの外側 45% だけが残り、中心が空になります。今回はスライスにラベルが付いていないため、plt.pie はウェッジオブジェクトを返します。それらをラベルのリストとともに plt.legend に渡すと、グラフの横に凡例が作成されます。plt.title は見出しを追加します。カテゴリ名が長い場合や細いスライスが多い場合は、スライス上のラベルよりも凡例のほうが読みやすくなります。サンプルデータの合計は 100 なので、セグメントの大きさはそのままパーセンテージ(58%、33%、6%、3%)として読めます。

長さと値のエラーを避ける

スライスごとの各引数はデータと一致しなければなりません。labels、explode、色のリストはいずれも値 1 つにつきちょうど 1 つの項目が必要であり、スライスが全体の負の割合を占めることはできないため、すべての値は非負でなければなりません。長さが一致しない場合、plt.pie はグラフを描画せずに ValueError で停止します。

import matplotlib.pyplot as plt

values = [35, 21, 29]
labels = ["A", "B"]

plt.pie(values, labels=labels)
plt.show()

出力:

ValueError: 'labels' must be of length 'x', not 2

修正するには、labels に 3 つの値それぞれに対応する項目を与えます。同じ規則は explode にも当てはまります。3 つの値に対して 2 項目の explode リストを指定すると、ValueError: 'explode' must be of length 'x', not 2 が発生します。values の負の項目も同様に失敗し、ValueError: Wedge sizes 'x' must be non negative values となります。最後に、カテゴリの数は少なく抑えてください。細いスライスが多いとラベルが重なり、割合の比較が難しくなります。小さなカテゴリは「Other」スライスにまとめるか、棒グラフへの切り替えを検討してください。