This came up before here #9247 and was caused by #8836. Since I think a logarithmic histogram with no extra args to set_yscale('log') is a reasonable ask, I'm going to leave this open.
In the meantime a fix is set_yscale('log', nonposy='clip')
Clearly my search-foo isn't good enough; thanks for the pointers @dstansby. I would have expected 'mask' to only hide entries with values <= 0, rather than the whole histogram. Is the latter behaviour really the intention?
Thanks @tacaswell, I wasn't aware of that. In my case I need to be able to set the scale after the hist call, but that's still useful to know.
It is only hiding the points at 0, but the histogram is drawn as a bunch of rectangles (with their bottom at 0). Once the bottom points are masked out, we don't know how to draw the rectangle (with only 2 points). This is obviously not great for histograms, but it is consistent makes sense in other contexts.
We may want to consider rolling this change back in 2.1.1 and think about it a bit more carefully.
I guess that "in theory", the solution would be to attach additional information to the rectangles generated by hist, so that a log transform applied to them would use clip mode instead of mask? Looks ugly (and haven't thought about the proper way to implement this), but in truth I think this is somewhat similar to how the sticky-edges mechanism works: a single artist shouldn't get to decide how a whole axis property (in this case, whether to clip or to mask invalid values in log transforms) affects all artists.
w/o looking at the code, I'm curious how log=True decides on the lowest y-value for the boxes? If its good enough for log=True I'd think that (non-zero) value is good enough for log=False. I appreciate that is a bit hacky...
The OP can of course bypass all this by calculating the histogram values and plotting them w/ fill-between with the step option where they can set the lower edge value themselves and swicth between log and non-log at will.
Adjustment of ylim is controlled by adjust_ylim in bar() at https://github.com/matplotlib/matplotlib/blob/master/lib/matplotlib/axes/_axes.py#L2188. Basically, on log scale, you can say "ylow is some constant factor below the smallest positive y value (with some clipping)" (so in log scale some constant offset); but you can't afford that in linear scale.
Activity
dstansby commented on Oct 6, 2017
This came up before here #9247 and was caused by #8836. Since I think a logarithmic histogram with no extra args to set_yscale('log') is a reasonable ask, I'm going to leave this open.
In the meantime a fix is set_yscale('log', nonposy='clip')
tacaswell commented on Oct 6, 2017
One of hists many kwargs is log so
will behave as expected.
alexpearce commented on Oct 6, 2017
Clearly my search-foo isn't good enough; thanks for the pointers @dstansby. I would have expected 'mask' to only hide entries with values <= 0, rather than the whole histogram. Is the latter behaviour really the intention?
Thanks @tacaswell, I wasn't aware of that. In my case I need to be able to set the scale after the hist call, but that's still useful to know.
tacaswell commented on Oct 6, 2017
It is only hiding the points at 0, but the histogram is drawn as a bunch of rectangles (with their bottom at 0). Once the bottom points are masked out, we don't know how to draw the rectangle (with only 2 points). This is obviously not great for histograms, but it is consistent makes sense in other contexts.
We may want to consider rolling this change back in 2.1.1 and think about it a bit more carefully.
anntzer commented on Oct 6, 2017
I guess that "in theory", the solution would be to attach additional information to the rectangles generated by hist, so that a log transform applied to them would use clip mode instead of mask? Looks ugly (and haven't thought about the proper way to implement this), but in truth I think this is somewhat similar to how the sticky-edges mechanism works: a single artist shouldn't get to decide how a whole axis property (in this case, whether to clip or to mask invalid values in log transforms) affects all artists.
jklymak commented on Oct 6, 2017
w/o looking at the code, I'm curious how log=True decides on the lowest y-value for the boxes? If its good enough for log=True I'd think that (non-zero) value is good enough for log=False. I appreciate that is a bit hacky...
The OP can of course bypass all this by calculating the histogram values and plotting them w/ fill-between with the step option where they can set the lower edge value themselves and swicth between log and non-log at will.
anntzer commented on Oct 6, 2017
Adjustment of ylim is controlled by adjust_ylim in bar() at https://github.com/matplotlib/matplotlib/blob/master/lib/matplotlib/axes/_axes.py#L2188. Basically, on log scale, you can say "ylow is some constant factor below the smallest positive y value (with some clipping)" (so in log scale some constant offset); but you can't afford that in linear scale.
TST: add test for clip and masking of negative values on log scale
TST: add test for clip and masking of negative values on log scale
tacaswell commented on Oct 30, 2017
Fixed by #9477
Deploy: Fix matplotlib version