Quick answer: np.digitize assigns each value to a bin index defined by monotonic bin edges. The right argument controls which side of an edge is included, and values outside the edge range receive boundary indices that need validation before they are mapped to labels. Use a separate label policy when bins represent categories.

numpy.digitize() returns the bin index for each input value. You give it numeric values and a one-dimensional array of bin edges, and it tells you where each value belongs.
The official NumPy documentation covers numpy.digitize(), numpy.searchsorted(), and numpy.histogram().
The bins array must be one-dimensional and monotonic. It can be increasing or decreasing, but the order must be consistent.
For increasing bins and the default right=False, a returned index i means the value falls in the interval bins[i-1] <= x < bins[i]. With right=True, the edge rule changes to bins[i-1] < x <= bins[i].
Out-of-range values are important. Values below the first edge return 0. Values above the last edge return len(bins). Those return values are not always safe to use directly as indexes into the bins array.
Use digitize() when you need bin numbers for later grouping or labeling. Use histogram() when you need counts per bin. Use searchsorted() when you need lower-level insertion points.
The return value from digitize() is not a count. It is a bin number for each input value. If you need to count how many values landed in each bin, pass the original values and bin edges to histogram() instead.
Think carefully about labels. If you create labels such as "small", "medium", and "large", the out-of-range codes need a separate policy. You might label them as below range and above range, filter them out, or expand the bin edges.
The edge rule is part of the data definition. A score of 10 might belong to the lower band or the upper band depending on whether you use right=False or right=True. Pick the rule before writing summary reports.
Place Values Into Bins
The basic call returns one bin index per input value.
import numpy as np
values = np.array([2, 7, 12, 18])
bins = np.array([0, 10, 20])
indices = np.digitize(values, bins)
print(indices)
The output has the same shape as values.
Each number tells you which bin interval contains the matching input value.
For increasing bins, the returned index starts at 1 for values inside the first interval.
That starting point is why direct label lookup often needs an offset or explicit boundary handling. Inside-range bins start at 1, while many Python arrays start at index 0.
Compare right False And True
The right argument controls which side of a bin edge is closed.
import numpy as np
values = np.array([0, 10, 20])
bins = np.array([0, 10, 20])
left_rule = np.digitize(values, bins, right=False)
right_rule = np.digitize(values, bins, right=True)
print(left_rule)
print(right_rule)
The two outputs differ exactly at bin edges.
Choose the rule that matches the grouping definition used by your data.
Document the rule when edge values have business meaning, such as score bands or age ranges.
When you are matching a published grading table or pricing band, test edge values directly. Those are the cases where a one-character change in right can change the result.

Handle Out Of Range Values
Values outside the bin range return 0 or len(bins).
import numpy as np
values = np.array([-5, 2, 12, 25])
bins = np.array([0, 10, 20])
indices = np.digitize(values, bins)
print(indices)
print(len(bins))
The low value returns 0.
The high value returns the length of the bins array.
Check for these boundary codes before using bin indexes to look up labels or edges.
A robust workflow usually checks for indices == 0 and indices == len(bins) before mapping to labels. That keeps boundary handling explicit instead of relying on accidental Python indexing behavior.
Digitize A 2D Array
digitize() preserves the shape of the input values.
import numpy as np
values = np.array([
[3, 9, 12],
[17, 21, 4],
])
bins = np.array([0, 10, 20])
indices = np.digitize(values, bins)
print(indices)
The result is also a two-dimensional array.
This is useful when binning grids, table columns, or image-like numeric data.
Shape preservation makes it easy to compare the bin index output with the original input.
This is useful for dashboards and array masks because every output position still corresponds to the same input position.

Use Decreasing Bins
Bins may be decreasing as long as they stay monotonic.
import numpy as np
values = np.array([25, 15, 5])
bins = np.array([20, 10, 0])
indices = np.digitize(values, bins)
print(indices)
NumPy checks the bin order and applies the matching interval rule.
Use increasing bins when possible because they are easier for most readers to inspect.
If decreasing bins are required, keep examples small and print the output during testing.
Most readers find increasing bins easier to review, so use decreasing bins only when the source data or domain convention already uses descending thresholds.
Compare With searchsorted
For increasing bins, digitize() is closely related to searchsorted().
import numpy as np
values = np.array([2, 7, 12, 18])
bins = np.array([0, 10, 20])
digitized = np.digitize(values, bins, right=True)
positions = np.searchsorted(bins, values, side="left")
print(digitized)
print(positions)
digitize() adds bin-specific checks and supports decreasing bins.
searchsorted() is a lower-level insertion-position helper.
Use digitize() for clearer binning intent. Use searchsorted() when you are already thinking in terms of insertion positions in a sorted array.
In short, use np.digitize() to assign values to monotonic bins, choose right deliberately, and handle the out-of-range return values before indexing labels or bin edges.

Create Ordered Bins
The bin edges must be monotonic. For increasing edges, digitize returns an index based on the intervals between them; keep the edge definition beside the labels so the categories cannot drift apart.
import numpy as np
values = np.array([0.2, 1.4, 2.8, 4.1])
edges = np.array([0., 1., 3., 5.])
indices = np.digitize(values, edges)
print(indices)
Understand right
The default and right=True choose different inclusion rules at an exact edge. Test boundary values explicitly when a value equal to an edge has business meaning.
import numpy as np
values = np.array([1., 3.])
edges = np.array([1., 3.])
print(np.digitize(values, edges, right=False))
print(np.digitize(values, edges, right=True))

Handle Out Of Range Values
A zero index or an index equal to len(edges) indicates that a value lies outside the interior bins. Decide whether to reject, clip, or assign an underflow or overflow label.
import numpy as np
values = np.array([-1., 2., 9.])
edges = np.array([0., 5.])
indices = np.digitize(values, edges)
print(indices)
valid = (indices > 0) & (indices < len(edges))
print(valid)
Map Indices To Labels
Labels are a separate application layer. Check the returned index before indexing the label list, especially when the input can be outside the configured range.
import numpy as np
values = np.array([0.2, 2.0, 4.5])
edges = np.array([0., 1., 3., 5.])
labels = ["small", "medium", "large"]
indices = np.digitize(values, edges)
result = [labels[index - 1] for index in indices]
print(result)
NumPy’s digitize() reference documents monotonic bins, right-side inclusion, and returned indices. Related references include histogram bins, searchsorted, and array axes.
For related binning and array operations, compare histogram bins, searchsorted, and array axes when assigning categories.
Frequently Asked Questions
What does np.digitize return?
It returns bin indices for each input value based on the supplied monotonic bin edges.
What does right=True change?
It changes which side of an edge is included, so boundary values can move to the neighboring bin.
What happens outside the bin range?
Values below the first edge or above the last edge receive indices outside the interior bin range.
How do I convert indices into labels?
Use an explicit label list and validate that every returned index maps to a supported category.