Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitef69c49

Browse files
committed
ENH: add wedge_labels parameter for pie
1 parent9b61b47 commitef69c49

File tree

12 files changed

+557
-146
lines changed

12 files changed

+557
-146
lines changed
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
Return value of ``pie``
2+
~~~~~~~~~~~~~~~~~~~~~~~
3+
Previously, if no *labels* were passed to `~.Axes.pie`, and *labeldistance* was
4+
not ``None``, empty text labels would be added to the axes and returned. This
5+
is no longer the case. To continue creating empty labels, either pass an empty
6+
string with the new *wedge_labels* parameter ``wedge_labels=''`` or, for
7+
compatibility with older Matplotlib versions, pass an empty string for each wedge
8+
via the *labels* parameter, i.e. ``labels=[''] * number_of_wedges``. Note the
9+
latter option will stop working at Matplotlib 3.16.
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
``pie`` *labels* and *labeldistance* parameters
2+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3+
Currently the *labels* parameter of `~.Axes.pie` is used both for annotating the
4+
pie wedges directly, and for automatic legend entries. For consistency
5+
with other plotting methods, in future *labels* will only be used for the legend.
6+
7+
The *labeldistance* parameter will therefore default to ``None`` from Matplotlib
8+
3.14, when it will also be deprecated and then removed in Matplotlib 3.16. To
9+
preserve the existing behavior for now, set ``labeldistance=1.1``. For the longer
10+
term, use the new *wedge_labels* parameter of `~.Axes.pie` instead of *labels*.
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
New *wedge_labels* parameter for pie
2+
------------------------------------
3+
4+
`~.Axes.pie` now accepts a *wedge_labels* parameter which may be used to
5+
annotate the wedges of the pie chart. It can take
6+
7+
* a list of strings, similar to the existing *labels* parameter
8+
* a format string in analogy to the existing *autopct* parameter except that it
9+
uses the `str.format` method, and it can handle absolute values as well as
10+
fractions/percentages
11+
12+
To add multiple labels per wedge, *wedge_labels* can take a sequence of any combination
13+
of the above two options.
14+
15+
*wedge_labels* have accompanying *wedge_label_distance* and *rotate_wedge_labels*
16+
parameters, to customise the position and rotation of the labels.
17+
18+
For examples, see:doc:`/gallery/pie_and_polar_charts/pie_features`.

‎galleries/examples/misc/svg_filter_pie.py‎

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,11 +28,12 @@
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+
pies=ax.pie(fracs,explode=explode,wedge_labels=[labels,'{frac:.1%}'],
32+
wedge_label_distance=[1.1,0.6])
3233

33-
forwinpies[0]:
34+
forw,labelinzip(pies[0],labels):
3435
# set the id with the label.
35-
w.set_gid(w.get_label())
36+
w.set_gid(label)
3637

3738
# we don't want to draw the edge of the pie
3839
w.set_edgecolor("none")

‎galleries/examples/pie_and_polar_charts/bar_of_pie.py‎

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,9 @@
2525
explode= [0.1,0,0]
2626
# rotate so that first wedge is split by the x-axis
2727
angle=-180*overall_ratios[0]
28-
wedges,*_=ax1.pie(overall_ratios,autopct='%1.1f%%',startangle=angle,
29-
labels=labels,explode=explode)
28+
wedges,*_=ax1.pie(
29+
overall_ratios,startangle=angle,explode=explode,
30+
wedge_labels=[labels,'{frac:.1%}'],wedge_label_distance=[1.1,0.6])
3031

3132
# bar chart parameters
3233
age_ratios= [.33,.54,.07,.06]

‎galleries/examples/pie_and_polar_charts/pie_and_donut_labels.py‎

Lines changed: 8 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,9 @@
1515
# Now it's time for the pie. Starting with a pie recipe, we create the data
1616
# and a list of labels from it.
1717
#
18-
# We can provide afunctionto 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.
18+
# We can provide aformat stringto the*wedge_labels* parameter, to
19+
#automatically label each ingredient's wedge with its weight in grams and
20+
#percentages.
2121
#
2222
# We then create the pie and store the returned objects for later. The first
2323
# returned element of the returned tuple is a list of the wedges. Those are
@@ -31,32 +31,24 @@
3131
importmatplotlib.pyplotasplt
3232
importnumpyasnp
3333

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

3636
recipe= ["375 g flour",
3737
"75 g sugar",
3838
"250 g butter",
3939
"300 g berries"]
4040

41-
data= [float(x.split()[0])forxinrecipe]
41+
data= [int(x.split()[0])forxinrecipe]
4242
ingredients= [x.split()[-1]forxinrecipe]
4343

44-
45-
deffunc(pct,allvals):
46-
absolute=int(np.round(pct/100.*np.sum(allvals)))
47-
returnf"{pct:.1f}%\n({absolute:d} g)"
48-
49-
50-
wedges,texts,autotexts=ax.pie(data,autopct=lambdapct:func(pct,data),
51-
textprops=dict(color="w"))
44+
wedges,texts=ax.pie(data,wedge_labels='{frac:.1%}\n({absval:d}g)',
45+
textprops=dict(color="w",size=8,weight="bold"))
5246

5347
ax.legend(wedges,ingredients,
5448
title="Ingredients",
5549
loc="center left",
5650
bbox_to_anchor=(1,0,0.5,1))
5751

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

6254
plt.show()
@@ -97,7 +89,7 @@ def func(pct, allvals):
9789

9890
data= [225,90,50,60,100,5]
9991

100-
wedges,texts=ax.pie(data,wedgeprops=dict(width=0.5),startangle=-40)
92+
wedges,_=ax.pie(data,wedgeprops=dict(width=0.5),startangle=-40)
10193

10294
bbox_props=dict(boxstyle="square,pad=0.3",fc="w",ec="k",lw=0.72)
10395
kw=dict(arrowprops=dict(arrowstyle="-"),

‎galleries/examples/pie_and_polar_charts/pie_features.py‎

Lines changed: 50 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -15,40 +15,75 @@
1515
# ------------
1616
#
1717
# Plot a pie chart of animals and label the slices. To add
18-
# labels, pass a list of labels to the *labels* parameter
18+
# labels, pass a list of labels to the *wedge_labels* parameter.
1919

2020
importmatplotlib.pyplotasplt
2121

2222
labels='Frogs','Hogs','Dogs','Logs'
23-
sizes= [15,30,45,10]
23+
sizes= [12,24,36,8]
2424

2525
fig,ax=plt.subplots()
26-
ax.pie(sizes,labels=labels)
26+
ax.pie(sizes,wedge_labels=labels)
2727

2828
# %%
2929
# Each slice of the pie chart is a `.patches.Wedge` object; therefore in
3030
# addition to the customizations shown here, each wedge can be customized using
3131
# the *wedgeprops* argument, as demonstrated in
3232
# :doc:`/gallery/pie_and_polar_charts/nested_pie`.
3333
#
34+
# Controlling label positions
35+
# ---------------------------
36+
# If you want the labels outside the pie, set a *wedge_label_distance* greater than 1.
37+
# This is the distance from the center of the pie as a fraction of its radius.
38+
39+
fig,ax=plt.subplots()
40+
ax.pie(sizes,wedge_labels=labels,wedge_label_distance=1.1)
41+
42+
# %%
43+
#
3444
# Auto-label slices
3545
# -----------------
3646
#
37-
# Pass a function or format string to *autopct* to label slices.
47+
# Pass a format string to *wedge_labels* to label slices with their values...
48+
49+
fig,ax=plt.subplots()
50+
ax.pie(sizes,wedge_labels='{absval:.1f}')
51+
52+
# %%
53+
#
54+
# ...or with their percentages...
55+
56+
fig,ax=plt.subplots()
57+
ax.pie(sizes,wedge_labels='{frac:.1%}')
58+
59+
# %%
60+
#
61+
# ...or both.
3862

3963
fig,ax=plt.subplots()
40-
ax.pie(sizes,labels=labels,autopct='%1.1f%%')
64+
ax.pie(sizes,wedge_labels='{absval:d}\n{frac:.1%}')
65+
66+
67+
# %%
68+
#
69+
# Multiple labels
70+
# ---------------
71+
#
72+
# Pass both a list of labels and a format string to *wedge_labels*, with a
73+
# corresponding *wedge_label_distance* for each.
74+
75+
fig,ax=plt.subplots()
76+
ax.pie(sizes,wedge_labels=[labels,'{frac:.1%}'],wedge_label_distance=[1.1,0.6])
4177

4278
# %%
43-
# By default, the label values are obtained from the percent size of the slice.
4479
#
4580
# Color slices
4681
# ------------
4782
#
4883
# Pass a list of colors to *colors* to set the color of each slice.
4984

5085
fig,ax=plt.subplots()
51-
ax.pie(sizes,labels=labels,
86+
ax.pie(sizes,wedge_labels=labels,wedge_label_distance=1.1,
5287
colors=['olivedrab','rosybrown','gray','saddlebrown'])
5388

5489
# %%
@@ -58,22 +93,10 @@
5893
# Pass a list of hatch patterns to *hatch* to set the pattern of each slice.
5994

6095
fig,ax=plt.subplots()
61-
ax.pie(sizes,labels=labels,hatch=['**O','oO','O.O','.||.'])
62-
63-
# %%
64-
# Swap label and autopct text positions
65-
# -------------------------------------
66-
# Use the *labeldistance* and *pctdistance* parameters to position the *labels*
67-
# and *autopct* text respectively.
68-
69-
fig,ax=plt.subplots()
70-
ax.pie(sizes,labels=labels,autopct='%1.1f%%',
71-
pctdistance=1.25,labeldistance=.6)
96+
ax.pie(sizes,wedge_labels=labels,wedge_label_distance=1.1,
97+
hatch=['**O','oO','O.O','.||.'])
7298

7399
# %%
74-
# *labeldistance* and *pctdistance* are ratios of the radius; therefore they
75-
# vary between ``0`` for the center of the pie and ``1`` for the edge of the
76-
# pie, and can be set to greater than ``1`` to place text outside the pie.
77100
#
78101
# Explode, shade, and rotate slices
79102
# ---------------------------------
@@ -89,8 +112,8 @@
89112
explode= (0,0.1,0,0)# only "explode" the 2nd slice (i.e. 'Hogs')
90113

91114
fig,ax=plt.subplots()
92-
ax.pie(sizes,explode=explode,labels=labels,autopct='%1.1f%%',
93-
shadow=True,startangle=90)
115+
ax.pie(sizes,explode=explode,wedge_labels=[labels,'{frac:.1%}'],
116+
wedge_label_distance=[1.1,0.6],shadow=True,startangle=90)
94117
plt.show()
95118

96119
# %%
@@ -107,7 +130,8 @@
107130

108131
fig,ax=plt.subplots()
109132

110-
ax.pie(sizes,labels=labels,autopct='%.0f%%',
133+
ax.pie(sizes,wedge_labels=[labels,'{frac:.1%}'],
134+
wedge_label_distance=[1.1,0.6],
111135
textprops={'size':'small'},radius=0.5)
112136
plt.show()
113137

@@ -119,7 +143,8 @@
119143
# the `.Shadow` patch. This can be used to modify the default shadow.
120144

121145
fig,ax=plt.subplots()
122-
ax.pie(sizes,explode=explode,labels=labels,autopct='%1.1f%%',
146+
ax.pie(sizes,explode=explode,wedge_labels=[labels,'{frac:.1%}'],
147+
wedge_label_distance=[1.1,0.6],
123148
shadow={'ox':-0.04,'edgecolor':'none','shade':0.9},startangle=90)
124149
plt.show()
125150

‎lib/matplotlib/__init__.py‎

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1429,7 +1429,8 @@ def _add_data_doc(docstring, replace_names):
14291429
returndocstring.replace(' DATA_PARAMETER_PLACEHOLDER',data_doc)
14301430

14311431

1432-
def_preprocess_data(func=None,*,replace_names=None,label_namer=None):
1432+
def_preprocess_data(func=None,*,replace_names=None,replace_names_multi=None,
1433+
label_namer=None):
14331434
"""
14341435
A decorator to add a 'data' kwarg to a function.
14351436
@@ -1454,6 +1455,11 @@ def func(ax, *args, **kwargs): ...
14541455
replace_names : list of str or None, default: None
14551456
The list of parameter names for which lookup into *data* should be
14561457
attempted. If None, replacement is attempted for all arguments.
1458+
replace_names_multi : list of str or None, default: None
1459+
As for *replace_names*, but if a sequence is passed, a lookup into *data*
1460+
will be attempted for each element of the sequence. Currently only
1461+
supported for parameters named in the function signature (not those passed via
1462+
*args or **kwargs).
14571463
label_namer : str, default: None
14581464
If set e.g. to "namer" (which must be a kwarg in the function's
14591465
signature -- not as ``**kwargs``), if the *namer* argument passed in is
@@ -1471,7 +1477,8 @@ def func(foo, label=None): ...
14711477
iffuncisNone:# Return the actual decorator.
14721478
returnfunctools.partial(
14731479
_preprocess_data,
1474-
replace_names=replace_names,label_namer=label_namer)
1480+
replace_names=replace_names,replace_names_multi=replace_names_multi,
1481+
label_namer=label_namer)
14751482

14761483
sig=inspect.signature(func)
14771484
varargs_name=None
@@ -1523,6 +1530,9 @@ def inner(ax, *args, data=None, **kwargs):
15231530
else:
15241531
ifreplace_namesisNoneorkinreplace_names:
15251532
bound.arguments[k]=_replacer(data,v)
1533+
if (replace_names_multiisnotNoneandkinreplace_names_multiand
1534+
notcbook.is_scalar_or_string(v)):
1535+
bound.arguments[k]= [_replacer(data,vi)forviinv]
15261536

15271537
new_args=bound.args
15281538
new_kwargs=bound.kwargs

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp