अपडेट करें
scipy.stats.mode
समारोह में काफी इस पोस्ट के बाद से अनुकूलित किया गया है, और सिफारिश की तरीका होगा
पुराना उत्तर
यह एक मुश्किल समस्या है, क्योंकि वहाँ एक अक्ष के साथ मोड की गणना करने के लिए बहुत कुछ नहीं है। समाधान 1-डी सरणियों के लिए सीधे आगे है, जहां numpy.bincount
आसान है, साथ ही numpy.unique
साथ return_counts
arg के रूप में True
। सबसे आम एन-आयामी फ़ंक्शन जो मैं देख रहा हूं वह scipy.stats.mode है, हालांकि यह निषेधात्मक रूप से धीमा है- विशेष रूप से कई अद्वितीय मूल्यों के साथ बड़े सरणियों के लिए। समाधान के रूप में, मैंने इस फ़ंक्शन को विकसित किया है, और इसका भारी उपयोग करता हूं:
import numpy
def mode(ndarray, axis=0):
ndarray = numpy.asarray(ndarray)
ndim = ndarray.ndim
if ndarray.size == 1:
return (ndarray[0], 1)
elif ndarray.size == 0:
raise Exception('Cannot compute mode on empty array')
try:
axis = range(ndarray.ndim)[axis]
except:
raise Exception('Axis "{}" incompatible with the {}-dimension array'.format(axis, ndim))
if all([ndim == 1,
int(numpy.__version__.split('.')[0]) >= 1,
int(numpy.__version__.split('.')[1]) >= 9]):
modals, counts = numpy.unique(ndarray, return_counts=True)
index = numpy.argmax(counts)
return modals[index], counts[index]
sort = numpy.sort(ndarray, axis=axis)
transpose = numpy.roll(numpy.arange(ndim)[::-1], axis)
shape = list(sort.shape)
shape[axis] = 1
strides = numpy.concatenate([numpy.zeros(shape=shape, dtype='bool'),
numpy.diff(sort, axis=axis) == 0,
numpy.zeros(shape=shape, dtype='bool')],
axis=axis).transpose(transpose).ravel()
counts = numpy.cumsum(strides)
counts[~strides] = numpy.concatenate([[0], numpy.diff(counts[~strides])])
counts[strides] = 0
shape = numpy.array(sort.shape)
shape[axis] += 1
shape = shape[transpose]
slices = [slice(None)] * ndim
slices[axis] = slice(1, None)
counts = counts.reshape(shape).transpose(transpose)[slices] + 1
slices = [slice(None, i) for i in sort.shape]
del slices[axis]
index = numpy.ogrid[slices]
index.insert(axis, numpy.argmax(counts, axis=axis))
return sort[index], counts[index]
परिणाम:
In [2]: a = numpy.array([[1, 3, 4, 2, 2, 7],
[5, 2, 2, 1, 4, 1],
[3, 3, 2, 2, 1, 1]])
In [3]: mode(a)
Out[3]: (array([1, 3, 2, 2, 1, 1]), array([1, 2, 2, 2, 1, 2]))
कुछ बेंचमार्क:
In [4]: import scipy.stats
In [5]: a = numpy.random.randint(1,10,(1000,1000))
In [6]: %timeit scipy.stats.mode(a)
10 loops, best of 3: 41.6 ms per loop
In [7]: %timeit mode(a)
10 loops, best of 3: 46.7 ms per loop
In [8]: a = numpy.random.randint(1,500,(1000,1000))
In [9]: %timeit scipy.stats.mode(a)
1 loops, best of 3: 1.01 s per loop
In [10]: %timeit mode(a)
10 loops, best of 3: 80 ms per loop
In [11]: a = numpy.random.random((200,200))
In [12]: %timeit scipy.stats.mode(a)
1 loops, best of 3: 3.26 s per loop
In [13]: %timeit mode(a)
1000 loops, best of 3: 1.75 ms per loop
संपादित करें: एक पृष्ठभूमि के अधिक प्रदान की और अधिक स्मृति कुशल होने के लिए दृष्टिकोण को संशोधित किया