NumPy
Python
Data Analysis
Arrays
Programming

Frequency counts for unique values in a NumPy array

ML System Design practice on Codemia

Design recommenders, ranking systems and training pipelines the way ML interviews actually ask for them, with worked solutions.

Practice ML system design

Introduction

The most common way to get frequency counts for values in a NumPy array is np.unique(..., return_counts=True). It is simple, vectorized, and works for many data types. The only real complication is choosing the right tool for the array you have: np.unique is general-purpose, while np.bincount can be faster for non-negative integers.

The standard solution: np.unique

np.unique can return both the sorted unique values and the number of times each value appears.

python
1import numpy as np
2
3arr = np.array([4, 2, 4, 1, 2, 4, 3])
4
5values, counts = np.unique(arr, return_counts=True)
6
7print(values)
8print(counts)

The two returned arrays line up by position. If values[0] is 1, then counts[0] is the frequency of 1.

This is the best default because it works for integers, floats, strings, and many other array types without special handling.

Build a mapping when that is easier to read

Sometimes you want a dictionary-like representation rather than parallel arrays.

python
1import numpy as np
2
3arr = np.array(["cat", "dog", "cat", "bird", "dog", "cat"])
4values, counts = np.unique(arr, return_counts=True)
5
6frequency_map = dict(zip(values.tolist(), counts.tolist()))
7print(frequency_map)

This is convenient for display, serialization, or code that expects keyed lookups. Just remember that the real counting work is still happening in NumPy.

Use np.bincount for non-negative integers

If your data is already a one-dimensional array of non-negative integers, np.bincount is often faster and simpler.

python
1import numpy as np
2
3arr = np.array([0, 2, 2, 3, 3, 3, 5], dtype=np.int64)
4counts = np.bincount(arr)
5
6print(counts)
7print("count of 3:", counts[3])

The output index is the value itself. So counts[3] tells you how many times 3 appears.

The tradeoff is that np.bincount is specialized. It is not for negative numbers, strings, or general mixed arrays.

Frequency counts along an axis

If you pass a multidimensional array to np.unique without an axis, NumPy flattens it first. That is often correct, but not always. When you want unique rows or unique columns, use the axis argument.

python
1import numpy as np
2
3arr = np.array([
4    [1, 2],
5    [1, 2],
6    [3, 4],
7    [1, 2],
8])
9
10rows, counts = np.unique(arr, axis=0, return_counts=True)
11
12print(rows)
13print(counts)

This counts repeated rows, not individual scalar values. That distinction matters in preprocessing pipelines and feature engineering.

Compare with pure Python tools

You can also use collections.Counter, especially if the data is already a Python list. But if the data is already in a NumPy array and you care about vectorized numeric workflows, np.unique usually fits better because it keeps the operation inside NumPy.

In short:

  • use np.unique for general arrays
  • use np.bincount for dense non-negative integer values
  • use Counter mainly when the data is not really in NumPy yet

Common Pitfalls

The most common mistake is forgetting that np.unique sorts the unique values. If you expected first-seen order, the output may look surprising.

Another issue is using np.bincount on data that contains negatives or non-integer values. That function is intentionally narrower than np.unique.

People also forget that multidimensional arrays are flattened by default. If the goal is to count unique rows, you need axis=0.

Finally, when building a dictionary from NumPy scalars, convert to Python values if you need clean JSON serialization or ordinary Python container behavior.

Summary

  • Use np.unique(arr, return_counts=True) as the default solution for frequency counts.
  • The returned values and counts arrays align by index.
  • Use np.bincount when the array contains non-negative integers and you want speed.
  • Be explicit about axis when counting rows or columns in multidimensional arrays.
  • Remember that np.unique returns sorted unique values, not first-seen order.

Related reading
Course
Intermediate
27 lessons
15 hours
DSA Fundamentals

Master algorithmic patterns and data structures through hands-on LeetCode-style problems - from arrays and hashing to dynamic programming and advanced graphs.

View the course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

ML System Design practice on Codemia

Design recommenders, ranking systems and training pipelines the way ML interviews actually ask for them, with worked solutions.

Practice ML system design

All Rights Reserved.