Skip to main content
v2026.11,858 entries · CC-BY 4.0

NumPy Histogram: np.histogram() Syntax, Bins, Density and Edges

How np.histogram() works: arguments, half-open bin edges, density versus probability, range and weights, with outputs run on NumPy 2.5.1.

Written and maintained by CASRAI Editorial Board

Last updated

numpy.histogram() counts how many values of an array fall into each of a set of bins and returns two arrays: the counts and the bin edges. It does not draw anything; it is the calculation that plotting functions such as plt.hist call underneath. This guide is for researchers and analysts who need the numbers behind a histogram in Python, and who want to know exactly where a boundary value lands, what density=True returns, and how range changes the result. Outputs shown were run on NumPy 2.5.1 and match the behaviour in the NumPy reference documentation (read 2026-11-08).

What np.histogram is used for in research

The function turns a continuous variable into a frequency table: counts per interval. Researchers use it to check the shape of a distribution before choosing a test, to build a frequency table for a methods section, to compare two samples on identical bins, and to feed a histogram or a probability-density estimate into later calculations. Because it returns arrays rather than a figure, the result can be stored, compared and reused. For drawing the chart, see histogram in Matplotlib and Seaborn histogram; the Matplotlib function passes its bin arguments to np.histogram. To judge what shape you are looking at, see how to identify the distribution of your data.

Install or access

NumPy is installed from the official project. The install page (numpy.org/install) gives pip install numpy and, for conda users, conda install numpy from the defaults or conda-forge channel, and recommends working in a virtual environment. Then import it:

import numpy as np

Syntax and arguments

numpy.histogram(a, bins=10, range=None, density=None, weights=None)

It returns (hist, bin_edges). The arguments, per the NumPy reference:

Argument What it does
a The input data (array_like). It is flattened, so a 2-D array is counted as one list of values.
bins An integer gives that many equal-width bins across range. A sequence gives the bin edges, including the rightmost edge, and can have non-uniform widths. A string names an automatic method (see below). Default 10.
range A (lower, upper) pair. Default is (a.min(), a.max()). Values outside the range are ignored. It also affects automatic bin calculation.
density If True, returns the probability density function value per bin instead of counts, so the integral over the range is 1.
weights An array of the same shape as a; each value contributes its weight to its bin instead of 1. The returned hist takes the dtype of the weights.

Step-by-step: build and read a histogram table

  1. Import NumPy and load the values. Here, 200 simulated measurements from a seeded generator so the output is reproducible:
    import numpy as np
    rng = np.random.default_rng(42)
    x = rng.normal(50, 10, 200)
  2. Call np.histogram with a bin count.
    hist, edges = np.histogram(x, bins=5)
    print(hist)    # [22 75 78 21  4]
    print(edges.round(2))  # [28.68 38.77 48.86 58.95 69.05 79.14]
  3. Pair counts with intervals. There is always one more edge than there are counts (len(edges) == len(hist) + 1), so count i belongs to the interval from edges[i] to edges[i+1]. Here 78 values fall between 48.86 and 58.95.
  4. Fix the bins when you need to compare samples. Pass an explicit edge sequence and reuse it for every group:
    edges = np.arange(30, 81, 10)
    hist_a, _ = np.histogram(group_a, bins=edges)
    hist_b, _ = np.histogram(group_b, bins=edges)
  5. Plot or tabulate. Pass the result to your plotting tool, or build a table of intervals and counts.

Output and how to read it

Which bin does a boundary value land in?

All bins are half-open, [a, b), except the last, which is closed, [a, b]. With bins=[1, 2, 3, 4] the intervals are [1, 2), [2, 3) and [3, 4]. Check:

np.histogram([1, 2, 3, 4], bins=[1, 2, 3, 4])
# (array([1, 1, 2]), array([1, 2, 3, 4]))

The value 2 is counted in [2, 3), not [1, 2), and both 3 and 4 fall in the last bin because it includes its upper edge. This matters for integer-valued data such as counts or Likert scores, where many values sit exactly on edges.

What density=True returns

With density=True the result is a probability density, not a probability. The NumPy documentation states that the integral over the range is 1, and that the values sum to 1 only when every bin has width 1. On the seeded data above:

h, e = np.histogram(x, bins=5, density=True)
h.sum()                 # 0.0991  (not 1)
(h * np.diff(e)).sum()  # 1.0

To get the share of observations in each bin, compute h * np.diff(e), or divide the plain counts by their total. The documentation’s own example, np.histogram(np.arange(4), bins=np.arange(5), density=True), returns 0.25 for each of four unit-width bins.

What range does

Values outside range are ignored, so the counts need not sum to the sample size. On the same data:

h, e = np.histogram(x, bins=5, range=(40, 60))
# h = [27 33 33 32 27], e = [40. 44. 48. 52. 56. 60.]
h.sum()   # 152, not 200

The range also governs automatic bin selection: the width is optimised on the data inside the range, and the resulting bins fill the whole range.

Weights

np.histogram([1, 2, 1], bins=[0, 1, 2, 3], weights=[0.5, 1.5, 2.0]) returns [0., 2.5, 1.5]: the two 1s add 0.5 + 2.0 to the second bin. Integer weights give an integer array; float weights give floats. With density=True the weights are normalised so the integral is 1.

Automatic bin methods

Instead of a number, bins accepts a string. The same strings are documented for numpy.histogram_bin_edges, which returns just the edges so you can inspect them first (it does not support weighted data for automatic sizing):

String Documented behaviour
'auto' Minimum bin width from the Sturges and Freedman-Diaconis estimators; described as good all-around performance.
'fd' Freedman-Diaconis; robust to outliers.
'doane' Improved Sturges estimator for non-normal data.
'scott' Less robust; uses variability and size of the data.
'stone' Leave-one-out cross-validation estimate of integrated squared error; a generalisation of Scott’s rule.
'rice' Depends on data size only; commonly overestimates the number of bins.
'sturges' R’s default; size only; optimal for Gaussian data, underestimates for large non-Gaussian data.
'sqrt' Square root of data size; used by Excel and others.

Troubleshooting

ValueError: autodetected range is not finite

If the data contain NaN (or infinity) and you do not pass range, NumPy cannot compute the minimum and maximum, and raises ValueError: autodetected range of [nan, nan] is not finite. Remove missing values first (for example x = x[~np.isnan(x)]) or supply a finite range.

Counts do not add up to the sample size

Check whether you passed a range or an edge sequence that does not cover all values; anything outside is dropped silently.

density=True values do not sum to 1

That is expected unless bin widths are 1; multiply by np.diff(edges) as shown above.

Data in a pandas column or a 2-D array

Pass df['col'].dropna() or the array directly; multi-dimensional input is flattened. To bin into labelled categories rather than count them, see pandas cut. Evenly spaced edges can be generated with numpy linspace, and ravel in NumPy explains flattening.

Free alternatives

Option Relation to np.histogram
matplotlib.pyplot.hist Draws the histogram; its bin arguments are passed to np.histogram.
numpy.histogram_bin_edges Returns only the bin edges, for inspecting or reusing automatic bins.

FAQ

What does np.histogram return?

A tuple of two arrays: hist, the counts (or densities) per bin, and bin_edges, which is one element longer than hist.

How do I use histogram in NumPy with my own bin edges?

Pass a monotonically increasing sequence as bins, including the rightmost edge. Widths may differ between bins.

Is the last bin included?

Yes. Every bin is half-open except the last, which includes its upper edge.

Does numpy histogram plot the data?

No. It only computes counts and edges. Use Matplotlib or Seaborn to draw them.

Sources (official documentation, read 2026-11-08)

Follow CASRAI

Research-administration guidance, standards updates and independent tool reviews.

Ask CASRAI · free to try

Ask about NumPy Histogram: np.histogram() Syntax, Bins, Density and Edges

Ask your first 2 questions free below. Subscribers get 150 a day for $29 a month.

An AI assistant specialized in research administration. It cites the sources behind every answer, labels web answers and says when it can't answer.

Answers draw on CASRAI's guides and dictionary plus the federal and funder documents we index: Federal Register, Grants.gov, Regulations.gov and UKRI.

Works on this site and inside Claude, Cursor and the AI tools you already use.

Everything CASRAI publishes — this page, the dictionary, the guides and the news — stays free to read, with no account and no card.

Referenced across the research world

University of Cambridge logoColumbia University logoCrossref logoUniversity of Edinburgh logoHarvard University logoUniversity of Oxford logoPrinceton University logoStanford School of Medicine logoUniversity College London logoORCID logoUniversity of Cambridge logoColumbia University logoCrossref logoUniversity of Edinburgh logoHarvard University logoUniversity of Oxford logoPrinceton University logoStanford School of Medicine logoUniversity College London logoORCID logo
  • University of Cambridge logo
  • Columbia University logo
  • Crossref logo
  • University of Edinburgh logo
  • Harvard University logo
  • University of Oxford logo
  • Princeton University logo
  • Stanford School of Medicine logo
  • University College London logo
  • ORCID logo

View CASRAI adoption →