Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit fda57b0

Browse files
committed
Accept same types to errorevery as markevery.
Though it doesn't accept real input for display-space, as errorbar is not continuous. Fixes #4438.
1 parent cc9ae2f commit fda57b0

File tree

3 files changed

+83
-14
lines changed

3 files changed

+83
-14
lines changed
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
``errorbar`` *errorevery* parameter matches *markevery*
2+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3+
4+
Similar to the *markevery* parameter to `~.Axes.plot`, the *errorevery*
5+
parameter of `~.Axes.errorbar` now accept slices and NumPy fancy indexes (which
6+
must match the size of *x*).
7+
8+
.. plot::
9+
10+
x = np.linspace(0, 1, 15)
11+
y = x * (1-x)
12+
yerr = y/6
13+
14+
fig, ax = plt.subplots(2, constrained_layout=True)
15+
ax[0].errorbar(x, y, yerr, capsize=2)
16+
ax[0].set_title('errorevery unspecified')
17+
18+
ax[1].errorbar(x, y, yerr, capsize=2,
19+
errorevery=[False, True, True, False, True] * 3)
20+
ax[1].set_title('errorevery=[False, True, True, False, True] * 3')

lib/matplotlib/axes/_axes.py

Lines changed: 29 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
import itertools
33
import logging
44
import math
5-
from numbers import Number
5+
from numbers import Integral, Number
66

77
import numpy as np
88
from numpy import ma
@@ -3147,17 +3147,6 @@ def errorbar(self, x, y, yerr=None, xerr=None,
31473147
kwargs = {k: v for k, v in kwargs.items() if v is not None}
31483148
kwargs.setdefault('zorder', 2)
31493149

3150-
try:
3151-
offset, errorevery = errorevery
3152-
except TypeError:
3153-
offset = 0
3154-
3155-
if errorevery < 1 or int(errorevery) != errorevery:
3156-
raise ValueError(
3157-
'errorevery must be positive integer or tuple of integers')
3158-
if int(offset) != offset:
3159-
raise ValueError("errorevery's starting index must be an integer")
3160-
31613150
self._process_unit_info([("x", x), ("y", y)], kwargs, convert=False)
31623151

31633152
# Make sure all the args are iterable; use lists not arrays to preserve
@@ -3179,6 +3168,33 @@ def errorbar(self, x, y, yerr=None, xerr=None,
31793168
if not np.iterable(yerr):
31803169
yerr = [yerr] * len(y)
31813170

3171+
if isinstance(errorevery, Integral):
3172+
errorevery = (0, errorevery)
3173+
if isinstance(errorevery, tuple):
3174+
if (len(errorevery) == 2 and
3175+
isinstance(errorevery[0], Integral) and
3176+
isinstance(errorevery[1], Integral)):
3177+
errorevery = slice(errorevery[0], None, errorevery[1])
3178+
else:
3179+
raise ValueError(
3180+
f'errorevery={errorevery!r} is a not a tuple of two '
3181+
f'integers')
3182+
3183+
elif isinstance(errorevery, slice):
3184+
pass
3185+
3186+
elif not isinstance(errorevery, str) and np.iterable(errorevery):
3187+
# fancy indexing
3188+
try:
3189+
x[errorevery]
3190+
except (ValueError, IndexError) as err:
3191+
raise ValueError(
3192+
f"errorevery={errorevery!r} is iterable but not a valid "
3193+
f"NumPy fancy index to match 'xerr'/'yerr'") from err
3194+
else:
3195+
raise ValueError(
3196+
f"errorevery={errorevery!r} is not a recognized value")
3197+
31823198
label = kwargs.pop("label", None)
31833199
kwargs['label'] = '_nolegend_'
31843200

@@ -3261,7 +3277,7 @@ def errorbar(self, x, y, yerr=None, xerr=None,
32613277
xuplims = np.broadcast_to(xuplims, len(x)).astype(bool)
32623278

32633279
everymask = np.zeros(len(x), bool)
3264-
everymask[offset::errorevery] = True
3280+
everymask[errorevery] = True
32653281

32663282
def apply_mask(arrays, mask):
32673283
# Return, for each array in *arrays*, the elements for which *mask*

lib/matplotlib/tests/test_axes.py

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3389,6 +3389,23 @@ def test_errorbar_with_prop_cycle(fig_test, fig_ref):
33893389
ax.set_xlim(1, 11)
33903390

33913391

3392+
def test_errorbar_every_invalid():
3393+
x = np.linspace(0, 1, 15)
3394+
y = x * (1-x)
3395+
yerr = y/6
3396+
3397+
ax = plt.figure().subplots()
3398+
3399+
with pytest.raises(ValueError, match='not a tuple of two integers'):
3400+
ax.errorbar(x, y, yerr, errorevery=(1, 2, 3))
3401+
with pytest.raises(ValueError, match='not a tuple of two integers'):
3402+
ax.errorbar(x, y, yerr, errorevery=(1.3, 3))
3403+
with pytest.raises(ValueError, match='not a valid NumPy fancy index'):
3404+
ax.errorbar(x, y, yerr, errorevery=[False, True])
3405+
with pytest.raises(ValueError, match='not a recognized value'):
3406+
ax.errorbar(x, y, yerr, errorevery='foobar')
3407+
3408+
33923409
@check_figures_equal()
33933410
def test_errorbar_every(fig_test, fig_ref):
33943411
x = np.linspace(0, 1, 15)
@@ -3401,7 +3418,7 @@ def test_errorbar_every(fig_test, fig_ref):
34013418
for color, shift in zip('rgbk', [0, 0, 2, 7]):
34023419
y += .02
34033420

3404-
# Using feature in question
3421+
# Check errorevery using an explicit offset and step.
34053422
ax_test.errorbar(x, y, yerr, errorevery=(shift, 4),
34063423
capsize=4, c=color)
34073424

@@ -3416,6 +3433,22 @@ def test_errorbar_every(fig_test, fig_ref):
34163433
ax_ref.plot(x[1::4], y[1::4] + 0.1, 'o', zorder=2.1)
34173434
ax_ref.errorbar(x, y + 0.1, yerr, capsize=4, fmt='none')
34183435

3436+
# Check that passing a slice to markevery/errorevery works.
3437+
ax_test.errorbar(x, y + 0.2, yerr, errorevery=slice(2, None, 3),
3438+
markevery=slice(2, None, 3),
3439+
capsize=4, c='C0', fmt='o')
3440+
ax_ref.plot(x[2::3], y[2::3] + 0.2, 'o', c='C0', zorder=2.1)
3441+
ax_ref.errorbar(x[2::3], y[2::3] + 0.2, yerr[2::3],
3442+
capsize=4, c='C0', fmt='none')
3443+
3444+
# Check that passing an iterable to markevery/errorevery works.
3445+
ax_test.errorbar(x, y + 0.2, yerr, errorevery=[False, True, False] * 5,
3446+
markevery=[False, True, False] * 5,
3447+
capsize=4, c='C1', fmt='o')
3448+
ax_ref.plot(x[1::3], y[1::3] + 0.2, 'o', c='C1', zorder=2.1)
3449+
ax_ref.errorbar(x[1::3], y[1::3] + 0.2, yerr[1::3],
3450+
capsize=4, c='C1', fmt='none')
3451+
34193452

34203453
@image_comparison(['hist_stacked_stepfilled', 'hist_stacked_stepfilled'])
34213454
def test_hist_stacked_stepfilled():

0 commit comments

Comments
 (0)