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

Interpret unitless bar widths for unitized data as relative to spacing.#13254

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Closed
anntzer wants to merge1 commit intomatplotlib:masterfromanntzer:bar-units
Closed
Changes fromall commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
133 changes: 60 additions & 73 deletionslib/matplotlib/axes/_axes.py
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -32,6 +32,7 @@
import matplotlib.ticker as mticker
import matplotlib.transforms as mtransforms
import matplotlib.tri as mtri
import matplotlib.units as munits
from matplotlib.container import BarContainer, ErrorbarContainer, StemContainer
from matplotlib.axes._base import _AxesBase, _process_plot_format

Expand DownExpand Up@@ -2012,56 +2013,33 @@ def step(self, x, y, *args, where='pre', data=None, **kwargs):
return self.plot(x, y, *args, data=data, **kwargs)

@staticmethod
def_convert_dx(dx, x0, xconv, convert):
def_convert_dz(axis, z, z_conv, dz):
"""
Small helper to do logic of width conversion flexibly.

*dx* and *x0* have units, but *xconv* has already been converted
to unitless (and is an ndarray). This allows the *dx* to have units
that are different from *x0*, but are still accepted by the
``__add__`` operator of *x0*.
Convert potentially unitized *dz* into unitless values using the
*axis*' converter and *z*/*z_conv* as values (respectively unitized and
unitless) over which *dz* apply.
"""

# x should be an array...
assert type(xconv) is np.ndarray

if xconv.size == 0:
# xconv has already been converted, but maybe empty...
return convert(dx)

try:
# attempt to add the width to x0; this works for
# datetime+timedelta, for instance

# only use the first element of x and x0. This saves
# having to be sure addition works across the whole
# vector. This is particularly an issue if
# x0 and dx are lists so x0 + dx just concatenates the lists.
# We can't just cast x0 and dx to numpy arrays because that
# removes the units from unit packages like `pint` that
# wrap numpy arrays.
try:
x0 = x0[0]
except (TypeError, IndexError, KeyError):
x0 = x0

try:
x = xconv[0]
except (TypeError, IndexError, KeyError):
x = xconv

delist = False
if not np.iterable(dx):
dx = [dx]
delist = True
dx = [convert(x0 + ddx) - x for ddx in dx]
if delist:
dx = dx[0]
except (ValueError, TypeError, AttributeError):
# if the above fails (for any reason) just fallback to what
# we do by default and convert dx by iteslf.
dx = convert(dx)
return dx
scalar_dz = np.ndim(dz) == 0
if axis.converter is not None: # z was unitized.
if munits.ConversionInterface.is_numlike(dz): # Scalar width.
if np.size(z_conv) == 1:
dz = np.diff(axis.get_view_interval()) * dz
else:
dz = np.array(dz) * np.ptp(z_conv) / (np.size(z_conv) - 1)
else: # Unitized.
# cbook.flatten([]) is similar to atleast_1d here, but returns
# a list and keeps units.
z = [*cbook.flatten([z])]
dz = [*cbook.flatten([dz])]
if len(z) == 1:
z = z * len(dz)
if len(dz) == 1:
dz = dz * len(z)
dz = [axis.convert_units(_z + _dz) - axis.convert_units(_z)
for _z, _dz in zip(z, dz)]
if scalar_dz and np.ndim(dz) > 0:
dz, = dz
return dz

@_preprocess_data()
@docstring.dedent_interpd
Expand All@@ -2088,7 +2066,8 @@ def bar(self, x, height, width=0.8, bottom=None, *, align="center",
The height(s) of the bars.

width : scalar or array-like, optional
The width(s) of the bars (default: 0.8).
The width(s) of the bars (default: 0.8, but see note below if *x*
has units).

bottom : scalar or array-like, optional
The y coordinate(s) of the bars bases (default: 0).
Expand DownExpand Up@@ -2166,14 +2145,19 @@ def bar(self, x, height, width=0.8, bottom=None, *, align="center",
*xerr*, and *yerr* can be either scalars or sequences of
length equal to the number of bars. This enables you to use
bar as the basis for stacked bar charts, or candlestick plots.
Detail: *xerr* and *yerr* are passed directly to
:meth:`errorbar`, so they can also have shape 2xN for
independent specification of lower and upper errors.

If *x* has units, then *width* should normally also be specified with
units (so that they can be meaningfully added). However, if a unitless
*width* is used (in particular, for the default *width*), then it
is interpreted as a fraction of the average inter-bar spacing. For
example, if the bars are equally spaced, then a *width* of 1 makes the
bars contiguous. As a special case, if there is a *single* bar, then
a unitless *width* is interpreted as a fraction of the axis (current)
view span.

Other optional kwargs:

%(Rectangle)s

"""
kwargs = cbook.normalize_kwargs(kwargs, mpatches.Patch._alias_map)
color = kwargs.pop('color', None)
Expand DownExpand Up@@ -2226,18 +2210,16 @@ def bar(self, x, height, width=0.8, bottom=None, *, align="center",

# lets do some conversions now since some types cannot be
# subtracted uniformly
if self.xaxis is not None:
x0 = x
x = np.asarray(self.convert_xunits(x))
width = self._convert_dx(width, x0, x, self.convert_xunits)
if xerr is not None:
xerr = self._convert_dx(xerr, x0, x, self.convert_xunits)
if self.yaxis is not None:
y0 = y
y = np.asarray(self.convert_yunits(y))
height = self._convert_dx(height, y0, y, self.convert_yunits)
if yerr is not None:
yerr = self._convert_dx(yerr, y0, y, self.convert_yunits)
x0 = x
x = self.convert_xunits(x)
width = self._convert_dz(self.xaxis, x0, x, width)
if xerr is not None:
xerr = self._convert_dz(self.xaxis, x0, x, xerr)
y0 = y
y = self.convert_yunits(y)
height = self._convert_dz(self.yaxis, y0, y, height)
if yerr is not None:
yerr = self._convert_dz(self.yaxis, y0, y, yerr)

x, height, width, y, linewidth = np.broadcast_arrays(
# Make args iterable too.
Expand DownExpand Up@@ -2376,8 +2358,9 @@ def barh(self, y, width, height=0.8, left=None, *, align="center",
width : scalar or array-like
The width(s) of the bars.

height : sequence of scalars, optional, default: 0.8
The heights of the bars.
height : sequence of scalars, optional
The heights of the bars (default: 0.8, but see note below if *y*
has units).

left : sequence of scalars
The x coordinates of the left sides of the bars (default: 0).
Expand DownExpand Up@@ -2452,14 +2435,19 @@ def barh(self, y, width, height=0.8, left=None, *, align="center",
*xerr*, and *yerr* can be either scalars or sequences of
length equal to the number of bars. This enables you to use
bar as the basis for stacked bar charts, or candlestick plots.
Detail: *xerr* and *yerr* are passed directly to
:meth:`errorbar`, so they can also have shape 2xN for
independent specification of lower and upper errors.

If *y* has units, then *height* should normally also be specified with
units (so that they can be meaningfully added). However, if a unitless
*height* is used (in particular, for the default *height*), then it is
interpreted as a fraction of the average inter-bar spacing. For
example, if the bars are equally spaced, then a *height* of 1 makes the
bars contiguous. As a special case, if there is a *single* bar, then
a unitless *height* is interpreted as a fraction of the axis (current)
view span.

Other optional kwargs:

%(Rectangle)s

"""
kwargs.setdefault('orientation', 'horizontal')
patches = self.bar(x=left, height=height, width=width, bottom=y,
Expand DownExpand Up@@ -2535,9 +2523,8 @@ def broken_barh(self, xranges, yrange, **kwargs):
'with two elements (i.e. an Nx2 array)')
# convert the absolute values, not the x and dx...
x_conv = np.asarray(self.convert_xunits(xr[0]))
x1 = self._convert_dx(xr[1], xr[0], x_conv,self.convert_xunits)
x1 = self._convert_dz(self.xaxis, xr[0], x_conv,xr[1])
xranges_conv.append((x_conv, x1))

yrange_conv = self.convert_yunits(yrange)

col = mcoll.BrokenBarHCollection(xranges_conv, yrange_conv, **kwargs)
Expand Down

[8]ページ先頭

©2009-2025 Movatter.jp