2013-05-02 13 views
27

में मोड खोजने का सबसे प्रभावी तरीका मेरे पास 2 डी सरणी है जिसमें पूर्णांक (सकारात्मक या नकारात्मक दोनों) हैं। प्रत्येक पंक्ति किसी विशेष स्थानिक साइट के लिए समय के साथ मूल्यों का प्रतिनिधित्व करती है, जबकि प्रत्येक कॉलम किसी दिए गए समय के लिए विभिन्न स्थानिक साइटों के मानों का प्रतिनिधित्व करता है।numpy array

तो अगर सरणी की तरह है:

1 3 4 2 2 7 
5 2 2 1 4 1 
3 3 2 2 1 1 

परिणाम होना चाहिए

1 3 2 2 2 1 

नोट जब वहाँ मोड के लिए अनेक मान रहे हैं, (बेतरतीब ढंग से चुना) किसी भी एक साधन के रूप में सेट किया जा सकता है कि ।

मैं एक समय में कॉलम ढूंढने वाले मोड पर फिर से सक्रिय कर सकता हूं लेकिन मुझे उम्मीद थी कि ऐसा करने के लिए numpy में कुछ अंतर्निहित फ़ंक्शन हो सकता है। या यदि लूपिंग के बिना कुशलतापूर्वक खोजने के लिए कोई चाल है।

+0

http://docs.scipy.org/doc/scipy/reference/generated/scipy.stats.mstats.mode.html और यहां जवाब है: http://stackoverflow.com/questions/6252280/find - सबसे-लगातार-संख्या-में-एक-numpy-vector – tom10

+1

@ tom10: आपका मतलब है [scipy.stats.mode()] (http: //docs.scipy।संगठन/डॉक्टर/scipy/संदर्भ/जेनरेट/scipy.stats.mode.html # scipy.stats.mode), है ना? दूसरा एक मुखौटा सरणी आउटपुट लगता है। – fgb

+0

@fgb: ठीक है, सुधार के लिए धन्यवाद (और आपके उत्तर के लिए +1)। – tom10

उत्तर

52

चेक scipy.stats.mode() (@ tom10 की टिप्पणी से प्रेरित):

import numpy as np 
from scipy import stats 

a = np.array([[1, 3, 4, 2, 2, 7], 
       [5, 2, 2, 1, 4, 1], 
       [3, 3, 2, 2, 1, 1]]) 

m = stats.mode(a) 
print(m) 

आउटपुट:

ModeResult(mode=array([[1, 3, 2, 2, 1, 1]]), count=array([[1, 2, 2, 2, 1, 2]])) 

आप देख सकते हैं, यह रिटर्न दोनों मोड के साथ ही गिना जाता है। ,

[[1 3 2 2 1 1]] 
+3

तो अपने आप से कोई भी ऐसी कार्यक्षमता का समर्थन नहीं करता है? – Nik

+1

स्पष्ट रूप से नहीं, लेकिन [scipy का कार्यान्वयन केवल numpy पर निर्भर करता है] (http://stackoverflow.com/questions/12399107/alternative-to-scipy-mode-function-in-numpy), तो आप बस उस कोड को अपने प्रतिलिपि बना सकते हैं अपना काम – fgb

+5

बस एक नोट, जो भविष्य में इसे देखते हैं: आपको 'scipy.stats' को स्पष्ट रूप से आयात करने की आवश्यकता है, जब आप बस 'आयात scipy' करते हैं तो इसमें शामिल नहीं होता है। – ffledgling

10

यह एक मुश्किल समस्या है के बाद से वहाँ बहुत वहाँ बाहर नहीं है एक धुरी के साथ मोड गणना करने के लिए: आप m[0] के माध्यम से सीधे मोड का चयन कर सकते हैं:

print(m[0]) 

आउटपुट। समाधान 1-डी सरणी के लिए सीधे आगे है, जहां numpy.bincountnumpy.unique के साथ return_counts तर्क True के साथ आसान है। मैं देखता हूं कि सबसे आम एन-आयामी फ़ंक्शन scipy.stats.mode है, हालांकि यह निषिद्ध रूप से धीमा है - विशेष रूप से कई अद्वितीय मूल्यों के साथ बड़े सरणी के लिए। एक समाधान के रूप में, मैं इस समारोह विकसित किया है, और यह भारी का उपयोग करें:

import numpy 

def mode(ndarray, axis=0): 
    # Check inputs 
    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 array is 1-D and numpy version is > 1.9 numpy.unique will suffice 
    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 array 
    sort = numpy.sort(ndarray, axis=axis) 
    # Create array to transpose along the axis and get padding shape 
    transpose = numpy.roll(numpy.arange(ndim)[::-1], axis) 
    shape = list(sort.shape) 
    shape[axis] = 1 
    # Create a boolean array along strides of unique values 
    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() 
    # Count the stride lengths 
    counts = numpy.cumsum(strides) 
    counts[~strides] = numpy.concatenate([[0], numpy.diff(counts[~strides])]) 
    counts[strides] = 0 
    # Get shape of padded counts and slice to return to the original shape 
    shape = numpy.array(sort.shape) 
    shape[axis] += 1 
    shape = shape[transpose] 
    slices = [slice(None)] * ndim 
    slices[axis] = slice(1, None) 
    # Reshape and compute final counts 
    counts = counts.reshape(shape).transpose(transpose)[slices] + 1 

    # Find maximum counts and return modals/counts 
    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 

संपादित करें: परंतु एक पृष्ठभूमि का अधिक से अधिक मेमोरी-कुशल होने के लिए दृष्टिकोण को संशोधित किया

3

this method, एप्पल पर विस्तार डेटा के मोड को खोजने के लिए जहां आपको वास्तविक सरणी के सूचकांक की आवश्यकता हो सकती है यह देखने के लिए कि वितरण के केंद्र से मूल्य कितना दूर है। जब लेन

(_, idx, counts) = np.unique(a, return_index=True, return_counts=True) 
index = idx[np.argmax(counts)] 
mode = a[index] 

मोड त्यागने के लिए याद रखें (np.argmax (मायने रखता है))> 1, अगर यह वास्तव में आपके डेटा के मध्य वितरण का प्रतिनिधि है आप जाँच कर सकते हैं कि क्या यह आपके मानक विचलन के अंदर गिर जाता है भी मान्य करने के लिए मध्यान्तर।