Written and maintained by CASRAI Editorial Board
Last updated
A pie chart in Python is most often drawn with Matplotlib’s pie() function: pass it a list of values and it draws one wedge per value, sized as that value’s share of the total. This guide is for researchers and graduate students who need to produce a labelled pie figure from a table of counts or proportions, either straight from a list or from a pandas DataFrame, and who want to know what each option does. Examples are based on the Matplotlib 3.11.2 and pandas documentation (read 2026-11-08).
What a pie chart is used for in research
A pie chart shows how a single total divides into parts: the fractional area of each wedge is x/sum(x). It suits a small number of categories that make up a whole, such as the share of respondents in each group or of funding by category. For comparing values across categories, or across several groups, a bar chart is usually easier to read; see great data visualization examples for research figures and types of graphs in statistics for when to choose which.
Install or access Matplotlib
Matplotlib’s installation page gives these official routes:
python -m pip install -U pip
python -m pip install -U matplotlib
conda install -c conda-forge matplotlib
The first pair uses pip; the last line uses conda from the conda-forge channel. Source: matplotlib.org install guide.
Make a pie chart in Python with Matplotlib
Step 1: A basic pie chart
- Import the plotting interface:
import matplotlib.pyplot as plt. - Define labels and sizes. The Matplotlib gallery example uses
labels = 'Frogs', 'Hogs', 'Dogs', 'Logs'andsizes = [15, 30, 45, 10]. - Create the axes and draw:
fig, ax = plt.subplots()thenax.pie(sizes, labels=labels). - Show the figure with
plt.show().
The sizes do not need to add up to 100. With the default normalize=True, x is normalized so the pie is always full; with normalize=False the chart is a partial pie if sum(x) <= 1, and a ValueError is raised if sum(x) > 1.
Step 2: Add percentages with autopct
Pass autopct='%1.1f%%' to print each wedge’s percentage with one decimal place. autopct accepts a format string or a function. pctdistance (default 0.6) sets where those numbers sit, as a fraction of the radius.
ax.pie(sizes, labels=labels, autopct='%1.1f%%')
Step 3: Explode, start angle and shadow
The gallery example offsets one wedge and rotates the chart:
explode = (0, 0.1, 0, 0)
ax.pie(sizes, explode=explode, labels=labels, autopct='%1.1f%%',
shadow=True, startangle=90)
explode takes one offset fraction per wedge, so its length must equal len(x). startangle defaults to 0, which starts the first slice on the positive x-axis, and wedges run counterclockwise (counterclock=True); startangle=90 moves the first slice to the positive y-axis.
Step 4: Labels, colours and text styling
labeldistance(default 1.1) andpctdistance(default 0.6) are ratios of the radius; values above 1 place text outside the pie.colorssets a colour per wedge;hatchsets a hatch pattern per slice.textpropsstyles label text, for exampletextprops={'size': 'small'};radiusscales the pie (the gallery showsradius=0.5).wedgeprops={'width': 0.4}turns the pie into a donut chart.
Pie chart from a pandas DataFrame
If your data are already in a table, DataFrame.plot.pie(y=None, **kwargs) wraps matplotlib.pyplot.pie. Choose the column with y; if you omit y, you must pass subplots=True to get one pie per column. The index supplies the labels. The pandas documentation example:
import pandas as pd
df = pd.DataFrame({'mass': [0.330, 4.87, 5.97],
'radius': [2439.7, 6051.8, 6378.1]},
index=['Mercury', 'Venus', 'Earth'])
plot = df.plot.pie(y='mass', figsize=(5, 5))
plot = df.plot.pie(subplots=True, figsize=(11, 6))
It returns a Matplotlib Axes object, or an array of them when subplots=True.
Output and how to read it
Each wedge’s angle is its share of the total, starting at the x-axis and running counterclockwise unless you change startangle or counterclock. Reading a pie is a judgement of angle and area, which is why labelled percentages (autopct) belong on any figure meant for a paper. In Matplotlib 3.11 pie() returns a container holding the wedge patches and associated text objects; before 3.11 it returned them as a tuple. Keep the returned object if you want to restyle individual wedges or labels after drawing.
Troubleshooting
| Problem | What the documentation says |
|---|---|
| Pie looks oval | pie() sets the axes aspect to equal, and the chart looks best with a square figure and Axes. The aspect can be changed with Axes.set_aspect, so check you have not overridden it. |
| Chart is not a full circle or raises ValueError | Occurs with normalize=False when values sum to 1 or less (partial pie) or more than 1 (ValueError). Leave normalize at its default True for a full pie. |
| Labels or percentages overlap | Move them with labeldistance and pctdistance (ratios of the radius), reduce text size with textprops, or change radius. |
pandas raises an error without y |
Give y a column label or position, or set subplots=True. |
| Explode raises an error | explode must have one entry per wedge (length len(x)). |
Other ways to draw a pie chart
| Route | Call | Notes |
|---|---|---|
| Matplotlib (pyplot) | plt.pie(x, ...) |
Wrapper for axes.Axes.pie. |
| Matplotlib (object-oriented) | ax.pie(x, ...) |
Used in the official gallery example. |
| pandas | df.plot.pie(y='col') |
Wraps matplotlib.pyplot.pie. |
For a comparison of the wider plotting libraries, see Seaborn vs Matplotlib and Plotly vs Matplotlib. For three-dimensional figures, see 3D plot in Python.
FAQ
How do I make a pie chart in Python?
Import matplotlib.pyplot, then call ax.pie(sizes, labels=labels) on an Axes from plt.subplots() and display it with plt.show(). Each wedge’s area is its value divided by the sum of all values.
How do I show percentages on a Python pie chart?
Set autopct='%1.1f%%' (a format string or function) in the pie() call.
How do I make a pie chart from a pandas DataFrame?
Call df.plot.pie(y='column_name'), or df.plot.pie(subplots=True) for one pie per column.
How do I make a donut chart?
Pass wedgeprops={'width': 0.4} to pie().
How do I highlight one slice?
Use explode with one offset per wedge, for example (0, 0.1, 0, 0).







