How to find most frequent values in numpy ndarray?
Use SciPy's mode function:
import numpy as np
from scipy.stats import mode
data = np.array([[[ 0, 1, 2, 3, 4],
[ 5, 6, 7, 8, 9],
[10, 11, 12, 13, 14],
[15, 16, 17, 18, 19]],
[[ 0, 1, 2, 3, 4],
[ 5, 6, 7, 8, 9],
[10, 11, 12, 13, 14],
[15, 16, 17, 18, 19]],
[[40, 40, 42, 43, 44],
[45, 46, 47, 48, 49],
[50, 51, 52, 53, 54],
[55, 56, 57, 58, 59]]])
print data
# find mode along the zero-th axis; the return value is a tuple of the
# modes and their counts.
print mode(data, axis=0)
To find the most frequent value of a flat array, use unique
, bincount
and argmax
:
arr = np.array([5, 4, -2, 1, -2, 0, 4, 4, -6, -1])
u, indices = np.unique(arr, return_inverse=True)
u[np.argmax(np.bincount(indices))]
To work with a multidimensional array, we don't need to worry about unique
, but we do need to use apply_along_axis
on bincount
:
arr = np.array([[5, 4, -2, 1, -2, 0, 4, 4, -6, -1],
[0, 1, 2, 2, 3, 4, 5, 6, 7, 8]])
axis = 1
u, indices = np.unique(arr, return_inverse=True)
u[np.argmax(np.apply_along_axis(np.bincount, axis, indices.reshape(arr.shape),
None, np.max(indices) + 1), axis=axis)]
With your data:
data = np.array([
[[ 0, 1, 2, 3, 4],
[ 5, 6, 7, 8, 9],
[10, 11, 12, 13, 14],
[15, 16, 17, 18, 19]],
[[ 0, 1, 2, 3, 4],
[ 5, 6, 7, 8, 9],
[10, 11, 12, 13, 14],
[15, 16, 17, 18, 19]],
[[40, 40, 42, 43, 44],
[45, 46, 47, 48, 49],
[50, 51, 52, 53, 54],
[55, 56, 57, 58, 59]]])
axis = 0
u, indices = np.unique(arr, return_inverse=True)
u[np.argmax(np.apply_along_axis(np.bincount, axis, indices.reshape(arr.shape),
None, np.max(indices) + 1), axis=axis)]
array([[ 0, 1, 2, 3, 4],
[ 5, 6, 7, 8, 9],
[10, 11, 12, 13, 14],
[15, 16, 17, 18, 19]])
NumPy 1.2, really? You can approximate np.unique(return_inverse=True)
reasonably efficiently using np.searchsorted
(it's an additional O(n log n), so shouldn't change the performance significantly):
u = np.unique(arr)
indices = np.searchsorted(u, arr.flat)
A slightly better solution in my opinion is the following
tmpL = np.array([3, 2, 3, 2, 5, 2, 2, 3, 3, 2, 2, 2, 3, 3, 2, 2, 3, 2, 3, 2])
unique, counts = np.unique(tmpL, return_counts=True)
return unique[np.argmax(counts)]
Using np.unique
we can get the count of each unique elements. The index of the max element in counts
will be the corresponding element in unique
.