Q:

Matplotlib: incorrect histograms

So I just learned about histograms on Khan Academy:

When I go plot something similar in Matplotlib, it is plotted differently. Why?

Shouldn't bins be completely filled? And since bin 5-6 has 3 counts (5, 6, 6), shouldn't it consists of a single bar of value 3? I'm confused

A:

By default, plt.hist() creates 10 bins (or 11 edges). The default value is found in the documentation, and is taken from you rc parameter rcParams["hist.bins"] = 10.
So if you provide data in the range [1–6], hist will count the number of values in the bins: [1.–1.5), [1.5–2.), [2–2.5), [2.5–3.), [3–3.5), [3.5–4.), [4–4.5), [4.5–5.), [5.–5.5), [5.5–6.]. You can tell that that's the case by looking at the text output by hist() (in addition to the graph).
hist() returns 3 objects when called:

the height of each bar (that is the number of items in each bin), equivalent to the column "#" in that Khan video
the edges of the bins, which is roughly equivalent to the column "Bucket" in the video
a list of matplotlib objects that you can use to tweak their appearance when needed.

In summary:
If you want to have bars of width 1, then you need to specify either the number of bins (5), or the edges of your bins.
These two calls provide the same result:
plt.hist(counts, bins=5)
plt.hist(counts, bins=[1,2,3,4,5,6]) 

EDIT
Here is a function that can help you see the "buckets" chosen by hist:
def hist_and_bins(x, ax=None, **kwargs):
    ax = ax or plt.gca()
    counts, edges, patches = ax.hist(x, **kwargs)
    bin_edges = [[a,b] for a,b in zip(edges, edges[1:])]
    ticks = np.mean(bin_edges, axis=1)
    tick_labels = ['[{}-{})'.format(l,r) for l,r in bin_edges]
    tick_labels[-1] = tick_labels[-1][:-1]+']' # last bin is a closed interval
    ax.set_xticks(ticks)
    ax.set_xticklabels(tick_labels)
    return counts, edges, patches, ax.get_xticks()

fig, (ax1, ax2, ax3) = plt.subplots(1,3, figsize=(9,3))
ax1.hist([1,2,3,4,5,6,6])
hist_and_bins([1,2,3,4,5,6,6], ax=ax2)
hist_and_bins([1,2,3,4,5,6,6], ax=ax3, bins=5, ec='w')
fig.autofmt_xdate()

