Skip to content

Matplotlib Pie Chart: Complete Guide to Creating Pie Charts in Python

Updated on

Creating effective data visualizations is critical for communicating insights clearly. When you need to show proportions or percentages of a whole, pie charts become an essential tool in your visualization arsenal. Yet many data analysts struggle with creating professional-looking pie charts that properly highlight important segments, use appropriate colors, and display percentages accurately. The default matplotlib pie chart often looks plain, lacks context, and fails to emphasize key data points.

These visualization challenges become more acute when presenting to stakeholders who need to quickly grasp market share distributions, budget allocations, or survey response breakdowns. A poorly designed pie chart can confuse rather than clarify, leading to misinterpretation of critical business metrics.

Matplotlib provides a comprehensive plt.pie() function with extensive customization options that transform basic circular charts into professional visualizations. This guide demonstrates how to create pie charts from simple proportions to complex nested diagrams, with practical examples covering labels, colors, exploded slices, donut charts, and integration with pandas DataFrames for real-world data analysis workflows.

📚

Basic Matplotlib Pie Chart Syntax

The foundation of creating pie charts in matplotlib starts with plt.pie(), which requires only a list or array of values representing the size of each slice.

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()

This creates a basic circular chart where slice sizes are proportional to the values in the sizes list. Matplotlib automatically calculates percentages and angles for each segment. The chart assigns colors from the default color cycle, which may not always suit your presentation needs.

For proper circular appearance rather than an ellipse, add 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()

Displaying Percentages with autopct

The autopct parameter automatically formats and displays percentage values on each slice, making the chart more informative without manual calculation.

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()

The format string '%1.1f%%' displays percentages with one decimal place. The first % starts the format specifier, 1.1f means one digit before the decimal and one after, and %% produces a literal percent symbol in the output.

For integer percentages without decimals, use '%1.0f%%':

plt.pie(sizes, labels=labels, autopct='%1.0f%%')

You can also pass a custom function to autopct for more control over percentage display:

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()

This displays both the percentage and the actual count on each slice.

Custom Colors and Colormaps

The colors parameter accepts a list of color specifications to override matplotlib's default color cycle. You can use named colors, hex codes, or RGB tuples.

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()

For data-driven color selection, use matplotlib colormaps:

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()

Popular colormaps for pie charts include Set1, Set2, Set3, Pastel1, Pastel2, and tab10.

Exploding Slices for Emphasis

The explode parameter separates specific slices from the center to emphasize important data points. Each value in the explode tuple represents the radial offset for the corresponding slice.

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()

The value 0.1 moves the first slice outward by 10% of the radius. You can explode multiple slices:

explode = (0.1, 0.05, 0, 0)  # Explode first two slices
plt.pie(sizes, labels=labels, colors=colors, autopct='%1.1f%%',
        explode=explode)

Adding Shadow and Start Angle

The shadow parameter adds a drop shadow for a three-dimensional effect, while startangle rotates the entire chart to position slices at specific angles.

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()

The startangle=90 rotates the chart so the first slice starts at 90 degrees (top of the circle) instead of the default 0 degrees (right side). This is useful for positioning important slices at the top for better visibility.

Creating Donut Charts

Donut charts are pie charts with a hollow center, created using the wedgeprops parameter to set the width of each wedge.

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()

The width value of 0.4 creates a ring that is 40% of the full radius. A smaller value creates a thinner ring, while values closer to 1.0 approach a full pie chart.

You can add text in the center of the donut chart:

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()

Nested and Concentric Pie Charts

Create complex visualizations by plotting multiple pie charts with different radii to show hierarchical data relationships.

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()

This creates two concentric donut charts where the inner ring shows subcategories of the outer ring segments.

Adding Legends

For charts with many slices or when labels clutter the visualization, move slice labels to a legend using the legend() function.

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()

The bbox_to_anchor parameter positions the legend outside the chart area. The tight_layout() function adjusts the plot area to prevent legend clipping.

For custom legend entries with percentages:

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()

Pie Chart Parameter Reference

ParameterTypeDescriptionExample
xarray-likeSlice sizes (required)[30, 25, 20, 25]
labelslist of strText labels for each slice['A', 'B', 'C', 'D']
colorslistColors for each slice['red', 'blue', 'green']
autopctstr or functionFormat string or function for percentages'%1.1f%%'
explodetupleRadial offset for each slice(0.1, 0, 0, 0)
shadowboolAdd drop shadowTrue or False
startanglefloatRotation angle in degrees90
radiusfloatPie chart radius1.0 (default)
wedgepropsdictProperties for wedge patches{'width': 0.4}
textpropsdictProperties for text labels{'fontsize': 12}
labeldistancefloatDistance of labels from center1.1 (default)
pctdistancefloatDistance of percentage text from center0.6 (default)
counterclockboolDirection of slicesTrue (default)
frameboolDraw axis frameFalse (default)

Customizing Text Properties

The textprops parameter controls the appearance of all text elements on the pie chart, including labels and percentages.

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()

For separate control over labels and percentage text, access the returned text objects:

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()

Working with Pandas DataFrames

Real-world data analysis often involves pandas DataFrames. You can create pie charts directly from DataFrame columns.

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()

For grouped data, use pandas aggregation before plotting:

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()

Saving Pie Charts to Files

Save pie charts to various image formats using plt.savefig() before calling 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']
 
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()

The bbox_inches='tight' parameter removes extra whitespace around the chart. The dpi parameter controls resolution for raster formats like PNG.

Real-World Example: Budget Breakdown

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()

Real-World Example: Survey Results

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()

Real-World Example: Market Share Analysis

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()

Combining Pie Charts with Other Visualizations

Create comprehensive dashboards by combining pie charts with bar charts, line graphs, or tables.

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()

When to Use Pie Charts vs Bar Charts

Pie charts work best in specific scenarios, but bar charts often provide clearer comparisons.

Use pie charts when:

  • Showing parts of a whole (percentages must sum to 100%)
  • Displaying 5 or fewer categories
  • Emphasizing one or two dominant segments
  • The exact proportions are less important than general composition
  • Creating high-level executive summaries

Use bar charts when:

  • Comparing values across categories
  • Displaying more than 5 categories
  • Showing precise value comparisons
  • Values don't sum to a meaningful whole
  • Displaying trends over time
  • Stakeholders need to compare similar-sized segments

Comparison example:

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()

The bar chart makes small differences between categories much more apparent than the pie chart.

Interactive Pie Charts with PyGWalker

For exploratory data analysis requiring interactive visualizations, PyGWalker (opens in a new tab) transforms pandas DataFrames into interactive Tableau-like interfaces with drag-and-drop pie chart creation.

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 enables business analysts without coding expertise to create pie charts and other visualizations interactively, filter data dynamically, and export results for presentations. The tool handles complex aggregations and provides built-in statistical summaries, making it valuable for rapid prototyping before finalizing production visualizations with matplotlib.

Advanced Customization: Edge Colors and Line Styles

Add visual separation between slices using edge colors and line widths through the wedgeprops parameter.

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()

For a subtle effect, use white edges:

wedgeprops = {'edgecolor': 'white', 'linewidth': 3}

Handling Small Slices and Label Overlap

When dealing with many small slices, labels can overlap. Solutions include using a legend, increasing figure size, or adjusting label positioning.

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()

Alternatively, show only percentage values on the chart and use a legend for category names, reducing visual clutter.

Creating Proportional Donut Charts with Multiple Rings

Build complex hierarchical visualizations showing category breakdowns across multiple levels.

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()

This creates a two-level donut chart where the inner ring shows team budgets that correspond to the department segments in the outer ring.

FAQ

How do I create a basic pie chart in matplotlib?

Use plt.pie() with a list of values and optional labels. Include plt.axis('equal') to ensure a circular shape rather than an ellipse. The basic syntax is plt.pie(sizes, labels=labels) followed by plt.show() to display the chart.

What does the autopct parameter do in matplotlib pie charts?

The autopct parameter automatically displays percentage values on each slice. Use format strings like '%1.1f%%' for percentages with one decimal place, or '%1.0f%%' for whole numbers. You can also pass a custom function to display both percentages and actual values simultaneously.

How do I create a donut chart in matplotlib?

Create a donut chart by setting the wedgeprops parameter with a width value less than 1. For example, wedgeprops={'width': 0.4} creates a donut with a 40% radius ring. Combine this with plt.text() to add labels in the center hollow area.

How do I explode specific slices in a pie chart?

Use the explode parameter with a tuple of offset values for each slice. For example, explode=(0.1, 0, 0, 0) moves the first slice outward by 10% of the radius while keeping other slices in place. Higher values create larger separations.

When should I use pie charts instead of bar charts?

Use pie charts when showing parts of a whole with 5 or fewer categories where percentages must sum to 100%. Use bar charts when comparing values across categories, displaying more than 5 items, or when precise value comparisons matter more than proportions. Bar charts make it easier to compare similar-sized segments.

How do I customize colors in matplotlib pie charts?

Pass a list of colors to the colors parameter using named colors, hex codes, or RGB tuples. For data-driven colors, use matplotlib colormaps like plt.cm.Set3 combined with np.linspace() to generate color arrays. Popular pie chart colormaps include Set1, Set2, Set3, and Pastel1.

How do I add a legend to a pie chart instead of slice labels?

Call plt.legend() with the labels list and position it using loc and bbox_to_anchor parameters. For example, plt.legend(labels, loc='upper left', bbox_to_anchor=(1, 0, 0.5, 1)) places the legend outside the chart on the right side. Use plt.tight_layout() to prevent clipping.

Conclusion

Matplotlib pie charts provide a powerful way to visualize proportional data when used appropriately. This guide covered the complete spectrum from basic circular charts to advanced nested donut visualizations, with practical examples demonstrating labels, colors, exploded slices, percentage displays, and DataFrame integration. The parameter reference table serves as a quick lookup for customization options, while the real-world examples show how to apply these techniques to budget analysis, survey results, and market share reporting.

Remember that pie charts work best with fewer categories showing clear proportions, while bar charts better serve detailed comparisons. For interactive exploration during analysis, PyGWalker offers a code-free alternative for rapid prototyping before finalizing production visualizations. By combining these matplotlib techniques with thoughtful design choices about when to use pie versus bar charts, you can create clear, informative visualizations that communicate insights effectively to any audience.

📚