Skip to content

Commit 8fec6ea

Browse files
authored
Merge pull request matplotlib#20515 from anntzer/bxp
Shorten the implementation of bxp().
2 parents c61077a + 68c6964 commit 8fec6ea

File tree

1 file changed

+48
-94
lines changed

1 file changed

+48
-94
lines changed

lib/matplotlib/axes/_axes.py

Lines changed: 48 additions & 94 deletions
Original file line numberDiff line numberDiff line change
@@ -3746,7 +3746,7 @@ def boxplot(self, x, notch=None, sym=None, vert=None, whis=None,
37463746

37473747
# if non-default sym value, put it into the flier dictionary
37483748
# the logic for providing the default symbol ('b+') now lives
3749-
# in bxp in the initial value of final_flierprops
3749+
# in bxp in the initial value of flierkw
37503750
# handle all of the *sym* related logic here so we only have to pass
37513751
# on the flierprops dict.
37523752
if sym is not None:
@@ -3925,72 +3925,47 @@ def bxp(self, bxpstats, positions=None, widths=None, vert=True,
39253925

39263926
zdelta = 0.1
39273927

3928-
def line_props_with_rcdefaults(subkey, explicit, zdelta=0,
3929-
use_marker=True):
3928+
def merge_kw_rc(subkey, explicit, zdelta=0, usemarker=True):
39303929
d = {k.split('.')[-1]: v for k, v in rcParams.items()
3931-
if k.startswith(f'boxplot.{subkey}')}
3930+
if k.startswith(f'boxplot.{subkey}props')}
39323931
d['zorder'] = zorder + zdelta
3933-
if not use_marker:
3932+
if not usemarker:
39343933
d['marker'] = ''
39353934
d.update(cbook.normalize_kwargs(explicit, mlines.Line2D))
39363935
return d
39373936

3938-
# box properties
3939-
if patch_artist:
3940-
final_boxprops = {
3941-
'linestyle': rcParams['boxplot.boxprops.linestyle'],
3942-
'linewidth': rcParams['boxplot.boxprops.linewidth'],
3943-
'edgecolor': rcParams['boxplot.boxprops.color'],
3944-
'facecolor': ('white' if rcParams['_internal.classic_mode']
3945-
else rcParams['patch.facecolor']),
3946-
'zorder': zorder,
3947-
**cbook.normalize_kwargs(boxprops, mpatches.PathPatch)
3948-
}
3949-
else:
3950-
final_boxprops = line_props_with_rcdefaults('boxprops', boxprops,
3951-
use_marker=False)
3952-
final_whiskerprops = line_props_with_rcdefaults(
3953-
'whiskerprops', whiskerprops, use_marker=False)
3954-
final_capprops = line_props_with_rcdefaults(
3955-
'capprops', capprops, use_marker=False)
3956-
final_flierprops = line_props_with_rcdefaults(
3957-
'flierprops', flierprops)
3958-
final_medianprops = line_props_with_rcdefaults(
3959-
'medianprops', medianprops, zdelta, use_marker=False)
3960-
final_meanprops = line_props_with_rcdefaults(
3961-
'meanprops', meanprops, zdelta)
3937+
box_kw = {
3938+
'linestyle': rcParams['boxplot.boxprops.linestyle'],
3939+
'linewidth': rcParams['boxplot.boxprops.linewidth'],
3940+
'edgecolor': rcParams['boxplot.boxprops.color'],
3941+
'facecolor': ('white' if rcParams['_internal.classic_mode']
3942+
else rcParams['patch.facecolor']),
3943+
'zorder': zorder,
3944+
**cbook.normalize_kwargs(boxprops, mpatches.PathPatch)
3945+
} if patch_artist else merge_kw_rc('box', boxprops, usemarker=False)
3946+
whisker_kw = merge_kw_rc('whisker', whiskerprops, usemarker=False)
3947+
cap_kw = merge_kw_rc('cap', capprops, usemarker=False)
3948+
flier_kw = merge_kw_rc('flier', flierprops)
3949+
median_kw = merge_kw_rc('median', medianprops, zdelta, usemarker=False)
3950+
mean_kw = merge_kw_rc('mean', meanprops, zdelta)
39623951
removed_prop = 'marker' if meanline else 'linestyle'
39633952
# Only remove the property if it's not set explicitly as a parameter.
39643953
if meanprops is None or removed_prop not in meanprops:
3965-
final_meanprops[removed_prop] = ''
3966-
3967-
def patch_list(xs, ys, **kwargs):
3968-
path = mpath.Path(
3969-
# Last vertex will have a CLOSEPOLY code and thus be ignored.
3970-
np.append(np.column_stack([xs, ys]), [(0, 0)], 0),
3971-
closed=True)
3972-
patch = mpatches.PathPatch(path, **kwargs)
3973-
self.add_artist(patch)
3974-
return [patch]
3954+
mean_kw[removed_prop] = ''
39753955

39763956
# vertical or horizontal plot?
3977-
if vert:
3978-
def doplot(*args, **kwargs):
3979-
return self.plot(*args, **kwargs)
3980-
3981-
def dopatch(xs, ys, **kwargs):
3982-
return patch_list(xs, ys, **kwargs)
3957+
maybe_swap = slice(None) if vert else slice(None, None, -1)
39833958

3984-
else:
3985-
def doplot(*args, **kwargs):
3986-
shuffled = []
3987-
for i in range(0, len(args), 2):
3988-
shuffled.extend([args[i + 1], args[i]])
3989-
return self.plot(*shuffled, **kwargs)
3959+
def do_plot(xs, ys, **kwargs):
3960+
return self.plot(*[xs, ys][maybe_swap], **kwargs)[0]
39903961

3991-
def dopatch(xs, ys, **kwargs):
3992-
xs, ys = ys, xs # flip X, Y
3993-
return patch_list(xs, ys, **kwargs)
3962+
def do_patch(xs, ys, **kwargs):
3963+
path = mpath.Path(
3964+
# Last (0, 0) vertex has a CLOSEPOLY code and is thus ignored.
3965+
np.column_stack([[*xs, 0], [*ys, 0]][maybe_swap]), closed=True)
3966+
patch = mpatches.PathPatch(path, **kwargs)
3967+
self.add_artist(patch)
3968+
return patch
39943969

39953970
# input validation
39963971
N = len(bxpstats)
@@ -4019,22 +3994,19 @@ def dopatch(xs, ys, **kwargs):
40193994
datalabels.append(stats.get('label', pos))
40203995

40213996
# whisker coords
4022-
whisker_x = np.ones(2) * pos
4023-
whiskerlo_y = np.array([stats['q1'], stats['whislo']])
4024-
whiskerhi_y = np.array([stats['q3'], stats['whishi']])
4025-
3997+
whis_x = [pos, pos]
3998+
whislo_y = [stats['q1'], stats['whislo']]
3999+
whishi_y = [stats['q3'], stats['whishi']]
40264000
# cap coords
40274001
cap_left = pos - width * 0.25
40284002
cap_right = pos + width * 0.25
4029-
cap_x = np.array([cap_left, cap_right])
4030-
cap_lo = np.ones(2) * stats['whislo']
4031-
cap_hi = np.ones(2) * stats['whishi']
4032-
4003+
cap_x = [cap_left, cap_right]
4004+
cap_lo = np.full(2, stats['whislo'])
4005+
cap_hi = np.full(2, stats['whishi'])
40334006
# box and median coords
40344007
box_left = pos - width * 0.5
40354008
box_right = pos + width * 0.5
40364009
med_y = [stats['med'], stats['med']]
4037-
40384010
# notched boxes
40394011
if shownotches:
40404012
box_x = [box_left, box_right, box_right, cap_right, box_right,
@@ -4045,58 +4017,40 @@ def dopatch(xs, ys, **kwargs):
40454017
stats['q3'], stats['cihi'], stats['med'],
40464018
stats['cilo'], stats['q1']]
40474019
med_x = cap_x
4048-
40494020
# plain boxes
40504021
else:
40514022
box_x = [box_left, box_right, box_right, box_left, box_left]
40524023
box_y = [stats['q1'], stats['q1'], stats['q3'], stats['q3'],
40534024
stats['q1']]
40544025
med_x = [box_left, box_right]
40554026

4056-
# maybe draw the box:
4027+
# maybe draw the box
40574028
if showbox:
4058-
if patch_artist:
4059-
boxes.extend(dopatch(box_x, box_y, **final_boxprops))
4060-
else:
4061-
boxes.extend(doplot(box_x, box_y, **final_boxprops))
4062-
4029+
do_box = do_patch if patch_artist else do_plot
4030+
boxes.append(do_box(box_x, box_y, **box_kw))
40634031
# draw the whiskers
4064-
whiskers.extend(doplot(
4065-
whisker_x, whiskerlo_y, **final_whiskerprops
4066-
))
4067-
whiskers.extend(doplot(
4068-
whisker_x, whiskerhi_y, **final_whiskerprops
4069-
))
4070-
4071-
# maybe draw the caps:
4032+
whiskers.append(do_plot(whis_x, whislo_y, **whisker_kw))
4033+
whiskers.append(do_plot(whis_x, whishi_y, **whisker_kw))
4034+
# maybe draw the caps
40724035
if showcaps:
4073-
caps.extend(doplot(cap_x, cap_lo, **final_capprops))
4074-
caps.extend(doplot(cap_x, cap_hi, **final_capprops))
4075-
4036+
caps.append(do_plot(cap_x, cap_lo, **cap_kw))
4037+
caps.append(do_plot(cap_x, cap_hi, **cap_kw))
40764038
# draw the medians
4077-
medians.extend(doplot(med_x, med_y, **final_medianprops))
4078-
4039+
medians.append(do_plot(med_x, med_y, **median_kw))
40794040
# maybe draw the means
40804041
if showmeans:
40814042
if meanline:
4082-
means.extend(doplot(
4043+
means.append(do_plot(
40834044
[box_left, box_right], [stats['mean'], stats['mean']],
4084-
**final_meanprops
4045+
**mean_kw
40854046
))
40864047
else:
4087-
means.extend(doplot(
4088-
[pos], [stats['mean']], **final_meanprops
4089-
))
4090-
4048+
means.append(do_plot([pos], [stats['mean']], **mean_kw))
40914049
# maybe draw the fliers
40924050
if showfliers:
4093-
# fliers coords
40944051
flier_x = np.full(len(stats['fliers']), pos, dtype=np.float64)
40954052
flier_y = stats['fliers']
4096-
4097-
fliers.extend(doplot(
4098-
flier_x, flier_y, **final_flierprops
4099-
))
4053+
fliers.append(do_plot(flier_x, flier_y, **flier_kw))
41004054

41014055
if manage_ticks:
41024056
axis_name = "x" if vert else "y"

0 commit comments

Comments
 (0)