2009-12-14 18 views
29

अगर मैं दो समानांतर सूचियों है और पहले में तत्वों के आदेश से उन्हें क्रमबद्ध करना चाहते हैं, यह बहुत आसान है:मैं समांतर numpy arrays "zip sort" कैसे कर सकता हूं?

>>> a = [2, 3, 1] 
>>> b = [4, 6, 2] 
>>> a, b = zip(*sorted(zip(a,b))) 
>>> print a 
(1, 2, 3) 
>>> print b 
(2, 4, 6) 

मैं एक ही NumPy सरणी का उपयोग कर सकते कैसे उन्हें पारंपरिक अजगर सूचियों में खोल के बिना ?

+1

@YGA, क्या आपके इनपुट सरणी में "ए" के पास कभी-कभी अद्वितीय अद्वितीय मूल्य होंगे? यदि हां, तो आप उस मामले में कैसे व्यवहार करना पसंद करेंगे? मनमाना आदेश? स्थिर प्रकार? सरणी "बी" में संबंधित मानों का उपयोग कर माध्यमिक क्रम? –

उत्तर

40

b[a.argsort()] चाल करना चाहिए।

यहां बताया गया है कि यह कैसे काम करता है। सबसे पहले आपको एक क्रमपरिवर्तन खोजने की आवश्यकता है जो एक प्रकार है।

>>> a = numpy.array([2, 3, 1]) 
>>> p = a.argsort() 
>>> p 
[2, 0, 1] 

आप आसानी से देख सकते हैं कि यह सही है:

>>> a[p] 
array([1, 2, 3]) 

अब लागू ही क्रमचय ख को argsort एक विधि है कि इस गणना करता है।

>>> b = numpy.array([4, 6, 2]) 
>>> b[p] 
array([2, 4, 6]) 
+2

यह "सहायक सॉर्टिंग" के लिए 'बी' का उपयोग नहीं करता है, उदाहरण के लिए जब 'ए' में तत्व दोहराए जाते हैं। विवरण के लिए कृपया मेरा उत्तर देखें। –

+1

otoh, सहायक सॉर्टिंग हमेशा वांछित नहीं है। – tacaswell

19

यहाँ एक दृष्टिकोण है कि कोई मध्यवर्ती अजगर सूचियों बनाता है, हालांकि यह छंटाई के लिए उपयोग करने के लिए एक NumPy "रिकॉर्ड सरणी" की आवश्यकता है है। यदि आपके दो इनपुट एरे वास्तव में संबंधित हैं (स्प्रेडशीट में कॉलम की तरह) तो यह हर समय दो अलग-अलग सरणी रखने के बजाए सामान्य रूप से आपके डेटा से निपटने का एक फायदेमंद तरीका खोल सकता है, इस मामले में आपके पास पहले से ही होगा एक रिकॉर्ड सरणी और आपकी मूल समस्या का उत्तर केवल आपके सरणी पर सॉर्ट() को कॉल करके किया जाएगा।

यह एक रिकार्ड सरणी में दोनों सरणियों पैकिंग के बाद एक in-place sort करता है:

>>> from numpy import array, rec 
>>> a = array([2, 3, 1]) 
>>> b = array([4, 6, 2]) 
>>> c = rec.fromarrays([a, b]) 
>>> c.sort() 
>>> c.f1 # fromarrays adds field names beginning with f0 automatically 
array([2, 4, 6]) 

संपादित rec.fromarrays() सादगी के लिए उपयोग करने के लिए, अनावश्यक dtype, डिफ़ॉल्ट सॉर्ट कुंजी उपयोग, उपयोग डिफ़ॉल्ट फ़ील्ड नामों को छोड़ निर्दिष्ट करने के बजाय (this example पर आधारित)।

+0

धन्यवाद! मैं वास्तव में चाहता हूं कि मैं दो उत्तरों स्वीकार कर सकूं। यह कम सरल लेकिन अधिक सामान्य है। मैंने इसे ऊपर उठाया है, कम से कम मैं कर सकता था :-) – YGA

2

यह आप जो चाहते हैं उसे करने का सबसे सरल और सबसे सामान्य तरीका हो सकता है। (मैंने यहां तीन सरणी का उपयोग किया था, लेकिन यह किसी भी आकार के सरणी पर काम करेगा, चाहे दो कॉलम या दो सौ)।

import numpy as NP 
fnx = lambda : NP.random.randint(0, 10, 6) 
a, b, c = fnx(), fnx(), fnx() 
abc = NP.column_stack((a, b, c)) 
keys = (abc[:,0], abc[:,1])   # sort on 2nd column, resolve ties using 1st col 
indices = NP.lexsort(keys)  # create index array 
ab_sorted = NP.take(abc, indices, axis=0) 

एक मोड़ डब्ल्यू/lexsort आप उलटे क्रम में कुंजी निर्दिष्ट करने के लिए है कि, जैसे कि, पहली बार अपने प्राथमिक कुंजी दूसरे और अपने माध्यमिक कुंजी डाल है। मेरे उदाहरण में, मैं दूसरे कॉलम का उपयोग प्राथमिक कुंजी के रूप में सॉर्ट करना चाहता हूं, इसलिए मैं इसे दूसरी सूची देता हूं; पहला स्तंभ केवल संबंधों को हल करता है, लेकिन यह पहले सूचीबद्ध है)।

+0

अच्छा पकड़ ब्रेंडन, धन्यवाद। – doug

संबंधित मुद्दे