32

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
  • 36,675
  • 19
  • 86
  • 83
xuhdev
  • 8,018
  • 2
  • 41
  • 69

3 Answers3

42

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
  • 36,675
  • 19
  • 86
  • 83
  • 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
  • 1
    @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
  • How to apply this grouped histogram to list of df columns with one column determining group? – Wizytor Aug 10 '22 at 06:18
  • Why are you multiplying data by 0.3 in your example? – Anscandance Oct 04 '22 at 21:41
  • @Anscandance It's just random sample data to show stacking multiple datasets. One dataset is `data` and the other is `data*0.3`. – tdy Oct 04 '22 at 21:44
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,083
  • 9
  • 10
12

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,444
  • 3
  • 18
  • 39