Skip to content

Commit a97c665

Browse files
committed
ENH: introduce PieContainer and pie_label method
1 parent 86a476d commit a97c665

File tree

14 files changed

+506
-88
lines changed

14 files changed

+506
-88
lines changed

doc/api/axes_api.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ Basic
7373
Axes.eventplot
7474

7575
Axes.pie
76+
Axes.pie_label
7677

7778
Axes.stackplot
7879

doc/api/pyplot_summary.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ Basic
6464
stem
6565
eventplot
6666
pie
67+
pie_label
6768
stackplot
6869
broken_barh
6970
vlines
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
Adding labels to pie chart wedges
2+
---------------------------------
3+
4+
The new `~.Axes.pie_label` method adds a label to each wedge in a pie chart created with
5+
`~.Axes.pie`. It can take
6+
7+
* a list of strings, similar to the existing *labels* parameter of `~.Axes.pie`
8+
* a format string similar to the existing *autopct* parameter of `~.Axes.pie` except
9+
that it uses the `str.format` method and it can handle absolute values as well as
10+
fractions/percentages
11+
12+
For more examples, see :doc:`/gallery/pie_and_polar_charts/pie_label`.
13+
14+
.. plot::
15+
:include-source: true
16+
:alt: A pie chart with three labels on each wedge, showing a food type, number, and fraction associated with the wedge.
17+
18+
import matplotlib.pyplot as plt
19+
20+
data = [36, 24, 8, 12]
21+
labels = ['spam', 'eggs', 'bacon', 'sausage']
22+
23+
fig, ax = plt.subplots()
24+
pie = ax.pie(data)
25+
26+
ax.pie_label(pie, labels, distance=1.1)
27+
ax.pie_label(pie, '{frac:.1%}', distance=0.7)
28+
ax.pie_label(pie, '{absval:d}', distance=0.4)

galleries/examples/misc/svg_filter_pie.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,16 +28,16 @@
2828

2929
# We want to draw the shadow for each pie, but we will not use "shadow"
3030
# option as it doesn't save the references to the shadow patches.
31-
pies = ax.pie(fracs, explode=explode, labels=labels, autopct='%1.1f%%')
31+
pie = ax.pie(fracs, explode=explode, labels=labels, autopct='%1.1f%%')
3232

33-
for w in pies[0]:
33+
for w in pie.wedges:
3434
# set the id with the label.
3535
w.set_gid(w.get_label())
3636

3737
# we don't want to draw the edge of the pie
3838
w.set_edgecolor("none")
3939

40-
for w in pies[0]:
40+
for w in pie.wedges:
4141
# create shadow patch
4242
s = Shadow(w, -0.01, -0.01)
4343
s.set_gid(w.get_gid() + "_shadow")

galleries/examples/pie_and_polar_charts/pie_and_donut_labels.py

Lines changed: 18 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@
66
Welcome to the Matplotlib bakery. We will create a pie and a donut
77
chart through the `pie method <matplotlib.axes.Axes.pie>` and
88
show how to label them with a `legend <matplotlib.axes.Axes.legend>`
9-
as well as with `annotations <matplotlib.axes.Axes.annotate>`.
9+
as well as with the `pie_label method <matplotlib.axes.Axes.pie>` and
10+
`annotations <matplotlib.axes.Axes.annotate>`.
1011
"""
1112

1213
# %%
@@ -15,12 +16,14 @@
1516
# Now it's time for the pie. Starting with a pie recipe, we create the data
1617
# and a list of labels from it.
1718
#
18-
# We can provide a function to the ``autopct`` argument, which will expand
19-
# automatic percentage labeling by showing absolute values; we calculate
20-
# the latter back from relative data and the known sum of all values.
19+
# We then create the pie and store the returned `~matplotlib.container.PieContainer`
20+
# object for later.
2121
#
22-
# We then create the pie and store the returned objects for later. The first
23-
# returned element of the returned tuple is a list of the wedges. Those are
22+
# We can provide the `~matplotlib.container.PieContainer` and a format string to
23+
# the `~matplotlib.axes.Axes.pie_label` method to automatically label each
24+
# ingredient's wedge with its weight in grams and percentages.
25+
#
26+
# The `~.PieContainer` has a list of patches as one of its attributes. Those are
2427
# `matplotlib.patches.Wedge` patches, which can directly be used as the handles
2528
# for a legend. We can use the legend's ``bbox_to_anchor`` argument to position
2629
# the legend outside of the pie. Here we use the axes coordinates ``(1, 0, 0.5,
@@ -31,32 +34,26 @@
3134
import matplotlib.pyplot as plt
3235
import numpy as np
3336

34-
fig, ax = plt.subplots(figsize=(6, 3), subplot_kw=dict(aspect="equal"))
37+
fig, ax = plt.subplots(figsize=(6, 3))
3538

3639
recipe = ["375 g flour",
3740
"75 g sugar",
3841
"250 g butter",
3942
"300 g berries"]
4043

41-
data = [float(x.split()[0]) for x in recipe]
44+
data = [int(x.split()[0]) for x in recipe]
4245
ingredients = [x.split()[-1] for x in recipe]
4346

47+
pie = ax.pie(data)
4448

45-
def func(pct, allvals):
46-
absolute = int(np.round(pct/100.*np.sum(allvals)))
47-
return f"{pct:.1f}%\n({absolute:d} g)"
48-
49+
ax.pie_label(pie, '{frac:.1%}\n({absval:d}g)',
50+
textprops=dict(color="w", size=8, weight="bold"))
4951

50-
wedges, texts, autotexts = ax.pie(data, autopct=lambda pct: func(pct, data),
51-
textprops=dict(color="w"))
52-
53-
ax.legend(wedges, ingredients,
52+
ax.legend(pie.wedges, ingredients,
5453
title="Ingredients",
5554
loc="center left",
5655
bbox_to_anchor=(1, 0, 0.5, 1))
5756

58-
plt.setp(autotexts, size=8, weight="bold")
59-
6057
ax.set_title("Matplotlib bakery: A pie")
6158

6259
plt.show()
@@ -97,13 +94,13 @@ def func(pct, allvals):
9794

9895
data = [225, 90, 50, 60, 100, 5]
9996

100-
wedges, texts = ax.pie(data, wedgeprops=dict(width=0.5), startangle=-40)
97+
pie = ax.pie(data, wedgeprops=dict(width=0.5), startangle=-40)
10198

10299
bbox_props = dict(boxstyle="square,pad=0.3", fc="w", ec="k", lw=0.72)
103100
kw = dict(arrowprops=dict(arrowstyle="-"),
104101
bbox=bbox_props, zorder=0, va="center")
105102

106-
for i, p in enumerate(wedges):
103+
for i, p in enumerate(pie.wedges):
107104
ang = (p.theta2 - p.theta1)/2. + p.theta1
108105
y = np.sin(np.deg2rad(ang))
109106
x = np.cos(np.deg2rad(ang))
@@ -131,6 +128,7 @@ def func(pct, allvals):
131128
# in this example:
132129
#
133130
# - `matplotlib.axes.Axes.pie` / `matplotlib.pyplot.pie`
131+
# - `matplotlib.axes.Axes.pie_label` / `matplotlib.pyplot.pie_label`
134132
# - `matplotlib.axes.Axes.legend` / `matplotlib.pyplot.legend`
135133
#
136134
# .. tags::
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
"""
2+
===================
3+
Labeling pie charts
4+
===================
5+
6+
This example illustrates some features of the `~matplotlib.axes.Axes.pie_label`
7+
method, which adds labels to an existing pie chart created with
8+
`~matplotlib.axes.Axes.pie`.
9+
"""
10+
11+
# %%
12+
# The simplest option is to provide a list of strings to label each slice of the pie.
13+
14+
import matplotlib.pyplot as plt
15+
16+
data = [36, 24, 8, 12]
17+
labels = ['spam', 'eggs', 'bacon', 'sausage']
18+
19+
fig, ax = plt.subplots()
20+
pie = ax.pie(data)
21+
ax.pie_label(pie, labels)
22+
23+
# %%
24+
#
25+
# If you want the labels outside the pie, set a *distance* greater than 1.
26+
# This is the distance from the center of the pie as a fraction of its radius.
27+
28+
fig, ax = plt.subplots()
29+
pie = ax.pie(data)
30+
ax.pie_label(pie, labels, distance=1.1)
31+
32+
# %%
33+
#
34+
# You can also rotate the labels so they are oriented away from the pie center.
35+
36+
fig, ax = plt.subplots()
37+
pie = ax.pie(data)
38+
ax.pie_label(pie, labels, rotate=True)
39+
40+
# %%
41+
#
42+
# Instead of explicit labels, pass a format string to label slices with their values...
43+
44+
fig, ax = plt.subplots()
45+
pie = ax.pie(data)
46+
ax.pie_label(pie, '{absval:.1f}')
47+
48+
# %%
49+
#
50+
# ...or with their percentages...
51+
52+
fig, ax = plt.subplots()
53+
pie = ax.pie(data)
54+
ax.pie_label(pie, '{frac:.1%}')
55+
56+
# %%
57+
#
58+
# ...or both.
59+
60+
fig, ax = plt.subplots()
61+
pie = ax.pie(data)
62+
ax.pie_label(pie, '{absval:d}\n{frac:.1%}')
63+
64+
# %%
65+
#
66+
# Font styling can be configured by passing a dictionary to the *textprops* parameter.
67+
68+
fig, ax = plt.subplots()
69+
pie = ax.pie(data)
70+
ax.pie_label(pie, labels, textprops={'fontsize': 'large', 'color': 'white'})
71+
72+
# %%
73+
#
74+
# `~matplotlib.axes.Axes.pie_label` can be called repeatedly to add multiple sets
75+
# of labels.
76+
77+
# sphinx_gallery_thumbnail_number = -1
78+
79+
fig, ax = plt.subplots()
80+
pie = ax.pie(data)
81+
82+
ax.pie_label(pie, labels, distance=1.1)
83+
ax.pie_label(pie, '{frac:.1%}', distance=0.7)
84+
ax.pie_label(pie, '{absval:d}', distance=0.4)
85+
86+
plt.show()
87+
88+
# %%
89+
# .. admonition:: References
90+
#
91+
# The use of the following functions, methods, classes and modules is shown
92+
# in this example:
93+
#
94+
# - `matplotlib.axes.Axes.pie` / `matplotlib.pyplot.pie`
95+
# - `matplotlib.axes.Axes.pie_label` / `matplotlib.pyplot.pie_label`
96+
#
97+
# .. tags::
98+
#
99+
# plot-type: pie
100+
# level: beginner

0 commit comments

Comments
 (0)