Matplotlib円グラフ:Pythonで円グラフを作成する完全ガイド
Updated on
効果的なデータ可視化は、洞察を明確に伝えるうえで不可欠です。全体に対する比率や割合を示したいとき、円グラフは可視化の武器として重要なツールになります。一方で、多くのデータアナリストが「重要なセグメントを適切に強調する」「適切な配色を選ぶ」「割合を正確に表示する」といった、プロらしい円グラフの作成に苦戦しがちです。matplotlibのデフォルトの円グラフは、見た目が素朴で文脈が不足し、重要なデータポイントを強調できないことがよくあります。
こうした可視化上の課題は、市場シェアの分布、予算配分、アンケート回答の内訳などを、短時間で理解する必要があるステークホルダーに提示する場面でさらに深刻になります。設計が不十分な円グラフは、理解を助けるどころか混乱を招き、重要なビジネスメトリクスの誤解釈につながりかねません。
matplotlibには、基本的な円形チャートをプロ品質の可視化に変換できる、豊富なカスタマイズオプションを備えた plt.pie() 関数が用意されています。このガイドでは、単純な比率の円グラフから複雑なネスト図までを扱い、ラベル、色、スライスの分離(explode)、ドーナツチャート、そして実務でよくあるpandas DataFrameとの連携まで、実用的な例で解説します。
基本的なMatplotlib円グラフの構文
matplotlibで円グラフを作る土台は plt.pie() で、各スライスの大きさを表す値のリスト(または配列)だけを必要とします。
import matplotlib.pyplot as plt
# Basic pie chart data
sizes = [35, 25, 20, 20]
labels = ['Product A', 'Product B', 'Product C', 'Product D']
# Create pie chart
plt.pie(sizes, labels=labels)
plt.title('Market Share Distribution')
plt.show()これは、sizes リストの値に比例してスライスの大きさが決まる基本的な円形チャートを作成します。matplotlibは各セグメントの割合と角度を自動的に計算します。色はデフォルトのカラ―サイクルから割り当てられますが、プレゼン用途では必ずしも適切とは限りません。
楕円ではなく正しい円形にするには plt.axis('equal') を追加します。
import matplotlib.pyplot as plt
sizes = [35, 25, 20, 20]
labels = ['Product A', 'Product B', 'Product C', 'Product D']
plt.pie(sizes, labels=labels)
plt.axis('equal') # Equal aspect ratio ensures circular shape
plt.title('Market Share Distribution')
plt.show()autopctで割合(パーセンテージ)を表示する
autopct パラメータを使うと、各スライスに割合を自動で整形して表示でき、手計算なしで情報量のあるチャートになります。
import matplotlib.pyplot as plt
sizes = [35, 25, 20, 20]
labels = ['Product A', 'Product B', 'Product C', 'Product D']
plt.pie(sizes, labels=labels, autopct='%1.1f%%')
plt.axis('equal')
plt.title('Market Share with Percentages')
plt.show()フォーマット文字列 '%1.1f%%' は小数第1位まで表示します。最初の % がフォーマット指定の開始、1.1f は小数点の前後それぞれ1桁、%% は出力にパーセント記号をリテラルとして出すための指定です。
小数なしの整数パーセントにしたい場合は '%1.0f%%' を使います。
plt.pie(sizes, labels=labels, autopct='%1.0f%%')さらに表示を細かく制御したい場合は、autopct にカスタム関数を渡すこともできます。
import matplotlib.pyplot as plt
sizes = [350, 250, 200, 200]
labels = ['Product A', 'Product B', 'Product C', 'Product D']
def make_autopct(values):
def my_autopct(pct):
total = sum(values)
val = int(round(pct * total / 100.0))
return f'{pct:.1f}%\n({val:d})'
return my_autopct
plt.pie(sizes, labels=labels, autopct=make_autopct(sizes))
plt.axis('equal')
plt.title('Market Share with Counts and Percentages')
plt.show()この例では、各スライスに「割合」と「実数(カウント)」の両方を表示します。
カスタムカラーとカラーマップ
colors パラメータに色指定のリストを渡すと、matplotlibのデフォルト配色を上書きできます。色は、名前付きカラー、16進カラーコード、RGBタプルなどで指定可能です。
import matplotlib.pyplot as plt
sizes = [35, 25, 20, 20]
labels = ['Product A', 'Product B', 'Product C', 'Product D']
colors = ['#ff9999', '#66b3ff', '#99ff99', '#ffcc99']
plt.pie(sizes, labels=labels, colors=colors, autopct='%1.1f%%')
plt.axis('equal')
plt.title('Market Share with Custom Colors')
plt.show()データに応じた色選択をしたい場合は、matplotlibのカラーマップ(colormap)を使えます。
import matplotlib.pyplot as plt
import numpy as np
sizes = [35, 25, 20, 20]
labels = ['Product A', 'Product B', 'Product C', 'Product D']
# Generate colors from a colormap
cmap = plt.cm.Set3
colors = cmap(np.linspace(0, 1, len(sizes)))
plt.pie(sizes, labels=labels, colors=colors, autopct='%1.1f%%')
plt.axis('equal')
plt.title('Market Share with Colormap')
plt.show()円グラフでよく使われるカラーマップには、Set1、Set2、Set3、Pastel1、Pastel2、tab10 などがあります。
explodeでスライスを分離して強調する
explode パラメータは、特定のスライスを中心から離して表示し、重要なデータポイントを強調します。explode の各要素は、対応するスライスの半径方向オフセットを表します。
import matplotlib.pyplot as plt
sizes = [35, 25, 20, 20]
labels = ['Product A', 'Product B', 'Product C', 'Product D']
colors = ['#ff9999', '#66b3ff', '#99ff99', '#ffcc99']
explode = (0.1, 0, 0, 0) # Explode the first slice
plt.pie(sizes, labels=labels, colors=colors, autopct='%1.1f%%',
explode=explode)
plt.axis('equal')
plt.title('Market Share with Exploded Slice')
plt.show()0.1 は最初のスライスを半径の10%分だけ外側に移動します。複数のスライスを分離することもできます。
explode = (0.1, 0.05, 0, 0) # Explode first two slices
plt.pie(sizes, labels=labels, colors=colors, autopct='%1.1f%%',
explode=explode)影(shadow)と開始角度(startangle)を追加する
shadow はドロップシャドウで立体感を加え、startangle はチャート全体を回転してスライス位置を調整します。
import matplotlib.pyplot as plt
sizes = [35, 25, 20, 20]
labels = ['Product A', 'Product B', 'Product C', 'Product D']
colors = ['#ff9999', '#66b3ff', '#99ff99', '#ffcc99']
explode = (0.1, 0, 0, 0)
plt.pie(sizes, labels=labels, colors=colors, autopct='%1.1f%%',
explode=explode, shadow=True, startangle=90)
plt.axis('equal')
plt.title('Market Share with Shadow and Rotation')
plt.show()startangle=90 により、最初のスライスの開始位置がデフォルトの0度(円の右側)ではなく90度(円の上)になります。重要なスライスを上部に配置して視認性を高めたい場合に有効です。
ドーナツチャートを作成する
ドーナツチャートは中心が空洞の円グラフで、wedgeprops を使って各ウェッジの幅を設定して作成します。
import matplotlib.pyplot as plt
sizes = [35, 25, 20, 20]
labels = ['Product A', 'Product B', 'Product C', 'Product D']
colors = ['#ff9999', '#66b3ff', '#99ff99', '#ffcc99']
# Create donut chart
wedgeprops = {'width': 0.4}
plt.pie(sizes, labels=labels, colors=colors, autopct='%1.1f%%',
wedgeprops=wedgeprops)
plt.axis('equal')
plt.title('Market Share Donut Chart')
plt.show()width=0.4 は、半径全体の40%分の厚みを持つリングを作ります。値が小さいほどリングは細くなり、1.0に近いほど通常の円グラフに近づきます。
ドーナツの中心にテキストを追加することもできます。
import matplotlib.pyplot as plt
sizes = [35, 25, 20, 20]
labels = ['Product A', 'Product B', 'Product C', 'Product D']
colors = ['#ff9999', '#66b3ff', '#99ff99', '#ffcc99']
wedgeprops = {'width': 0.4, 'edgecolor': 'white', 'linewidth': 2}
plt.pie(sizes, labels=labels, colors=colors, autopct='%1.1f%%',
wedgeprops=wedgeprops)
plt.axis('equal')
# Add center text
plt.text(0, 0, 'Total\nSales', ha='center', va='center',
fontsize=14, fontweight='bold')
plt.title('Market Share Donut Chart')
plt.show()ネスト(同心)円グラフ
複数の円グラフを半径を変えて重ねることで、階層関係を表す複雑な可視化を作れます。
import matplotlib.pyplot as plt
import numpy as np
# Outer ring data
outer_sizes = [35, 25, 20, 20]
outer_labels = ['Product A', 'Product B', 'Product C', 'Product D']
outer_colors = ['#ff9999', '#66b3ff', '#99ff99', '#ffcc99']
# Inner ring data (subcategories)
inner_sizes = [15, 20, 12, 13, 10, 10, 8, 12]
inner_labels = ['A1', 'A2', 'B1', 'B2', 'C1', 'C2', 'D1', 'D2']
inner_colors = ['#ffcccc', '#ff6666', '#99ccff', '#3399ff',
'#ccffcc', '#66ff66', '#ffe6cc', '#ffb366']
fig, ax = plt.subplots()
# Outer pie
ax.pie(outer_sizes, labels=outer_labels, colors=outer_colors,
autopct='%1.1f%%', radius=1.2, wedgeprops={'width': 0.4})
# Inner pie
ax.pie(inner_sizes, labels=inner_labels, colors=inner_colors,
autopct='%1.0f%%', radius=0.8, wedgeprops={'width': 0.4})
ax.axis('equal')
plt.title('Nested Pie Chart: Products and Subcategories')
plt.show()この例では2つの同心ドーナツチャートを作成し、内側のリングが外側のセグメントに対応するサブカテゴリを示します。
凡例(Legend)を追加する
スライス数が多い場合やラベルが混雑する場合、legend() でラベルを凡例へ移すと読みやすくなります。
import matplotlib.pyplot as plt
sizes = [35, 25, 20, 15, 5]
labels = ['Product A', 'Product B', 'Product C', 'Product D', 'Others']
colors = ['#ff9999', '#66b3ff', '#99ff99', '#ffcc99', '#ff99cc']
plt.pie(sizes, colors=colors, autopct='%1.1f%%', startangle=90)
plt.axis('equal')
plt.legend(labels, loc='upper left', bbox_to_anchor=(1, 0, 0.5, 1))
plt.title('Market Share Distribution')
plt.tight_layout()
plt.show()bbox_to_anchor は凡例をチャート領域の外側に配置するための指定です。tight_layout() は凡例が切れないようにレイアウトを調整します。
割合付きのカスタム凡例を作る例:
import matplotlib.pyplot as plt
sizes = [35, 25, 20, 15, 5]
labels = ['Product A', 'Product B', 'Product C', 'Product D', 'Others']
colors = ['#ff9999', '#66b3ff', '#99ff99', '#ffcc99', '#ff99cc']
wedges, texts, autotexts = plt.pie(sizes, colors=colors, autopct='%1.1f%%',
startangle=90)
plt.axis('equal')
# Create legend with labels and percentages
legend_labels = [f'{label} ({size}%)' for label, size in zip(labels, sizes)]
plt.legend(wedges, legend_labels, loc='upper left',
bbox_to_anchor=(1, 0, 0.5, 1))
plt.title('Market Share Distribution')
plt.tight_layout()
plt.show()円グラフのパラメータ参照
| Parameter | Type | Description | Example |
|---|---|---|---|
x | array-like | スライスの大きさ(必須) | [30, 25, 20, 25] |
labels | list of str | 各スライスのテキストラベル | ['A', 'B', 'C', 'D'] |
colors | list | 各スライスの色 | ['red', 'blue', 'green'] |
autopct | str or function | 割合表示のフォーマット文字列/関数 | '%1.1f%%' |
explode | tuple | 各スライスの半径方向オフセット | (0.1, 0, 0, 0) |
shadow | bool | ドロップシャドウを追加 | True or False |
startangle | float | 回転角(度) | 90 |
radius | float | 円グラフの半径 | 1.0 (default) |
wedgeprops | dict | wedgeパッチのプロパティ | {'width': 0.4} |
textprops | dict | テキストラベルのプロパティ | {'fontsize': 12} |
labeldistance | float | ラベルの中心からの距離 | 1.1 (default) |
pctdistance | float | パーセントテキストの中心からの距離 | 0.6 (default) |
counterclock | bool | スライスの描画方向 | True (default) |
frame | bool | 軸フレームを描画 | False (default) |
テキストプロパティをカスタマイズする
textprops は、ラベルやパーセント表示を含む円グラフ上の全テキスト要素の見た目を制御します。
import matplotlib.pyplot as plt
sizes = [35, 25, 20, 20]
labels = ['Product A', 'Product B', 'Product C', 'Product D']
colors = ['#ff9999', '#66b3ff', '#99ff99', '#ffcc99']
textprops = {'fontsize': 14, 'fontweight': 'bold', 'color': 'darkblue'}
plt.pie(sizes, labels=labels, colors=colors, autopct='%1.1f%%',
textprops=textprops)
plt.axis('equal')
plt.title('Market Share with Custom Text', fontsize=16, fontweight='bold')
plt.show()ラベルとパーセント表示を別々に制御したい場合は、返されるテキストオブジェクトにアクセスします。
import matplotlib.pyplot as plt
sizes = [35, 25, 20, 20]
labels = ['Product A', 'Product B', 'Product C', 'Product D']
colors = ['#ff9999', '#66b3ff', '#99ff99', '#ffcc99']
wedges, texts, autotexts = plt.pie(sizes, labels=labels, colors=colors,
autopct='%1.1f%%')
# Customize label text
for text in texts:
text.set_fontsize(12)
text.set_fontweight('bold')
# Customize percentage text
for autotext in autotexts:
autotext.set_color('white')
autotext.set_fontsize(10)
autotext.set_fontweight('bold')
plt.axis('equal')
plt.title('Market Share with Styled Text')
plt.show()Pandas DataFramesと一緒に使う
実務のデータ分析ではpandas DataFrameを扱うことが多く、DataFrameの列から直接円グラフを作成できます。
import matplotlib.pyplot as plt
import pandas as pd
# Sample DataFrame
data = {
'Product': ['Product A', 'Product B', 'Product C', 'Product D'],
'Sales': [350000, 250000, 200000, 200000]
}
df = pd.DataFrame(data)
# Create pie chart from DataFrame
plt.pie(df['Sales'], labels=df['Product'], autopct='%1.1f%%',
startangle=90)
plt.axis('equal')
plt.title('Sales Distribution by Product')
plt.show()集計が必要なデータでは、描画前にpandasで集約します。
import matplotlib.pyplot as plt
import pandas as pd
# Sample DataFrame with categories
data = {
'Region': ['North', 'South', 'East', 'West', 'North', 'South', 'East', 'West'],
'Product': ['A', 'A', 'A', 'A', 'B', 'B', 'B', 'B'],
'Sales': [120000, 80000, 95000, 105000, 90000, 110000, 85000, 95000]
}
df = pd.DataFrame(data)
# Group by region and sum sales
region_sales = df.groupby('Region')['Sales'].sum()
plt.pie(region_sales.values, labels=region_sales.index, autopct='%1.1f%%',
startangle=90)
plt.axis('equal')
plt.title('Total Sales by Region')
plt.show()円グラフをファイルに保存する
plt.show() の前に plt.savefig() を呼び出すと、さまざまな画像形式で保存できます。
import matplotlib.pyplot as plt
sizes = [35, 25, 20, 20]
labels = ['Product A', 'Product B', 'Product C', 'Product D']
colors = ['#ff9999', '#66b3ff', '#99ff99', '#ffcc99']
plt.pie(sizes, labels=labels, colors=colors, autopct='%1.1f%%')
plt.axis('equal')
plt.title('Market Share Distribution')
# Save as PNG with high DPI
plt.savefig('market_share.png', dpi=300, bbox_inches='tight')
# Save as PDF for vector graphics
plt.savefig('market_share.pdf', bbox_inches='tight')
# Save as SVG for web use
plt.savefig('market_share.svg', bbox_inches='tight')
plt.show()bbox_inches='tight' は周辺の余白を詰めます。dpi はPNGなどラスタ形式の解像度を制御します。
実務例:予算の内訳
import matplotlib.pyplot as plt
import pandas as pd
# Annual budget data
budget_data = {
'Category': ['Salaries', 'Marketing', 'Operations', 'R&D', 'Infrastructure'],
'Amount': [450000, 180000, 120000, 150000, 100000]
}
df = pd.DataFrame(budget_data)
# Calculate total budget
total_budget = df['Amount'].sum()
# Define colors
colors = ['#ff6b6b', '#4ecdc4', '#45b7d1', '#f9ca24', '#6c5ce7']
# Create pie chart
fig, ax = plt.subplots(figsize=(10, 7))
wedges, texts, autotexts = ax.pie(df['Amount'], labels=df['Category'],
colors=colors, autopct='%1.1f%%',
startangle=90, explode=(0.05, 0, 0, 0, 0))
# Customize text
for text in texts:
text.set_fontsize(12)
text.set_fontweight('bold')
for autotext in autotexts:
autotext.set_color('white')
autotext.set_fontsize(10)
autotext.set_fontweight('bold')
ax.axis('equal')
plt.title(f'Annual Budget Breakdown\nTotal: ${total_budget:,}',
fontsize=16, fontweight='bold', pad=20)
plt.tight_layout()
plt.savefig('budget_breakdown.png', dpi=300, bbox_inches='tight')
plt.show()実務例:アンケート結果
import matplotlib.pyplot as plt
import numpy as np
# Survey response data
responses = {
'Very Satisfied': 145,
'Satisfied': 230,
'Neutral': 85,
'Dissatisfied': 30,
'Very Dissatisfied': 10
}
labels = list(responses.keys())
sizes = list(responses.values())
total_responses = sum(sizes)
# Color scheme from red to green
colors = ['#2ecc71', '#3498db', '#95a5a6', '#e67e22', '#e74c3c']
fig, ax = plt.subplots(figsize=(10, 7))
wedges, texts, autotexts = ax.pie(sizes, labels=labels, colors=colors,
autopct=lambda pct: f'{pct:.1f}%\n({int(pct * total_responses / 100)})',
startangle=90, wedgeprops={'edgecolor': 'white', 'linewidth': 2})
for text in texts:
text.set_fontsize(11)
for autotext in autotexts:
autotext.set_color('white')
autotext.set_fontsize(9)
autotext.set_fontweight('bold')
ax.axis('equal')
plt.title(f'Customer Satisfaction Survey Results\nTotal Responses: {total_responses}',
fontsize=16, fontweight='bold', pad=20)
plt.tight_layout()
plt.show()実務例:市場シェア分析
import matplotlib.pyplot as plt
import pandas as pd
# Market share data for multiple quarters
data = {
'Company': ['Company A', 'Company B', 'Company C', 'Company D', 'Others'],
'Q1_Share': [28, 24, 18, 15, 15],
'Q2_Share': [30, 22, 19, 14, 15],
'Q3_Share': [32, 21, 18, 15, 14],
'Q4_Share': [35, 20, 17, 16, 12]
}
df = pd.DataFrame(data)
# Create subplots for each quarter
fig, axes = plt.subplots(2, 2, figsize=(14, 12))
quarters = ['Q1_Share', 'Q2_Share', 'Q3_Share', 'Q4_Share']
colors = ['#ff9999', '#66b3ff', '#99ff99', '#ffcc99', '#ff99cc']
for idx, (ax, quarter) in enumerate(zip(axes.flat, quarters)):
wedges, texts, autotexts = ax.pie(df[quarter], labels=df['Company'],
colors=colors, autopct='%1.1f%%',
startangle=90)
for text in texts:
text.set_fontsize(10)
for autotext in autotexts:
autotext.set_color('white')
autotext.set_fontsize(9)
autotext.set_fontweight('bold')
ax.set_title(f'Market Share {quarter.replace("_Share", "")}',
fontsize=12, fontweight='bold')
plt.suptitle('Quarterly Market Share Analysis', fontsize=16, fontweight='bold', y=0.995)
plt.tight_layout()
plt.savefig('market_share_analysis.png', dpi=300, bbox_inches='tight')
plt.show()円グラフを他の可視化と組み合わせる
円グラフと棒グラフ、折れ線、表などを組み合わせて、包括的なダッシュボードを作れます。
import matplotlib.pyplot as plt
import pandas as pd
import numpy as np
# Sample data
categories = ['Product A', 'Product B', 'Product C', 'Product D']
current_sales = [350000, 250000, 200000, 200000]
previous_sales = [320000, 280000, 180000, 220000]
# Create figure with subplots
fig = plt.figure(figsize=(14, 6))
# Pie chart showing current market share
ax1 = plt.subplot(1, 2, 1)
colors = ['#ff9999', '#66b3ff', '#99ff99', '#ffcc99']
ax1.pie(current_sales, labels=categories, colors=colors, autopct='%1.1f%%',
startangle=90)
ax1.set_title('Current Market Share', fontsize=14, fontweight='bold')
# Bar chart showing comparison
ax2 = plt.subplot(1, 2, 2)
x = np.arange(len(categories))
width = 0.35
bars1 = ax2.bar(x - width/2, previous_sales, width, label='Previous Period',
color='#95a5a6', alpha=0.8)
bars2 = ax2.bar(x + width/2, current_sales, width, label='Current Period',
color='#3498db', alpha=0.8)
ax2.set_xlabel('Products', fontsize=12, fontweight='bold')
ax2.set_ylabel('Sales ($)', fontsize=12, fontweight='bold')
ax2.set_title('Sales Comparison', fontsize=14, fontweight='bold')
ax2.set_xticks(x)
ax2.set_xticklabels(categories)
ax2.legend()
ax2.grid(axis='y', alpha=0.3)
plt.tight_layout()
plt.savefig('combined_visualization.png', dpi=300, bbox_inches='tight')
plt.show()円グラフと棒グラフの使い分け
円グラフは特定の状況で有効ですが、棒グラフのほうが比較が明確になることも多いです。
円グラフを使うべきケース:
- 全体に対する内訳(割合の合計が100%になる)
- カテゴリが5つ以下
- 1〜2つの支配的なセグメントを強調したい
- 厳密な比率よりも大まかな構成が重要
- 経営層向けのハイレベルな要約を作る
棒グラフを使うべきケース:
- カテゴリ間の値を比較したい
- カテゴリが5つを超える
- 正確な値の比較が重要
- 合計が意味のある「全体」にならない
- 時系列のトレンドを示したい
- 近い値同士の差を見分ける必要がある
比較例:
import matplotlib.pyplot as plt
data = {'Category A': 23, 'Category B': 19, 'Category C': 18,
'Category D': 17, 'Category E': 13, 'Category F': 10}
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(14, 5))
# Pie chart
ax1.pie(data.values(), labels=data.keys(), autopct='%1.1f%%', startangle=90)
ax1.set_title('Pie Chart: Harder to Compare Similar Values', fontweight='bold')
# Bar chart
ax2.bar(data.keys(), data.values(), color='#3498db')
ax2.set_ylabel('Value', fontweight='bold')
ax2.set_title('Bar Chart: Easier to Compare Similar Values', fontweight='bold')
ax2.grid(axis='y', alpha=0.3)
plt.tight_layout()
plt.show()棒グラフのほうが、カテゴリ間の小さな差を円グラフよりもはるかに把握しやすくなります。
PyGWalkerでインタラクティブな円グラフを作る
探索的データ分析(EDA)でインタラクティブな可視化が必要な場合、PyGWalker (opens in a new tab) を使うと、pandas DataFramesをドラッグ&ドロップで円グラフを作れるTableau風のインターフェースに変換できます。
import pandas as pd
import pygwalker as pyg
# Sample DataFrame
data = {
'Product': ['Product A', 'Product B', 'Product C', 'Product D', 'Product E'],
'Sales': [350000, 250000, 200000, 200000, 150000],
'Region': ['North', 'South', 'East', 'West', 'North']
}
df = pd.DataFrame(data)
# Launch interactive visualization interface
walker = pyg.walk(df)PyGWalkerを使うと、コーディング経験が少ないビジネスアナリストでも、円グラフを含む可視化を対話的に作成でき、データを動的にフィルタし、結果をプレゼン用にエクスポートできます。複雑な集計や統計サマリーもツール側で扱えるため、matplotlibで本番用可視化を仕上げる前の高速プロトタイピングとして有用です。
高度なカスタマイズ:境界色と線スタイル
wedgeprops で境界色や線幅を指定すると、スライス間の視覚的な区切りを強められます。
import matplotlib.pyplot as plt
sizes = [35, 25, 20, 20]
labels = ['Product A', 'Product B', 'Product C', 'Product D']
colors = ['#ff9999', '#66b3ff', '#99ff99', '#ffcc99']
wedgeprops = {
'edgecolor': 'black',
'linewidth': 2,
'linestyle': '-',
'antialiased': True
}
plt.pie(sizes, labels=labels, colors=colors, autopct='%1.1f%%',
startangle=90, wedgeprops=wedgeprops)
plt.axis('equal')
plt.title('Market Share with Edge Styling')
plt.show()控えめな効果にしたい場合は白い境界線が定番です。
wedgeprops = {'edgecolor': 'white', 'linewidth': 3}小さいスライスとラベルの重なりに対応する
小さいスライスが多いとラベルが重なりがちです。凡例を使う、図のサイズを大きくする、ラベル位置を調整する、といった対策が有効です。
import matplotlib.pyplot as plt
# Data with several small slices
sizes = [30, 25, 15, 10, 8, 5, 4, 3]
labels = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H']
colors = plt.cm.Set3(range(len(sizes)))
fig, ax = plt.subplots(figsize=(10, 8))
wedges, texts, autotexts = ax.pie(sizes, colors=colors, autopct='%1.1f%%',
startangle=90, pctdistance=0.85)
# Remove labels from pie and use legend
for text in texts:
text.set_text('')
ax.legend(wedges, labels, title="Categories", loc="center left",
bbox_to_anchor=(1, 0, 0.5, 1))
ax.axis('equal')
ax.set_title('Distribution with Many Categories', fontsize=14, fontweight='bold')
plt.tight_layout()
plt.show()別案として、チャート上には割合のみを表示し、カテゴリ名は凡例に回すことで、視覚的な混雑を減らせます。
複数リングの比例ドーナツチャートを作る
複数階層の内訳を示す、より複雑な階層可視化を構築できます。
import matplotlib.pyplot as plt
import numpy as np
# Department budget data
departments = ['Engineering', 'Sales', 'Marketing', 'Operations']
dept_budgets = [400000, 300000, 200000, 100000]
# Team breakdown within departments
teams = ['Backend', 'Frontend', 'Mobile',
'Field Sales', 'Inside Sales',
'Digital', 'Content',
'Logistics', 'Support']
team_budgets = [200000, 150000, 50000,
180000, 120000,
120000, 80000,
60000, 40000]
fig, ax = plt.subplots(figsize=(12, 8))
# Outer ring (departments)
dept_colors = ['#e74c3c', '#3498db', '#2ecc71', '#f39c12']
outer_pie = ax.pie(dept_budgets, labels=departments, colors=dept_colors,
autopct='%1.1f%%', radius=1.3, wedgeprops={'width': 0.35})
# Inner ring (teams)
team_colors = ['#c0392b', '#e74c3c', '#ec7063',
'#2980b9', '#3498db',
'#27ae60', '#2ecc71',
'#d68910', '#f39c12']
inner_pie = ax.pie(team_budgets, labels=teams, colors=team_colors,
autopct='%1.0f%%', radius=0.95,
wedgeprops={'width': 0.35}, labeldistance=0.7,
textprops={'fontsize': 9})
ax.axis('equal')
plt.title('Organizational Budget Breakdown\nDepartments and Teams',
fontsize=16, fontweight='bold', pad=20)
plt.tight_layout()
plt.show()この例では2階層のドーナツチャートを作り、内側リングのチーム予算が外側の部署セグメントに対応する形で表示されます。
FAQ
matplotlibで基本的な円グラフを作るには?
値のリストと(必要に応じて)ラベルを plt.pie() に渡します。楕円ではなく円にするために plt.axis('equal') を入れてください。基本形は plt.pie(sizes, labels=labels) のあとに plt.show() で表示します。
matplotlibの円グラフでautopctパラメータは何をしますか?
autopct は各スライスに割合(パーセント)を自動表示します。小数第1位なら '%1.1f%%'、整数なら '%1.0f%%' を使います。また、カスタム関数を渡して、割合と実数の両方を同時表示することも可能です。
matplotlibでドーナツチャートを作るには?
wedgeprops に width を指定して、1未満にします。たとえば wedgeprops={'width': 0.4} で半径40%のリングのドーナツになります。plt.text() を組み合わせると中心の空洞にラベルを追加できます。
円グラフで特定のスライスだけを分離(explode)するには?
explode に各スライスのオフセットを並べたタプルを渡します。例えば explode=(0.1, 0, 0, 0) は最初のスライスを半径の10%分だけ外へ移動し、他はそのままです。値を大きくするほど分離が強くなります。
棒グラフではなく円グラフを使うべきなのはいつですか?
カテゴリが5つ以下で、合計が100%になる「全体の内訳」を示す場合は円グラフが適しています。カテゴリ比較や項目が多い場合、精密な値比較が重要な場合は棒グラフが適しています。棒グラフのほうが近い値同士の比較がしやすいです。
matplotlibの円グラフで色をカスタマイズするには?
colors パラメータに色のリスト(名前付きカラー、16進、RGBタプルなど)を渡します。データ駆動の配色には、plt.cm.Set3 のようなカラーマップと np.linspace() を組み合わせて色配列を生成します。円グラフ向きのカラーマップには Set1/Set2/Set3/Pastel1 などがあります。
スライスラベルの代わりに凡例を表示するには?
plt.legend() にラベルを渡し、loc と bbox_to_anchor で配置します。例として plt.legend(labels, loc='upper left', bbox_to_anchor=(1, 0, 0.5, 1)) で、右側の外に凡例を置けます。plt.tight_layout() で切れを防ぎます。
まとめ
Matplotlibの円グラフは、適切に使えば、比率データを可視化する強力な手段になります。このガイドでは、基本的な円形チャートから高度なネスト型ドーナツ可視化まで、ラベル・色・explodeによる強調・割合表示・DataFrame連携といった要素を、実用例とともに幅広く解説しました。パラメータ参照表はカスタマイズ時のクイックリファレンスとして役立ち、実務例は予算分析、アンケート結果、市場シェア報告への適用方法を示しています。
円グラフはカテゴリが少なく、比率が明確に分かれる場合に最適で、詳細な比較には棒グラフが向いています。分析中のインタラクティブな探索には、PyGWalkerがコード不要の代替手段として、matplotlibで本番用可視化を仕上げる前の迅速なプロトタイピングに役立ちます。これらのmatplotlib手法と、「円グラフと棒グラフをいつ使い分けるか」という設計判断を組み合わせることで、どんなオーディエンスにも洞察を明確に伝える、分かりやすく有益な可視化を作成できます。