2016-01-19 4 views
6

मुझे पता है कि मैं के साथ मिनट या अधिकतम मान प्राप्त कर सकते हैं: एक numpy मैट्रिक्स/वेक्टर से बाहरnumpy array से अधिकतम या न्यूनतम n-elements प्राप्त करें? (अधिमानतः चपटा नहीं)

max(matrix) 
min(matrix) 

। उन वैल के सूचकांक द्वारा लौटाया जाता है:

argmax(matrix) 
argmin(matrix) 

तो उदा। जब मैं एक 5x5 मैट्रिक्स है:

a = np.arange(5*5).reshape(5, 5) + 10 

# array([[10, 11, 12, 13, 14], 
#  [15, 16, 17, 18, 19], 
#  [20, 21, 22, 23, 24], 
#  [25, 26, 27, 28, 29], 
#  [30, 31, 32, 33, 34]]) 

मैं कर सकता मिल के माध्यम से अधिकतम मूल्य:

In [86]: np.max(a) # getting the max-value out of a 
Out[86]: 34 

In [87]: np.argmax(a) # index of max-value 34 is 24 if array a were flattened 
Out[87]: 24 

... लेकिन क्या सबसे कारगर तरीका अधिकतम या न्यूनतम एन-तत्व प्राप्त करने के लिए है?

तो मान लें कि से मैं 5 उच्चतम और 5 सबसे कम तत्व प्राप्त करना चाहता हूं। यह मुझे अपने सूचकांक के लिए [20, 21, 22, 23, 24] क्रमशः 5 उच्चतम मानों के लिए [30, 31, 32, 33, 34] वापस कर देना चाहिए। 5 सबसे कम मूल्यों के सूचकांक के लिए 5 सबसे कम मूल्यों और [0, 1, 2, 3, 4] के लिए [10, 11, 12, 13, 14]

इसके लिए एक कुशल, उचित समाधान क्या होगा?

मेरा पहला विचार था सपाट और सरणी छंटाई और आखिरी और पहले 5 मूल्यों लेने। बाद में मैं उन मूल्यों के सूचकांक के लिए मूल 2 डी मैट्रिक्स के माध्यम से खोज करता हूं। हालांकि यह प्रक्रिया फ़्लैटनिंग + सॉर्टिंग बहुत ही कुशल नहीं है ... क्या किसी को तेज़ समाधान पता है?

इसके अतिरिक्त मैं मूल 2 डी सरणी के सूचकांक और फ़्लैटनिंग नहीं करना चाहता हूं। तो 24 के बजाय np.argmax(a) पर लौटाया गया है, मुझे (4, 4) होना चाहिए।

+1

'np.partition' (और सूचकांक के लिए' np.argpartition') ओ (एन) - मुझे लगता है कि यह सबसे अच्छा है जिसके लिए आप यहां उम्मीद कर सकते हैं।इसके लिए पहले सरणी को घुमाने की आवश्यकता है (इसे केवल एक दृश्य बनाना चाहिए और इसलिए कोई प्रदर्शन जुर्माना नहीं लेना चाहिए)। फिर आप अपने मूल सरणी में 2 डी सूचकांक प्राप्त करने के लिए 'unravel_index' का उपयोग कर सकते हैं। इस मामले में –

उत्तर

4

किसी सरणी में सबसे बड़े या छोटे मूल्यों के सूचकांक प्राप्त करने का मानक तरीका np.argpartition का उपयोग करना है। यह फ़ंक्शन एक इंट्रोसेलेक्ट एल्गोरिदम का उपयोग करता है और रैखिक जटिलता के साथ चलता है - यह बड़े सरणी के लिए पूरी तरह से सॉर्ट करने से बेहतर प्रदर्शन करता है (जो आमतौर पर ओ (एन लॉग एन) होता है)।

डिफ़ॉल्ट रूप से यह फ़ंक्शन सरणी के अंतिम धुरी के साथ काम करता है। एक संपूर्ण सरणी पर विचार करने के लिए, आपको ravel() का उपयोग करने की आवश्यकता है।

>>> a = np.random.randint(0, 100, size=(5, 5)) 
>>> a 
array([[60, 68, 86, 66, 9], 
     [66, 26, 83, 87, 50], 
     [41, 26, 0, 55, 9], 
     [57, 80, 71, 50, 22], 
     [94, 30, 95, 99, 76]]) 

तब (चपटा) 2 डी सरणी में पांच सबसे बड़े मूल्यों का सूचकांक प्राप्त करने के लिए, का उपयोग करें:

>>> i = np.argpartition(a.ravel(), -5)[-5:] # argpartition(a.ravel(), 5)[:5] for smallest 
>>> i 
array([ 2, 8, 22, 23, 20]) 

इसी 2 डी सूचकांक वापस पाने के लिए उदाहरण के लिए, यहाँ एक यादृच्छिक सरणी a है a में इन पदों की, unravel_index का उपयोग करें:

>>> i2d = np.unravel_index(i, a.shape) 
>>> i2d 
(array([0, 1, 4, 4, 4]), array([2, 3, 2, 3, 0])) 

तब का अनुक्रमण ai2d के साथ वापस कर देता है पांच सबसे बड़े मूल्य:

>>> a[i2d] 
array([86, 87, 95, 99, 94]) 
+0

, सॉर्टिंग तेज़ है: '% timeit a.ravel.argpartition (-5) -> 5.5 μs' और'% timeit a.ravel.argsort() -> 3.8 μs'। लेकिन निश्चित रूप से बड़े सरणी के साथ, यह सही तरीका है। –