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

Commitec2952a

Browse files
committed
WIP
1 parent677d990 commitec2952a

File tree

7 files changed

+292
-113
lines changed

7 files changed

+292
-113
lines changed

‎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,
32+
wedge_labels=[labels,'{frac:.1%}'],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: 5 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -38,25 +38,16 @@
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+
ax.pie(data,wedge_labels='{frac:.1%}\n({abs:d}g)',labels=ingredients,
45+
labeldistance=None,textprops=dict(color="w",size=8,weight="bold"))
4446

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"))
52-
53-
ax.legend(wedges,ingredients,
54-
title="Ingredients",
47+
ax.legend(title="Ingredients",
5548
loc="center left",
5649
bbox_to_anchor=(1,0,0.5,1))
5750

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

6253
plt.show()
@@ -97,7 +88,7 @@ def func(pct, allvals):
9788

9889
data= [225,90,50,60,100,5]
9990

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

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

‎lib/matplotlib/axes/_axes.py

Lines changed: 182 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
importcollections.abc
12
importfunctools
23
importitertools
34
importlogging
@@ -3200,13 +3201,12 @@ def stem(self, *args, linefmt=None, markerfmt=None, basefmt=None, bottom=0,
32003201
self.add_container(stem_container)
32013202
returnstem_container
32023203

3203-
@_api.make_keyword_only("3.9","explode")
32043204
@_preprocess_data(replace_names=["x","explode","labels","colors"])
3205-
defpie(self,x,explode=None,labels=None,colors=None,
3206-
autopct=None,pctdistance=0.6,shadow=False,labeldistance=1.1,
3207-
startangle=0,radius=1,counterclock=True,
3208-
wedgeprops=None,textprops=None,center=(0,0),
3209-
frame=False,rotatelabels=False,*,normalize=True,hatch=None):
3205+
defpie(self,x,*,explode=None,labels=None,colors=None,wedge_labels=None,
3206+
wedge_label_distance=0.6,rotate_wedge_labels=False,autopct=None,
3207+
pctdistance=0.6,shadow=False,labeldistance=False,startangle=0,radius=1,
3208+
counterclock=True,wedgeprops=None,textprops=None,center=(0,0),
3209+
frame=False,rotatelabels=False,normalize=True,hatch=None):
32103210
"""
32113211
Plot a pie chart.
32123212
@@ -3239,6 +3239,8 @@ def pie(self, x, explode=None, labels=None, colors=None,
32393239
32403240
.. versionadded:: 3.7
32413241
3242+
wedge_labels :
3243+
32423244
autopct : None or str or callable, default: None
32433245
If not *None*, *autopct* is a string or function used to label the
32443246
wedges with their numeric value. The label will be placed inside
@@ -3321,9 +3323,7 @@ def pie(self, x, explode=None, labels=None, colors=None,
33213323
The Axes aspect ratio can be controlled with `.Axes.set_aspect`.
33223324
"""
33233325
self.set_aspect('equal')
3324-
# The use of float32 is "historical", but can't be changed without
3325-
# regenerating the test baselines.
3326-
x=np.asarray(x,np.float32)
3326+
x=np.asarray(x)
33273327
ifx.ndim>1:
33283328
raiseValueError("x must be 1D")
33293329

@@ -3332,18 +3332,19 @@ def pie(self, x, explode=None, labels=None, colors=None,
33323332

33333333
sx=x.sum()
33343334

3335+
defcheck_length(name,values):
3336+
iflen(values)!=len(x):
3337+
raiseValueError(f"'{name}' must be of length 'x', not{len(values)}")
3338+
33353339
ifnormalize:
3336-
x=x/sx
3340+
fracs=x/sx
33373341
elifsx>1:
33383342
raiseValueError('Cannot plot an unnormalized pie with sum(x) > 1')
3339-
iflabelsisNone:
3340-
labels=['']*len(x)
3343+
else:
3344+
fracs=x
33413345
ifexplodeisNone:
33423346
explode= [0]*len(x)
3343-
iflen(x)!=len(labels):
3344-
raiseValueError(f"'labels' must be of length 'x', not{len(labels)}")
3345-
iflen(x)!=len(explode):
3346-
raiseValueError(f"'explode' must be of length 'x', not{len(explode)}")
3347+
check_length("explode",explode)
33473348
ifcolorsisNone:
33483349
get_next_color=self._get_patches_for_fill.get_next_color
33493350
else:
@@ -3366,18 +3367,147 @@ def get_next_color():
33663367
iftextpropsisNone:
33673368
textprops= {}
33683369

3369-
texts= []
33703370
slices= []
33713371
autotexts= []
33723372

3373-
forfrac,label,explinzip(x,labels,explode):
3374-
x,y=center
3373+
# Define some functions for choosing label fontize and horizontal alignment
3374+
# based on distance and whether we are right of center (i.e. cartesian x > 0)
3375+
3376+
deflegacy(distance,is_right):
3377+
# Used to place `labels`. This function can be removed when the
3378+
# `labeldistance` deprecation expires. Always align so the labels
3379+
# do not overlap the pie
3380+
ha='left'ifis_rightelse'right'
3381+
returnmpl.rcParams['xtick.labelsize'],ha
3382+
3383+
defflexible(distance,is_right):
3384+
ifdistance>=1:
3385+
# Align so the labels do not overlap the pie
3386+
ha='left'ifis_rightelse'right'
3387+
else:
3388+
ha='center'
3389+
3390+
returnNone,ha
3391+
3392+
deffixed(distance,is_right):
3393+
# Used to place the labels generated with autopct. Always centered
3394+
# for backwards compatibility
3395+
returnNone,'center'
3396+
3397+
# Build a (possibly empty) list of lists of wedge labels, with corresponding
3398+
# lists of distances, rotation choices and alignment functions
3399+
3400+
defsanitize_formatted_string(s):
3401+
ifmpl._val_or_rc(textprops.get("usetex"),"text.usetex"):
3402+
# escape % (i.e. \%) if it is not already escaped
3403+
returnre.sub(r"([^\\])%",r"\1\\%",s)
3404+
3405+
returns
3406+
3407+
deffmt_str_to_list(wl):
3408+
return [sanitize_formatted_string(wl.format(abs=absval,frac=frac))
3409+
forabsval,fracinzip(x,fracs)]
3410+
3411+
ifwedge_labelsisNone:
3412+
processed_wedge_labels= []
3413+
wedge_label_distance= []
3414+
rotate_wedge_labels= []
3415+
elifisinstance(wedge_labels,str):
3416+
# Format string.
3417+
processed_wedge_labels= [fmt_str_to_list(wedge_labels)]
3418+
elifnotisinstance(wedge_labels,collections.abc.Sequence):
3419+
raiseTypeError("wedge_labels must be a string or sequence")
3420+
else:
3421+
wl0=wedge_labels[0]
3422+
ifisinstance(wl0,str)andwl0.format(abs=1,frac=1)==wl0:
3423+
# Plain string. Assume we have a sequence of ready-made labels
3424+
check_length("wedge_labels",wedge_labels)
3425+
processed_wedge_labels= [wedge_labels]
3426+
else:
3427+
processed_wedge_labels= []
3428+
forwlinwedge_labels:
3429+
ifisinstance(wl,str):
3430+
# Format string
3431+
processed_wedge_labels.append(fmt_str_to_list(wl))
3432+
else:
3433+
# Ready made list
3434+
check_length("wedge_labels[i]",wl)
3435+
processed_wedge_labels.append(wl)
3436+
3437+
ifisinstance(wedge_label_distance,Number):
3438+
wedge_label_distance= [wedge_label_distance]
3439+
else:
3440+
# Copy so we won't append to user input
3441+
wedge_label_distance=wedge_label_distance[:]
3442+
3443+
n_label_sets=len(processed_wedge_labels)
3444+
ifn_label_sets!= (nd:=len(wedge_label_distance)):
3445+
raiseValueError(f"Found{n_label_sets} sets of wedge labels but "
3446+
f"{nd} wedge label distances.")
3447+
3448+
ifisinstance(rotate_wedge_labels,bool):
3449+
rotate_wedge_labels= [rotate_wedge_labels]
3450+
else:
3451+
# Copy so we won't append to user input
3452+
rotate_wedge_labels=rotate_wedge_labels[:]
3453+
3454+
iflen(rotate_wedge_labels)==1:
3455+
rotate_wedge_labels=rotate_wedge_labels*n_label_sets
3456+
elifn_label_sets!= (nr:=len(rotate_wedge_labels)):
3457+
raiseValueError(f"Found{n_label_sets} sets of wedge labels but "
3458+
f"{nr} wedge label rotation choices.")
3459+
3460+
prop_funcs= [flexible]*n_label_sets
3461+
3462+
iflabelsisNone:
3463+
labels= [None]*len(x)
3464+
else:
3465+
check_length("labels",labels)
3466+
3467+
ifnotlabeldistanceandlabeldistanceisFalse:
3468+
msg= ("In future labeldistance will default to None. To preserve "
3469+
"existing behavior, pass labeldistance=1.1. Consider using "
3470+
"wedge_labels instead of labels.")
3471+
_api.warn_deprecated("3.11",message=msg)
3472+
labeldistance=1.1
3473+
3474+
iflabeldistanceisnotNone:
3475+
processed_wedge_labels.append(labels)
3476+
wedge_label_distance.append(labeldistance)
3477+
prop_funcs.append(legacy)
3478+
rotate_wedge_labels.append(rotatelabels)
3479+
3480+
wedgetexts= [[]]*len(processed_wedge_labels)
3481+
3482+
ifautopctisnotNone:
3483+
ifisinstance(autopct,str):
3484+
processed_pct= [sanitize_formatted_string(autopct% (100.*frac))
3485+
forfracinfracs]
3486+
elifcallable(autopct):
3487+
processed_pct= [sanitize_formatted_string(autopct(100.*frac))
3488+
forfracinfracs]
3489+
else:
3490+
raiseTypeError('autopct must be callable or a format string')
3491+
3492+
processed_wedge_labels.append(processed_pct)
3493+
wedge_label_distance.append(pctdistance)
3494+
prop_funcs.append(fixed)
3495+
rotate_wedge_labels.append(False)
3496+
3497+
# Transpose so we can loop over wedges
3498+
processed_wedge_labels=np.transpose(processed_wedge_labels)
3499+
ifnotprocessed_wedge_labels.size:
3500+
processed_wedge_labels=processed_wedge_labels.reshape(len(x),0)
3501+
3502+
forfrac,label,expl,wlsinzip(fracs,labels,explode,
3503+
processed_wedge_labels):
3504+
x_pos,y_pos=center
33753505
theta2= (theta1+frac)ifcounterclockelse (theta1-frac)
33763506
thetam=2*np.pi*0.5* (theta1+theta2)
3377-
x+=expl*math.cos(thetam)
3378-
y+=expl*math.sin(thetam)
3507+
x_pos+=expl*math.cos(thetam)
3508+
y_pos+=expl*math.sin(thetam)
33793509

3380-
w=mpatches.Wedge((x,y),radius,360.*min(theta1,theta2),
3510+
w=mpatches.Wedge((x_pos,y_pos),radius,360.*min(theta1,theta2),
33813511
360.*max(theta1,theta2),
33823512
facecolor=get_next_color(),
33833513
hatch=next(hatch_cycle),
@@ -3395,44 +3525,31 @@ def get_next_color():
33953525
shadow_dict.update(shadow)
33963526
self.add_patch(mpatches.Shadow(w,**shadow_dict))
33973527

3398-
iflabeldistanceisnotNone:
3399-
xt=x+labeldistance*radius*math.cos(thetam)
3400-
yt=y+labeldistance*radius*math.sin(thetam)
3401-
label_alignment_h='left'ifxt>0else'right'
3402-
label_alignment_v='center'
3403-
label_rotation='horizontal'
3404-
ifrotatelabels:
3405-
label_alignment_v='bottom'ifyt>0else'top'
3406-
label_rotation= (np.rad2deg(thetam)
3407-
+ (0ifxt>0else180))
3408-
t=self.text(xt,yt,label,
3409-
clip_on=False,
3410-
horizontalalignment=label_alignment_h,
3411-
verticalalignment=label_alignment_v,
3412-
rotation=label_rotation,
3413-
size=mpl.rcParams['xtick.labelsize'])
3414-
t.set(**textprops)
3415-
texts.append(t)
3416-
3417-
ifautopctisnotNone:
3418-
xt=x+pctdistance*radius*math.cos(thetam)
3419-
yt=y+pctdistance*radius*math.sin(thetam)
3420-
ifisinstance(autopct,str):
3421-
s=autopct% (100.*frac)
3422-
elifcallable(autopct):
3423-
s=autopct(100.*frac)
3424-
else:
3425-
raiseTypeError(
3426-
'autopct must be callable or a format string')
3427-
ifmpl._val_or_rc(textprops.get("usetex"),"text.usetex"):
3428-
# escape % (i.e. \%) if it is not already escaped
3429-
s=re.sub(r"([^\\])%",r"\1\\%",s)
3430-
t=self.text(xt,yt,s,
3431-
clip_on=False,
3432-
horizontalalignment='center',
3433-
verticalalignment='center')
3434-
t.set(**textprops)
3435-
autotexts.append(t)
3528+
ifwls.size>0:
3529+
# Add wedge labels
3530+
fori, (wl,ld,pf,rot)inenumerate(
3531+
zip(wls,wedge_label_distance,prop_funcs,
3532+
rotate_wedge_labels)):
3533+
xt=x_pos+ld*radius*math.cos(thetam)
3534+
yt=y_pos+ld*radius*math.sin(thetam)
3535+
fontsize,label_alignment_h=pf(ld,xt>0)
3536+
label_alignment_v='center'
3537+
label_rotation='horizontal'
3538+
ifrot:
3539+
label_alignment_v='bottom'ifyt>0else'top'
3540+
label_rotation= (np.rad2deg(thetam)+ (0ifxt>0else180))
3541+
t=self.text(xt,yt,wl,
3542+
clip_on=False,
3543+
horizontalalignment=label_alignment_h,
3544+
verticalalignment=label_alignment_v,
3545+
rotation=label_rotation,
3546+
size=fontsize)
3547+
t.set(**textprops)
3548+
ifi==len(wedgetexts):
3549+
# autopct texts are returned separately
3550+
autotexts.append(t)
3551+
else:
3552+
wedgetexts[i].append(t)
34363553

34373554
theta1=theta2
34383555

@@ -3443,10 +3560,13 @@ def get_next_color():
34433560
xlim=(-1.25+center[0],1.25+center[0]),
34443561
ylim=(-1.25+center[1],1.25+center[1]))
34453562

3563+
iflen(wedgetexts)==1:
3564+
wedgetexts=wedgetexts[0]
3565+
34463566
ifautopctisNone:
3447-
returnslices,texts
3567+
returnslices,wedgetexts
34483568
else:
3449-
returnslices,texts,autotexts
3569+
returnslices,wedgetexts,autotexts
34503570

34513571
@staticmethod
34523572
def_errorevery_to_mask(x,errorevery):

‎lib/matplotlib/axes/_axes.pyi

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -299,6 +299,9 @@ class Axes(_AxesBase):
299299
explode:ArrayLike|None= ...,
300300
labels:Sequence[str]|None= ...,
301301
colors:ColorType|Sequence[ColorType]|None= ...,
302+
wedge_labels:str|Sequence|None= ...,
303+
wedge_label_distance:float|Sequence= ...,
304+
rotate_wedge_labels:bool|Sequence= ...,
302305
autopct:str|Callable[[float],str]|None= ...,
303306
pctdistance:float= ...,
304307
shadow:bool= ...,

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp