Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

Fix bugs in stacked histograms #1706

Closed
wants to merge 2 commits into from

4 participants

@neggert

Hi,

This is an attempt to fix both #1679 and #1631, which both came about because of the way that stacked histograms are handled, introduced in #847.

This isn't ready to go in yet, but I'm running into some problems getting it to work correctly, so I thought I'd try to get some more eyes on it.

There are two problems I'm running into:

  1. fill_between isn't actually filling
  2. fill_between seems to be screwing up autosetting the y axis limits.

Here is the image I get when I run test_hist_stacked. The two histograms are now in the proper order, fixing #1679, you can see the two problems I mentioned. The histograms should be filled and the minimum of the y-axis should be 0.

hist_stacked

Could someone a little more familiar with fill_between take a look at this?

@neggert neggert commented on the diff
lib/matplotlib/axes.py
@@ -8218,17 +8218,11 @@ def hist(self, x, bins=10, range=None, normed=False, weights=None,
labels += [None] * (nx - len(labels))
for (patch, lbl) in zip(patches, labels):
- if patch:
- p = patch[0]
- p.update(kwargs)
- if lbl is not None:
- p.set_label(lbl)
-
- p.set_snap(False)
+ patch.update(kwargs)
+ if lbl is not None:
+ patch.set_label(lbl)
@neggert
neggert added a note

Since the switch to fill_between, we're dealing with a PolyCollection rather than a list of patches. Thus, some changes here. I also put the patches from the bar histtype into a PatchCollection, so they can be treated using the same interface.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
@dmcdougall
Collaborator

This currently targets master. Should it instead target v1.2.x if its intent is to fix a bug?

@neggert

I suppose you're correct. Let's get it working first, then I'll switch it over.

@WeatherGod
Collaborator
@neggert

I think we can keep the API the same by just returning patches.get_paths(). I'm not particularly attached to using the collections, that's just what fill_between returns. If we can't get fill_between to behave, this doesn't matter anyway.

@dmcdougall
Collaborator

I think we can keep the API the same by just returning patches.get_paths().

Actually, not only the type of the returned value needs to be the same, but the order in which they appear in the returned iterable needs to be unchanged as well.

@neggert

Let's cross that bridge when we come to it. Right now, this isn't even working properly.

@NelleV NelleV commented on the diff
lib/matplotlib/axes.py
@@ -8180,11 +8180,11 @@ def hist(self, x, bins=10, range=None, normed=False, weights=None,
x, y = y, x
if fill:
- patches.append(self.fill(x, y,
- closed=False, facecolor=c))
+ patches.append(self.fill_between(x, y, y_bottom,
+ closed=False, facecolors=c))
@NelleV Collaborator
NelleV added a note

PEP8 nitpick: this line is under-indented: it should be align with the opening ( of the previous line

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
@NelleV NelleV commented on the diff
lib/matplotlib/axes.py
((8 lines not shown))
else:
- patches.append(self.fill(x, y,
- closed=False, edgecolor=c, fill=False))
+ patches.append(self.fill_between(x, y, y_bottom,
@NelleV Collaborator
NelleV added a note

Same here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
@neggert

Closed in favor of #1723.

@neggert neggert closed this
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Jan 26, 2013
  1. @neggert

    Overhauling stacked histograms

    neggert authored
  2. @neggert

    Fix some whitespace

    neggert authored
This page is out of date. Refresh to see the latest.
Showing with 16 additions and 22 deletions.
  1. +16 −22 lib/matplotlib/axes.py
View
38 lib/matplotlib/axes.py
@@ -4450,7 +4450,7 @@ def legend(self, *args, **kwargs):
*framealpha*: [*None* | float]
If not None, alpha channel for legend frame. Default *None*.
-
+
*ncol* : integer
number of columns. default is 1
@@ -8076,10 +8076,7 @@ def hist(self, x, bins=10, range=None, normed=False, weights=None,
n = []
mlast = bottom
- # reversed order is necessary so when stacking histogram, first
- # dataset is on top if histogram isn't stacked, this doesn't make any
- # difference
- for i in reversed(xrange(nx)):
+ for i in xrange(nx):
# this will automatically overwrite bins,
# so that each histogram uses the same bins
m, bins = np.histogram(x[i], bins, weights=w[i], **hist_kwargs)
@@ -8103,8 +8100,6 @@ def hist(self, x, bins=10, range=None, normed=False, weights=None,
else:
n = [m[slc].cumsum()[slc] for m in n]
- n.reverse() # put them back in the right order
-
patches = []
if histtype.startswith('bar'):
@@ -8145,7 +8140,9 @@ def hist(self, x, bins=10, range=None, normed=False, weights=None,
patch = _barfunc(bins[:-1] + boffset, m, width,
align='center', log=log,
color=c)
- patches.append(patch)
+ # need to turn this into a collection so that it's consistent
+ # with the step histogram
+ patches.append(mcoll.PatchCollection(patch))
boffset += dw
elif histtype.startswith('step'):
@@ -8172,7 +8169,10 @@ def hist(self, x, bins=10, range=None, normed=False, weights=None,
# overriding this
fill = (histtype == 'stepfilled')
+ y_bottom = y[:]
for m, c in zip(n, color):
+ if stacked:
+ y_bottom = y[:]
y[1:-1:2], y[2::2] = m, m
if log:
y[y < minimum] = minimum
@@ -8180,11 +8180,11 @@ def hist(self, x, bins=10, range=None, normed=False, weights=None,
x, y = y, x
if fill:
- patches.append(self.fill(x, y,
- closed=False, facecolor=c))
+ patches.append(self.fill_between(x, y, y_bottom,
+ closed=False, facecolors=c))
@NelleV Collaborator
NelleV added a note

PEP8 nitpick: this line is under-indented: it should be align with the opening ( of the previous line

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
else:
- patches.append(self.fill(x, y,
- closed=False, edgecolor=c, fill=False))
+ patches.append(self.fill_between(x, y, y_bottom,
@NelleV Collaborator
NelleV added a note

Same here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
+ closed=False, edgecolors=c, fill=False))
# adopted from adjust_x/ylim part of the bar method
if orientation == 'horizontal':
@@ -8218,17 +8218,11 @@ def hist(self, x, bins=10, range=None, normed=False, weights=None,
labels += [None] * (nx - len(labels))
for (patch, lbl) in zip(patches, labels):
- if patch:
- p = patch[0]
- p.update(kwargs)
- if lbl is not None:
- p.set_label(lbl)
-
- p.set_snap(False)
+ patch.update(kwargs)
+ if lbl is not None:
+ patch.set_label(lbl)
@neggert
neggert added a note

Since the switch to fill_between, we're dealing with a PolyCollection rather than a list of patches. Thus, some changes here. I also put the patches from the bar histtype into a PatchCollection, so they can be treated using the same interface.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
- for p in patch[1:]:
- p.update(kwargs)
- p.set_label('_nolegend_')
+ patch.set_snap(False)
if binsgiven:
if orientation == 'vertical':
Something went wrong with that request. Please try again.