One number per slice, and a warning.
When is a pie chart the right answer? Rarely, and it is worth saying so before the syntax. People are good at comparing lengths and bad at comparing angles, so two slices of similar size are nearly impossible to rank by eye — the exact comparison a chart exists to make. A bar chart of the same numbers is easier to read, sorts meaningfully, and survives having a dozen categories rather than four.
The case for a pie is narrow but real: a small number of parts that genuinely add up to one whole, where the point is "this one is about half" rather than "this one is slightly bigger than that one". Vote share, market share, a budget. If your data does not sum to something meaningful, you want plot.bar.
Official documentation: pandas.DataFrame.plot.pie.
The arguments that earn their keep
s.plot.pie() # a Series: index labels, values slice
s.plot.pie(autopct='%1.0f%%') # write the percentage on each slice
s.plot.pie(colors=['red', 'blue']) # when the categories have real colors
s.plot.pie(ylabel='') # drop the axis label Pandas adds
df.plot.pie(y='seats') # a frame: name the column
s.plot.pie(figsize=(7, 7)) # square, or it comes out an ellipse
autopct is the one that makes the chart honest. Without it the reader is guessing at angles; with it every slice carries its number and the pie becomes a labeled summary rather than a visual puzzle. colors matters more here than elsewhere because pie charts so often show things that already have colors — political parties, brands, traffic-light categories — and letting matplotlib assign them at random makes the chart harder to read than a table.
Note the shape requirement: plot.pie wants one number per slice. A Series straight out of value_counts or groupby(...).sum() is exactly right. A whole data frame is not, which is why y= exists.
A worked example, on real data
Every daily VIX close since 1990, bucketed into calm and stressed days:
import pandas as pd
url = 'https://fred.stlouisfed.org/graph/fredgraph.csv?id=VIXCLS'
df = pd.read_csv(url, parse_dates=['observation_date'])
df.columns = ['date', 'vix']
(df
.assign(regime=lambda df_: (df_['vix'] > 20).map({True: 'stressed',
False: 'calm'}))
['regime'].value_counts()
.plot.pie(autopct='%1.0f%%', ylabel='', figsize=(7, 7)))
The Series behind the slices:
regime
calm 6136
stressed 3430
Two slices, 64 percent and 36 percent of 9,566 trading days, and that is a fair use of the format: the categories are exhaustive, they add to every trading day on record, and the interesting fact is a proportion rather than a ranking. Two slices is also where pie charts are at their best — the moment there are seven, the four small ones become indistinguishable and a sorted bar chart wins.
ylabel='' is doing housekeeping. Pandas labels the axis with the Series name, which on a pie chart appears as a stray word beside the circle.
Three mistakes people make
Slicing things that do not sum to a whole. A pie of the top five countries implies the five are everything. If the categories are a selection rather than a partition, either add an "other" slice with the remainder or use a bar chart.
Too many slices. Past about five, adjacent wedges stop being distinguishable and the legend becomes the chart. Group the tail into "other" with replace before plotting.
Leaving out the numbers. Without autopct, a pie chart asks the reader to estimate angles, which they cannot do. If the percentages matter enough to draw, they matter enough to print.
Where it shows up in Bamboo Weekly
Bamboo Weekly #74: UK elections is the case the format was made for. Seats won by party is a genuine partition — every seat belongs to exactly one party, and they add up to Parliament. The solution runs df['party_abbreviation'].value_counts().plot.pie(), then draws it again with colors=['red', 'blue', 'orange', 'lightblue', 'gray', 'green', 'purple'], because British parties have colors readers already know and a random palette would fight what they expect.
Practice it
Work through a plot.pie exercise, with instant feedback and no signup required: practice.lernerpython.com/bamboo-weekly/plot-pie/
Go deeper
plot.bar is the honest default and the better chart most of the time. value_counts produces the Series a pie wants, and its normalize=True gives you the proportions directly. groupby is how you get there from a column of numbers rather than categories.
More Pandas videos on Python and Pandas with Reuven Lerner.
Bamboo Weekly is the practice. If you want the structured version — full courses with downloadable Jupyter notebooks, plus live Pandas office hours when you get stuck — that is LernerPython+Data. A paid Bamboo Weekly subscription is included with it.
See it on real data
Below are the 9 Bamboo Weekly exercises that use plot.pie on real-world data — try each one, then study the worked solution.
- Bamboo Weekly #121: Research funding
- Bamboo Weekly #116: Philadelphia Fed survey
- Bamboo Weekly #107: Consumer confidence
- Bamboo Weekly #96: Taylor Swift
- Bamboo Weekly #94: Strategic Wine Reserve
- Bamboo Weekly #92: Climate disaster costs
- Bamboo Weekly #88: Hot summers
- Bamboo Weekly #87: Nuclear power
- Bamboo Weekly #74: UK elections
Part of the Pandas Methods Index. See also practice by skill.