8000 Allow scalar height for plt.bar by dstansby · Pull Request #7644 · matplotlib/matplotlib · GitHub
[go: up one dir, main page]

Skip to content

Allow scalar height for plt.bar #7644

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 our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Jan 16, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
< 10000 div data-show-on-forbidden-error hidden>

Uh oh!

There was an error while loading. Please reload this page.

Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 7 additions & 7 deletions lib/matplotlib/axes/_axes.py
Original file line number Diff line number Diff line change
Expand Up @@ -1876,8 +1876,8 @@ def bar(self, left, height, width=0.8, bottom=None, **kwargs):
left : sequence of scalars
the x coordinates of the left sides of the bars

height : sequence of scalars
the heights of the bars
height : scalar or sequence of scalars
the height(s) of the bars

width : scalar or array-like, optional
the width(s) of the bars
Expand Down Expand Up @@ -2025,8 +2025,6 @@ def make_iterable(x):
bottom = [0]

nbars = len(left)
if len(width) == 1:
width *= nbars
if len(bottom) == 1:
bottom *= nbars

Expand All @@ -2045,14 +2043,16 @@ def make_iterable(x):
nbars = len(bottom)
if len(left) == 1:
left *= nbars
if len(height) == 1:
height *= nbars

tick_label_axis = self.yaxis
tick_label_position = bottom
else:
raise ValueError('invalid orientation: %s' % orientation)

if len(height) == 1:
height *= nbars
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks like this is leaving in place an old bug--probably harmless, since no one seems to have tripped over it. The potential problem is that if a kwarg like 'height' is passed in as an ndarray of length 1, it will arrive here and have its value multiplied by nbars, which might not be 1.

_make_iterable could be modified to ensure that if an argument comes in with length 1, it is returned as a list; or it could be turned into a _to_list, and turn any argument into a list. The point is that in at least parts of the code the returned object is assumed to be a list, not just an iterable.

I think the _to_list approach is the way to go; for these variables, there is no advantage in leaving their type as an indeterminate 'iterable'.

if len(width) == 1:
width *= nbars
if len(linewidth) < nbars:
linewidth *= nbars

Expand All @@ -2077,7 +2077,7 @@ def make_iterable(x):
"be length %d or scalar" % nbars)
if len(height) != nbars:
raise ValueError("incompatible sizes: argument 'height' "
"must be length %d or scalar" % nbars)
"must be length %d or scalar" % nbars)
if len(width) != nbars:
raise ValueError("incompatible sizes: argument 'width' "
"must be length %d or scalar" % nbars)
Expand Down
9 changes: 9 additions & 0 deletions lib/matplotlib/tests/test_axes.py
Original file line number Diff line number Diff line change
Expand Up @@ -4877,3 +4877,12 @@ def test_scatter_color_masking():
def test_eventplot_legend():
plt.eventplot([1.0], label='Label')
plt.legend()


@cleanup
def test_bar_single_height():
fig, ax = plt.subplots()
# Check that a bar chart with a single height for all bars works
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Slightly better to do

fig, ax = plt.subplots()
ax.bar(...)

which helps to protect from tests leaking into each other a bit more.

ax.bar(range(4), 1)
# Check that a horizontal chart with one width works
ax.bar(0, 1, bottom=range(4), width=1, orientation='horizontal')
0