Lukas Barth
Lukas Barth

Reputation: 3048

Matplotlib histogram: glitch when setting rwidth to 0.9

I'm trying to plot a histogram with matplotlib and have a little space between the individual bars. Therefore I set rwidth=0.9. This is the output:

enter image description here

Is there a way of avoiding the glitch? Setting lower values for rwidth ensures that all the bars are separated, however there are still visible differences in the width of the space:

enter image description here

I am using matplotlib version 2.0.2. Here is a pip freeze if that helps:

appdirs==1.4.3
bleach==2.0.0
bokeh==0.12.9
callcatcher==1.2.0
certifi==2017.7.27.1
chardet==3.0.4
cycler==0.10.0
decorator==4.1.2
entrypoints==0.2.3
graphviz==0.8
holoviews==1.8.4
html5lib==0.999999999
idna==2.6
ipykernel==4.6.1
ipython==6.2.0
ipython-genutils==0.2.0
ipywidgets==7.0.1
jedi==0.11.0
Jinja2==2.9.6
jsonschema==2.6.0
jupyter==1.0.0
jupyter-client==5.1.0
jupyter-console==5.2.0
jupyter-core==4.3.0
MarkupSafe==1.0
matplotlib==2.0.2
mistune==0.7.4
nbconvert==5.3.1
nbformat==4.4.0
notebook==5.1.0
numpy==1.13.2
packaging==16.8
pandas==0.20.3
pandocfilters==1.4.2
param==1.5.1
parso==0.1.0
pexpect==4.2.1
pickleshare==0.7.4
pkg-resources==0.0.0
prompt-toolkit==1.0.15
ptyprocess==0.5.2
Pygments==2.2.0
pyparsing==2.2.0
python-dateutil==2.6.1
pytz==2017.2
PyYAML==3.12
pyzmq==16.0.2
qtconsole==4.3.1
requests==2.18.4
scipy==0.19.1
seaborn==0.8.1
simplegeneric==0.8.1
six==1.11.0
terminado==0.6
testpath==0.3.1
tornado==4.5.2
traitlets==4.3.2
urllib3==1.22
wcwidth==0.1.7
webencodings==0.5.1
widgetsnbextension==3.0.3
xonsh==0.3.2

Any help is appreciated, thanks!

Lukas

Upvotes: 2

Views: 3195

Answers (2)

ImportanceOfBeingErnest
ImportanceOfBeingErnest

Reputation: 339150

I think this behaviour was introduced to matplotlib with version 2.0 (at least I can't remember this being as bad as now in previous versions, but I may be wrong here) and one could consider it to be a bug. Bugs can be reported at the issue tracker. Of course there are cases, where no optimal solutions can exist (i.e. if bars are very thin).

The following are some considerations as to how to cope with the issue.

  • First, note that a figure exported to pdf does not have the problem of unequal bar widths, due to the vector format in use. So for publications or similar, using pdf is definitely an option to consider.

    import numpy as np
    import matplotlib.pyplot as plt
    
    x = np.random.randn(5000)
    plt.hist(x,bins=50, rwidth=0.9)
    
    plt.savefig(__file__+".pdf")
    
  • Because pdf works fine, you may convert the pdf to a png, e.g. through imagemagick

    > convert -density 300 -trim test.pdf test.png
    
  • You may create a png image with a higher resolution. I.e. changing the dpi to something above 200 may already give you the desired output

    plt.savefig(__file__+".pdf", dpi=288)
    

  • When working in a Jupyter notebook you may also set the dpi for the figure to a higher value

    plt.rcParams["figure.dpi"] = 288
    

    for all figures or

    plt.figure(dpi=288)
    

    for a single figure. The drawback might be that the figure becomes too large.

  • To avoid the above huge image, you may instead of displaying the actual figure, display a figure of heigh dpi but set the width of the output to some smaller value. This is a little tedious, but of course one can copy paste the below function for reuse.

    import numpy as np
    import matplotlib.pyplot as plt
    from IPython.display import Image, display
    import io
    
    def display_figure(fig=None):
        if not fig: fig=plt.gcf();
        buff = io.BytesIO()
        fig.savefig(buff, dpi=288)
        buff.seek(0)
        display(Image(data=buff.getvalue(), width=480))
    
    x = np.random.randn(5000);
    plt.hist(x,bins=50, rwidth=0.9);
    display_figure(plt.gcf())
    

    enter image description here

Upvotes: 3

Arthur Gouveia
Arthur Gouveia

Reputation: 744

There should be no gaps between consecutive bars on a Histogram: "As the adjacent bins leave no gaps, the rectangles of a histogram touch each other to indicate that the original variable is continuous.[4]"

And I don't think it's a matplotlib glitch. Try to reduce the number of bins or increase your chart size and you'll probably see the gaps between the bars. I say probably because it will depend on how your browser renders the histogram figure.

To set the size of the histogram you must set the figsize; the figure width and height in inches.

plt.figure(figsize=(12, 5))
plt.hist(x, bins=50, normed=True, rwidth=0.9);

Upvotes: 0

Related Questions