21

With matplotlib's hist function, how can one make it display the count for each bin over the bar?

For example,

import matplotlib.pyplot as plt
data = [ ... ] # some data
plt.hist(data, bins=10)

How can we make the count in each bin display over its bar?

tdy
  • 26,545
  • 9
  • 43
  • 50
xuhdev
  • 7,234
  • 2
  • 37
  • 62

3 Answers3

25

it seems hist can't do this,you can write some like :

your_bins=20
data=[]
arr=plt.hist(data,bins=your_bins)
for i in range(your_bins):
    plt.text(arr[1][i],arr[0][i],str(arr[0][i]))
kiviak
  • 1,065
  • 9
  • 10
11

New in matplotlib 3.4.0

There is a new plt.bar_label method to automatically label bar containers.

plt.hist returns the bar container(s) as the third output:

data = np.random.default_rng(123).rayleigh(1, 70)
counts, edges, bars = plt.hist(data)
#              ^

plt.bar_label(bars)

If you have a grouped or stacked histogram, bars will contain multiple containers (one per group), so iterate:

fig, ax = plt.subplots()
counts, edges, bars = ax.hist([data, data * 0.3], histtype='barstacked')

for b in bars:
    ax.bar_label(b)

Note that you can also access the bar container(s) via ax.containers:

for c in ax.containers:
    ax.bar_label(c)
tdy
  • 26,545
  • 9
  • 43
  • 50
  • Hello, what if there are some 0 values that I don't wanna display what I'm gonna do? – Arkadian May 21 '22 at 03:36
  • @Arkadian Pass a filtered list of `datavalues` using the `labels` param ([similar to this answer](https://stackoverflow.com/a/70516643/13138364)), e.g.: `plt.bar_label(bars, labels=[v if v > 0 else '' for v in bars.datavalues])` – tdy May 21 '22 at 04:54
10

Not solution solely using plt.hist() but with some added functionality.

If you don't want to specify your bins beforehand and only plot densities bars, but also want to display the bin counts you can use the following.

import numpy as np
import matplotlib.pyplot as plt

data = np.random.randn(100)
density, bins, _ = plt.hist(data, density=True, bins=20)
count, _ = np.histogram(data, bins)
for x,y,num in zip(bins, density, count):
    if num != 0:
        plt.text(x, y+0.05, num, fontsize=10, rotation=-90) # x,y,str

The result looks as follows:

enter image description here

v.tralala
  • 1,220
  • 1
  • 13
  • 33