Quick wins for a faster PC:
Scan for outdated or missing drivers - takes under a minuteDriver Scan →Clear out junk files and repair common Windows errorsFree Scan →To get distinct values and how often each one appears in a NumPy array, call values, counts = np.unique(a, return_counts=True). To get distinct rows of a 2D array, call np.unique(a, axis=0), and use axis=1 for distinct columns. The outputs are aligned by position, so the details below matter mainly when you need to map results back to the original data or write code that runs across NumPy versions.
Getting unique values and their counts
With the default axis=None, np.unique flattens the input and returns the distinct scalar values in sorted order. Adding return_counts=True returns a second array of occurrence counts. The two arrays line up position by position: counts[i] is the number of times values[i] appears in the input, whatever the input’s shape.
As an Amazon Associate I earn from qualifying purchases.
import numpy as np
a = np.array([3, 1, 2, 3, 1, 1])
values, counts = np.unique(a, return_counts=True)
print(values) # [1 2 3]
print(counts) # [3 1 2]
Here the value 1 appears three times, 2 once, and 3 twice. A 2D input works the same way without any extra flags: it is flattened first, so every element counts individually. If you want counts per row rather than per element, use the row-based form in the next section.
Unique rows and unique columns
To treat each row as one item, pass axis=0. NumPy compares whole rows and returns them sorted lexicographically. Combine it with return_counts=True to count how many times each distinct row occurs:
#1 Best Overall
b = np.array([[1, 2],
[3, 4],
[1, 2]])
unique_rows, row_counts = np.unique(b, axis=0, return_counts=True)
print(unique_rows) # [[1 2]
# [3 4]]
print(row_counts) # [2 1]
Use axis=1 to treat each column as one item instead. The result is the distinct columns, again sorted lexicographically. Two restrictions apply: object arrays are not supported with axis, and neither are structured arrays that contain objects. If your data holds Python objects, convert it to a numeric or string dtype first, or deduplicate it another way.
Tracking where values came from
Counts answer “how many,” but two other outputs answer “where.” Each is optional and is requested with a keyword flag. Together they let you locate representatives in the original array and rebuild it from the unique set.
First-occurrence indices with return_index
return_index=True returns, for each unique value, the index of its first occurrence in the input. This is useful when you want to keep the first record for each key, such as the first row that matches a given identifier.
Free tools Windows power users keep installed
One-click scans. No signup required.
values, first_idx = np.unique(a, return_index=True)
print(first_idx) # [1 2 0]
The value 1 first appears at index 1, 2 at index 2, and 3 at index 0.
Reconstructing the input with return_inverse
return_inverse=True returns an index array that maps each element of the original input to its position in the unique array. Indexing the unique array with it rebuilds the input:
unique_values, inverse = np.unique(a, return_inverse=True)
reconstructed = unique_values[inverse]
print(inverse) # [2 0 1 2 0 0]
print(reconstructed) # [3 1 2 3 1 1]
For a 1D array, this reconstruction is exact and keeps the original order. For axis-based deduplication, the mapping must be applied along the same axis. The NumPy reference documents np.take(unique, unique_inverse, axis=axis) for this case, and the shape behavior of the inverse output depends on the NumPy version, as described below.
Rank #4
Repeating values by their counts is not the same as reconstruction
You may be tempted to rebuild the data with np.repeat(values, counts). That produces the same multiset of values, but in sorted order. It does not preserve the original arrangement. If position matters, use the inverse indices instead.
Do these 3 things before closing this tab:
1Clear out junk files and repair common Windows errors2Fix the driver behind crashes, sound loss and screen glitches3Repair Windows errors before they cause bigger problemsMultidimensional inputs and the NumPy 2.0 change
NumPy 2.0 changed the shape of the inverse output for multidimensional inputs. The NumPy reference describes this change in its notes on np.unique. If your code must run on both older and newer releases, flatten the inverse array explicitly with inverse.reshape(-1) before using it for indexing. Confirm the expected shape against the NumPy version you are targeting, because a reshape that is correct in one release can be unnecessary in another.
Best Value
NaN handling and the sorted parameter
According to the current stable reference, equal_nan defaults to True, so repeated NaN values collapse into a single entry in the result. The parameter itself was introduced in NumPy 1.24.
The sorted parameter was added in NumPy 2.3. Its documented behavior with sorted=False is not a guarantee of any particular unsorted order: in practice the output may still come back sorted, and that behavior may change in future releases. If you need a specific order, sort the result yourself rather than relying on sorted=False.
Choosing the right call
Start by deciding what counts as one item: a scalar after flattening (default), a row (axis=0), or a column (axis=1). Then choose the extra outputs based on what you need back.
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
| Goal | Call | What you get back |
|---|---|---|
| Distinct scalar values | np.unique(a) |
Sorted array of unique values from the flattened input |
| Frequency of each value | np.unique(a, return_counts=True) |
Unique values plus counts aligned by position |
| Distinct rows | np.unique(a, axis=0, return_counts=True) |
Unique rows, sorted lexicographically, with row counts |
| Distinct columns | np.unique(a, axis=1) |
Unique columns, sorted lexicographically |
| Representative locations | np.unique(a, return_index=True) |
Index of the first occurrence of each unique value |
| Rebuild the original arrangement | np.unique(a, return_inverse=True) |
Index map from each element to its unique value |
Two cautions. Do not assume sorted=False yields a fixed unsorted order. And for multidimensional inverse results, check the shape against your NumPy version.
Quick Recap
Official references
- NumPy numpy.unique reference (stable, v2.5), covering parameters, return values, ordering, axis behavior, NaN handling, and version notes.
- NumPy beginner guide (stable, v2.5), with introductory examples of values, counts, unique rows, and unique columns.
“
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.




