# Gaps in histogram or bargap error depending on number of bins

My Code:

``````import numpy as np

mean = houses['Overall Cond'].mean()
median = houses['Overall Cond'].median()

houses['Overall Cond'].plot.hist()
plt.show()
``````

What I expected to happen:
A nice pretty histogram with no gaps.

What actually happened:
I got gaps…

Realizing that the data spans from 1 to 9 and that there are 10 bins (default), I realized the bins are (9-1)/10 units wide and therefore the [4.2, 5.0) bin is empty! Ok, easy enough to fix: change to 9 bins! While this generates a `bargap` error, it does produce a plot without gaps but the xlabels aren’t quite right.

``````houses['Overall Cond'].plot.hist(bins=9)
plt.show()
``````

Error produced by the above code:

``````ValueErrorTraceback (most recent call last)
<ipython-input-1-5a1140c5ef17> in <module>()
17
18 houses['Overall Cond'].plot.hist(bins=9)
---> 19 plt.show()
20
21 print(houses['Overall Cond'].value_counts().sort_index())

/dataquest/system/env/python3/lib/python3.5/site-packages/matplotlib/pyplot.py in show(*args, **kw)
252     """
253     global _show
--> 254     return _show(*args, **kw)
255
256

/dataquest/system/libs/dq_matplotlib_backend.py in show(*args, **kw)
123
124         results = backend_inline.show(*args, close=False, **kw)
--> 125         record_jsons(figures)
126     finally:
127         matplotlib.pyplot.close("all")

/dataquest/system/libs/dq_matplotlib_backend.py in record_jsons(figures)
326
327     for figure in figures:
--> 328         plotly_fig = plotly_tools.mpl_to_plotly(figure).to_plotly_json()
329         json_list.append(plotly_fig)
330

/dataquest/system/env/python3/src/plotly-master/packages/python/plotly/plotly/tools.py in mpl_to_plotly(fig, resize, strip_style, verbose)
110     if matplotlylib:
111         renderer = matplotlylib.PlotlyRenderer()
--> 112         matplotlylib.Exporter(renderer).run(fig)
113         if resize:
114             renderer.resize()

/dataquest/system/env/python3/src/plotly-master/packages/python/plotly/plotly/matplotlylib/mplexporter/exporter.py in run(self, fig)
49             import matplotlib.pyplot as plt
50             plt.close(fig)
---> 51         self.crawl_fig(fig)
52
53     @staticmethod

/dataquest/system/env/python3/src/plotly-master/packages/python/plotly/plotly/matplotlylib/mplexporter/exporter.py in crawl_fig(self, fig)
116                                        props=utils.get_figure_properties(fig)):
117             for ax in fig.axes:
--> 118                 self.crawl_ax(ax)
119
120     def crawl_ax(self, ax):

/dataquest/system/env/python3/src/plotly-master/packages/python/plotly/plotly/matplotlylib/mplexporter/exporter.py in crawl_ax(self, ax)
147                 with self.renderer.draw_legend(legend=legend, props=props):
148                     if props['visible']:
--> 149                         self.crawl_legend(ax, legend)
150
151     def crawl_legend(self, ax, legend):

/usr/local/lib/python3.5/contextlib.py in __exit__(self, type, value, traceback)
64         if type is None:
65             try:
---> 66                 next(self.gen)
67             except StopIteration:
68                 return False

/dataquest/system/env/python3/src/plotly-master/packages/python/plotly/plotly/matplotlylib/mplexporter/renderers/base.py in draw_axes(self, ax, props)
57         self.open_axes(ax=ax, props=props)
58         yield
---> 59         self.close_axes(ax=ax)
60         self._current_ax = None
61         self._ax_props = {}

/dataquest/system/env/python3/src/plotly-master/packages/python/plotly/plotly/matplotlylib/renderer.py in close_axes(self, ax)
197
198         """
--> 199         self.draw_bars(self.current_bars)
200         self.msg += "  Closing axes\n"
201         self.x_is_mpl_date = False

/dataquest/system/env/python3/src/plotly-master/packages/python/plotly/plotly/matplotlylib/renderer.py in draw_bars(self, bars)
214             )
215         for trace in mpl_traces:
--> 216             self.draw_bar(trace)
217
218     def draw_bar(self, coll):

/dataquest/system/env/python3/src/plotly-master/packages/python/plotly/plotly/matplotlylib/renderer.py in draw_bar(self, coll)
306             if bar_gap is not None:
--> 307                 self.plotly_fig["layout"]["bargap"] = bar_gap
308         else:
309             self.msg += "    Bar chart not drawn\n"

/dataquest/system/env/python3/src/plotly-master/packages/python/plotly/plotly/basedatatypes.py in __setitem__(self, prop, value)
4435         if match is None:
4436             # Set as ordinary property
-> 4437             super(BaseLayoutHierarchyType, self).__setitem__(prop, value)
4438         else:
4439             # Set as subplotid property

/dataquest/system/env/python3/src/plotly-master/packages/python/plotly/plotly/basedatatypes.py in __setitem__(self, prop, value)
3488             # ### Handle simple property ###
3489             else:
-> 3490                 self._set_prop(prop, value)
3491
3492         # Handle non-scalar case

/dataquest/system/env/python3/src/plotly-master/packages/python/plotly/plotly/basedatatypes.py in _set_prop(self, prop, val)
3775                 return
3776             else:
-> 3777                 raise err
3778
3779         # val is None

/dataquest/system/env/python3/src/plotly-master/packages/python/plotly/plotly/basedatatypes.py in _set_prop(self, prop, val)
3770         validator = self._validators.get(prop)
3771         try:
-> 3772             val = validator.validate_coerce(val)
3773         except ValueError as err:
3774             if self._skip_invalid:

/dataquest/system/env/python3/src/plotly-master/packages/python/plotly/_plotly_utils/basevalidators.py in validate_coerce(self, v)
785             if self.has_min_max:
786                 if not (self.min_val <= v <= self.max_val):
--> 787                     self.raise_invalid_val(v)
788         return v
789

/dataquest/system/env/python3/src/plotly-master/packages/python/plotly/_plotly_utils/basevalidators.py in raise_invalid_val(self, v, inds)
281                 typ=type_str(v),
282                 v=repr(v),
--> 283                 valid_clr_desc=self.description(),
284             )
285         )

ValueError:
Invalid value of type 'numpy.float64' received for the 'bargap' property of layout

The 'bargap' property is a number and may be specified as:
- An int or float in the interval [0, 1]
``````

Despite this lengthy error, a plot is still produced:

However, since the bins are now (9-1)/9 units wide, the xlabels are a little off.

After much Googling and sifting through Stackoverflow posts, I came up with the following code:

``````houses['Overall Cond'].plot.hist(bins=np.arange(0.5, 10, 1))
plt.xticks(np.arange(10))
plt.show()
``````

Which produces the following plot:

While I ultimately was able to produce what I was looking for, I’m wondering if there is a better way to do this or if there’s something I failed to understand when generating histograms for discrete values?

Any and all help/feedback are greatly welcomed!

BONUS QUESTION: According to the documentation, `df.plot.hist()`returns a `matplotlib.AxesSubplot` object whereas `matplotlib.pyplot.hist()` returns `n`, `bins`, and `patches` so that one can easily retrieve the values for each bin (`n`) and the bin edges (`bins`). Is there an easy way to retrieve this same data from the pandas version of `hist()`? IOW: how would one retrieve the bin edges of a histogram from an `axe` object?