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

Commite5db08a

Browse files
committed
ENH: add option to label pie charts with absolute values
1 parent183b04f commite5db08a

File tree

8 files changed

+132
-30
lines changed

8 files changed

+132
-30
lines changed
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
The *pctdistance* parameter of ``Axes.pie``
2+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3+
4+
... is deprecated. Please use *autodistance* instead.
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
Label pie charts with absolute input values
2+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3+
4+
Pie charts may now be automatically labelled with the original input values
5+
using the new *absolutefmt* parameter in `~.Axes.pie`.
6+
7+
..plot::
8+
:include-source: true
9+
:alt: Pie chart with each wedge labelled with its input value
10+
11+
import matplotlib.pyplot as plt
12+
13+
x = [4, 2, 1]
14+
15+
fig, ax = plt.subplots()
16+
ax.pie(x, absolutefmt='%d')
17+
18+
plt.show()

‎galleries/examples/pie_and_polar_charts/pie_and_donut_labels.py‎

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -38,17 +38,17 @@
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]
43+
total=np.sum(data)
4344

4445

45-
deffunc(pct,allvals):
46-
absolute=int(np.round(pct/100.*np.sum(allvals)))
47-
returnf"{pct:.1f}%\n({absolute:d} g)"
46+
deffunc(value):
47+
fraction=value/total
48+
returnf"{fraction:.1%}\n({value:d} g)"
4849

4950

50-
wedges,texts,autotexts=ax.pie(data,autopct=lambdapct:func(pct,data),
51-
textprops=dict(color="w"))
51+
wedges,texts,autotexts=ax.pie(data,absolutefmt=func,textprops=dict(color="w"))
5252

5353
ax.legend(wedges,ingredients,
5454
title="Ingredients",

‎galleries/examples/pie_and_polar_charts/pie_features.py‎

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -34,13 +34,19 @@
3434
# Auto-label slices
3535
# -----------------
3636
#
37-
# Pass a function or format string to *autopct* to label slices.
37+
# Pass a function or format string to *absolutefmt* to label slices with your
38+
# input values...
39+
40+
fig,ax=plt.subplots()
41+
ax.pie(sizes,labels=labels,absolutefmt='%d')
42+
43+
# %%
44+
# ...or to *autopct* to label slices with the percent sizes of the slice.
3845

3946
fig,ax=plt.subplots()
4047
ax.pie(sizes,labels=labels,autopct='%1.1f%%')
4148

4249
# %%
43-
# By default, the label values are obtained from the percent size of the slice.
4450
#
4551
# Color slices
4652
# ------------
@@ -63,15 +69,15 @@
6369
# %%
6470
# Swap label and autopct text positions
6571
# -------------------------------------
66-
# Use the *labeldistance* and *pctdistance* parameters to position the *labels*
72+
# Use the *labeldistance* and *autodistance* parameters to position the *labels*
6773
# and *autopct* text respectively.
6874

6975
fig,ax=plt.subplots()
7076
ax.pie(sizes,labels=labels,autopct='%1.1f%%',
71-
pctdistance=1.25,labeldistance=.6)
77+
autodistance=1.25,labeldistance=.6)
7278

7379
# %%
74-
# *labeldistance* and *pctdistance* are ratios of the radius; therefore they
80+
# *labeldistance* and *autodistance* are ratios of the radius; therefore they
7581
# vary between ``0`` for the center of the pie and ``1`` for the edge of the
7682
# pie, and can be set to greater than ``1`` to place text outside the pie.
7783
#

‎lib/matplotlib/axes/_axes.py‎

Lines changed: 53 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -3154,13 +3154,13 @@ def stem(self, *args, linefmt=None, markerfmt=None, basefmt=None, bottom=0,
31543154
self.add_container(stem_container)
31553155
returnstem_container
31563156

3157-
@_api.make_keyword_only("3.9","explode")
3157+
@_api.rename_parameter("3.11","pctdistance","autodistance")
31583158
@_preprocess_data(replace_names=["x","explode","labels","colors"])
3159-
defpie(self,x,explode=None,labels=None,colors=None,
3160-
autopct=None,pctdistance=0.6,shadow=False,labeldistance=1.1,
3159+
defpie(self,x,*,explode=None,labels=None,colors=None,absolutefmt=None,
3160+
autopct=None,autodistance=0.6,shadow=False,labeldistance=1.1,
31613161
startangle=0,radius=1,counterclock=True,
31623162
wedgeprops=None,textprops=None,center=(0,0),
3163-
frame=False,rotatelabels=False,*,normalize=True,hatch=None):
3163+
frame=False,rotatelabels=False,normalize=True,hatch=None):
31643164
"""
31653165
Plot a pie chart.
31663166
@@ -3193,18 +3193,38 @@ def pie(self, x, explode=None, labels=None, colors=None,
31933193
31943194
.. versionadded:: 3.7
31953195
3196+
absolutefmt : None or str or callable, default: None
3197+
If not *None*, *absolutefmt* is a string or function used to label
3198+
the wedges with their original numeric values. The label will be
3199+
placed according to *autodistance*. If *absolutefmt* is a format
3200+
string, the label will be ``fmt % number``. If *absolutefmt* is a
3201+
function, then it will be called. Cannot be used at the same time
3202+
as *autopct*.
3203+
3204+
.. versionadded:: 3.11
3205+
31963206
autopct : None or str or callable, default: None
31973207
If not *None*, *autopct* is a string or function used to label the
3198-
wedges with their numeric value. The label will be placed inside
3199-
the wedge. If *autopct* is a format string, the label will be
3200-
``fmt % pct``. If *autopct* is a function, then it will be called.
3208+
wedges with their percentage values. The label will be placed
3209+
according to *autodistance*. If *autopct* is a format string, the
3210+
label will be ``fmt % pct``. If *autopct* is a function, then it
3211+
will be called. Cannot be used at the same time as *absolutefmt*.
3212+
3213+
autodistance : float, default: 0.6
3214+
The relative distance along the radius at which the text
3215+
generated by *absolutefmt* or *autopct* is drawn. To draw the text
3216+
outside the pie, set *autodistance* > 1. This parameter is ignored
3217+
if both *absolutefmt* and *autopct* are ``None``.
32013218
32023219
pctdistance : float, default: 0.6
32033220
The relative distance along the radius at which the text
32043221
generated by *autopct* is drawn. To draw the text outside the pie,
32053222
set *pctdistance* > 1. This parameter is ignored if *autopct* is
32063223
``None``.
32073224
3225+
.. deprecated:: 3.11
3226+
Use *autodistance* instead.
3227+
32083228
labeldistance : float or None, default: 1.1
32093229
The relative distance along the radius at which the labels are
32103230
drawn. To draw the labels inside the pie, set *labeldistance* < 1.
@@ -3275,9 +3295,7 @@ def pie(self, x, explode=None, labels=None, colors=None,
32753295
The Axes aspect ratio can be controlled with `.Axes.set_aspect`.
32763296
"""
32773297
self.set_aspect('equal')
3278-
# The use of float32 is "historical", but can't be changed without
3279-
# regenerating the test baselines.
3280-
x=np.asarray(x,np.float32)
3298+
x=np.asarray(x)
32813299
ifx.ndim>1:
32823300
raiseValueError("x must be 1D")
32833301

@@ -3287,9 +3305,11 @@ def pie(self, x, explode=None, labels=None, colors=None,
32873305
sx=x.sum()
32883306

32893307
ifnormalize:
3290-
x=x/sx
3308+
fracs=x/sx
32913309
elifsx>1:
32923310
raiseValueError('Cannot plot an unnormalized pie with sum(x) > 1')
3311+
else:
3312+
fracs=x
32933313
iflabelsisNone:
32943314
labels= ['']*len(x)
32953315
ifexplodeisNone:
@@ -3324,7 +3344,7 @@ def get_next_color():
33243344
slices= []
33253345
autotexts= []
33263346

3327-
forfrac,label,explinzip(x,labels,explode):
3347+
forn,frac,label,explinzip(x,fracs,labels,explode):
33283348
x,y=center
33293349
theta2= (theta1+frac)ifcounterclockelse (theta1-frac)
33303350
thetam=2*np.pi*0.5* (theta1+theta2)
@@ -3369,15 +3389,33 @@ def get_next_color():
33693389
texts.append(t)
33703390

33713391
ifautopctisnotNone:
3372-
xt=x+pctdistance*radius*math.cos(thetam)
3373-
yt=y+pctdistance*radius*math.sin(thetam)
3392+
ifabsolutefmtisnotNone:
3393+
raiseValueError('Only one of autopct and absolutefmt may be used.')
33743394
ifisinstance(autopct,str):
33753395
s=autopct% (100.*frac)
33763396
elifcallable(autopct):
33773397
s=autopct(100.*frac)
33783398
else:
33793399
raiseTypeError(
33803400
'autopct must be callable or a format string')
3401+
autolabels=True
3402+
3403+
elifabsolutefmtisnotNone:
3404+
ifisinstance(absolutefmt,str):
3405+
s=absolutefmt%n
3406+
elifcallable(absolutefmt):
3407+
s=absolutefmt(n)
3408+
else:
3409+
raiseTypeError(
3410+
'absolutefmt must be callable or a format string')
3411+
autolabels=True
3412+
3413+
else:
3414+
autolabels=False
3415+
3416+
ifautolabels:
3417+
xt=x+autodistance*radius*math.cos(thetam)
3418+
yt=y+autodistance*radius*math.sin(thetam)
33813419
ifmpl._val_or_rc(textprops.get("usetex"),"text.usetex"):
33823420
# escape % (i.e. \%) if it is not already escaped
33833421
s=re.sub(r"([^\\])%",r"\1\\%",s)
@@ -3397,7 +3435,7 @@ def get_next_color():
33973435
xlim=(-1.25+center[0],1.25+center[0]),
33983436
ylim=(-1.25+center[1],1.25+center[1]))
33993437

3400-
ifautopctisNone:
3438+
ifnotautotexts:
34013439
returnslices,texts
34023440
else:
34033441
returnslices,texts,autotexts

‎lib/matplotlib/axes/_axes.pyi‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -299,8 +299,9 @@ class Axes(_AxesBase):
299299
explode:ArrayLike|None= ...,
300300
labels:Sequence[str]|None= ...,
301301
colors:ColorType|Sequence[ColorType]|None= ...,
302+
absolutefmt:str|Callable[[float],str]|None= ...,
302303
autopct:str|Callable[[float],str]|None= ...,
303-
pctdistance:float= ...,
304+
autodistance:float= ...,
304305
shadow:bool= ...,
305306
labeldistance:float|None= ...,
306307
startangle:float= ...,

‎lib/matplotlib/pyplot.py‎

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3772,11 +3772,13 @@ def phase_spectrum(
37723772
@_copy_docstring_and_deprecators(Axes.pie)
37733773
defpie(
37743774
x:ArrayLike,
3775+
*,
37753776
explode:ArrayLike|None=None,
37763777
labels:Sequence[str]|None=None,
37773778
colors:ColorType|Sequence[ColorType]|None=None,
3779+
absolutefmt:str|Callable[[float],str]|None=None,
37783780
autopct:str|Callable[[float],str]|None=None,
3779-
pctdistance:float=0.6,
3781+
autodistance:float=0.6,
37803782
shadow:bool=False,
37813783
labeldistance:float|None=1.1,
37823784
startangle:float=0,
@@ -3787,7 +3789,6 @@ def pie(
37873789
center:tuple[float,float]= (0,0),
37883790
frame:bool=False,
37893791
rotatelabels:bool=False,
3790-
*,
37913792
normalize:bool=True,
37923793
hatch:str|Sequence[str]|None=None,
37933794
data=None,
@@ -3797,8 +3798,9 @@ def pie(
37973798
explode=explode,
37983799
labels=labels,
37993800
colors=colors,
3801+
absolutefmt=absolutefmt,
38003802
autopct=autopct,
3801-
pctdistance=pctdistance,
3803+
autodistance=autodistance,
38023804
shadow=shadow,
38033805
labeldistance=labeldistance,
38043806
startangle=startangle,

‎lib/matplotlib/tests/test_axes.py‎

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5961,6 +5961,39 @@ def test_pie_default():
59615961
autopct='%1.1f%%',shadow=True,startangle=90)
59625962

59635963

5964+
deftest_pie_abs():
5965+
labels= ['Frogs','Hogs','Dogs','Logs']
5966+
sizes= [15,30,45,10]
5967+
fig1,ax1=plt.subplots(figsize=(8,6))
5968+
slices,texts,autotexts=ax1.pie(
5969+
sizes,labels=labels,absolutefmt='%d')
5970+
5971+
assert [txt.get_text()fortxtintexts]==labels
5972+
assert [txt.get_text()fortxtinautotexts]== [str(size)forsizeinsizes]
5973+
5974+
5975+
deftest_pie_abs_func():
5976+
labels= ['Frogs','Hogs','Dogs','Logs']
5977+
sizes= [15,30,45,10]
5978+
fig1,ax1=plt.subplots(figsize=(8,6))
5979+
5980+
defdouble(n):
5981+
returnn*2
5982+
5983+
slices,texts,autotexts=ax1.pie(
5984+
sizes,labels=labels,absolutefmt=double)
5985+
5986+
assert [txt.get_text()fortxtintexts]==labels
5987+
assert [txt.get_text()fortxtinautotexts]== [str(size*2)forsizeinsizes]
5988+
5989+
5990+
deftest_pie_both_number_formats():
5991+
sizes= [15,30,45,10]
5992+
fig1,ax1=plt.subplots(figsize=(8,6))
5993+
withpytest.raises(ValueError,match='Only one of autopct and absolutefmt'):
5994+
ax1.pie(sizes,absolutefmt='%d',autopct='%1.1f%%')
5995+
5996+
59645997
@image_comparison(['pie_linewidth_0','pie_linewidth_0','pie_linewidth_0'],
59655998
extensions=['png'],style='mpl20',tol=0.01)
59665999
deftest_pie_linewidth_0():

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp