स्तंभ द्वारा NumPy में सॉर्टिंग सरणियाँ


336

मैं एनटीपी कॉलम द्वारा न्यूपी में एक सरणी को कैसे सॉर्ट कर सकता हूं?

उदाहरण के लिए,

a = array([[9, 2, 3],
           [4, 5, 6],
           [7, 0, 5]])

मैं दूसरे कॉलम द्वारा पंक्तियों को क्रमबद्ध करना चाहूंगा, जैसे कि मुझे वापस मिलें:

array([[7, 0, 5],
       [9, 2, 3],
       [4, 5, 6]])

8
यह वास्तव में एक बुरा उदाहरण है क्योंकि np.sort(a, axis=0)दिए गए मैट्रिक्स के लिए एक संतोषजनक समाधान होगा। मैंने एक बेहतर उदाहरण के साथ एक संपादन का सुझाव दिया था, लेकिन खारिज कर दिया गया था, हालांकि वास्तव में प्रश्न बहुत अधिक स्पष्ट होगा। उदाहरण a = numpy.array([[1, 2, 3], [6, 5, 2], [3, 1, 1]])वांछित आउटपुट के साथ कुछ होना चाहिएarray([[3, 1, 1], [1, 2, 3], [6, 5, 2]])
डेविड

29
डेविड, तुम सवाल का मुद्दा नहीं मिलता है। वह आदेश को प्रत्येक पंक्ति के भीतर रखना चाहता है।
मार्कोरोसी

@marcorossi मुझे बात नहीं मिली, लेकिन उदाहरण बहुत बुरी तरह से तैयार किया गया था क्योंकि, जैसा कि मैंने कहा, कई संभावित उत्तर थे (जो, हालांकि, ओपी के अनुरोध को संतुष्ट नहीं किया होगा)। मेरी टिप्पणी के आधार पर बाद में संपादित किया गया वास्तव में अनुमोदित किया गया है (मज़ेदार है कि मेरा खारिज कर दिया गया, हालांकि)। तो अब सब ठीक है।
डेविड

जवाबों:


141

@steve का जवाब वास्तव में इसे करने का सबसे सुरुचिपूर्ण तरीका है।

"सही" तरीके के लिए numpy.ndarray.sort का ऑर्डर कीवर्ड तर्क देखें

हालाँकि, आपको अपने सरणी को फ़ील्ड (एक संरचित सरणी) के साथ एक सरणी के रूप में देखना होगा।

"सही" तरीका काफी बदसूरत है यदि आपने शुरू में फ़ील्ड के साथ अपनी सरणी को परिभाषित नहीं किया ...

एक त्वरित उदाहरण के रूप में, इसे क्रमबद्ध करने और प्रतिलिपि वापस करने के लिए:

In [1]: import numpy as np

In [2]: a = np.array([[1,2,3],[4,5,6],[0,0,1]])

In [3]: np.sort(a.view('i8,i8,i8'), order=['f1'], axis=0).view(np.int)
Out[3]: 
array([[0, 0, 1],
       [1, 2, 3],
       [4, 5, 6]])

इसे क्रमबद्ध करने के लिए:

In [6]: a.view('i8,i8,i8').sort(order=['f1'], axis=0) #<-- returns None

In [7]: a
Out[7]: 
array([[0, 0, 1],
       [1, 2, 3],
       [4, 5, 6]])

@ स्टीव वास्तव में इसे करने का सबसे सुंदर तरीका है, जहाँ तक मुझे पता है ...

इस पद्धति का एकमात्र लाभ यह है कि "ऑर्डर" तर्क खोज द्वारा ऑर्डर करने के लिए फ़ील्ड की एक सूची है। उदाहरण के लिए, आप दूसरे कॉलम, फिर तीसरे कॉलम, फिर ऑर्डर = ['f1', 'f2', 'f0'] की आपूर्ति करके पहला कॉलम सॉर्ट कर सकते हैं।


3
मेरी numpy 1.6.1rc1 में, यह उठता हैValueError: new type not compatible with array.
Clippit

9
क्या यह सुविधा अनुरोध दर्ज करने के लिए समझ में आएगा कि "सही" तरीका कम बदसूरत बना दिया जाए?
एंडोलिथ

4
यदि सरणी में मान हैं तो क्या होगा float? क्या मुझे कुछ बदलना चाहिए?
मार्को

1
और हाइब्रिड प्रकार के लिए जैसे a = np.array([['a',1,2,3],['b',4,5,6],['c',0,0,1]])मुझे किस दृष्टिकोण का पालन करना चाहिए?
ePascoal

10
स्टीव के ऊपर इस पद्धति का एक प्रमुख लाभ यह है कि यह बहुत बड़ी सरणियों को जगह में क्रमबद्ध करने की अनुमति देता है। पर्याप्त रूप से बड़े सरणी के लिए, उन द्वारा लौटाए गए सूचकांकों में np.argsortकाफी मेमोरी हो सकती है, और उसके शीर्ष पर, एक सरणी के साथ अनुक्रमण भी उस सरणी की एक प्रति उत्पन्न करेगा जो क्रमबद्ध हो रही है।
अली_म

736

मुझे लगता है कि यह काम करता है: a[a[:,1].argsort()]

यह दूसरे कॉलम को इंगित करता है aऔर उसी के आधार पर इसे क्रमबद्ध करता है।


2
यह स्पष्ट नहीं है, 1यहाँ क्या है ? सूचकांक किसके द्वारा क्रमबद्ध किया जाना है?
orezvani

29
[:,1]का दूसरा कॉलम इंगित करता है a
स्टीव तोजा

60
यदि आप रिवर्स प्रकार चाहते हैं, तो इसे संशोधित करेंa[a[:,1].argsort()[::-1]]
स्टीवन सी। हॉवेल

1
सरल और काम करता है! इससे तेज है np.sortया नहीं?
वैक्लाव पाविल्क

14
मुझे यह पढ़ने में आसान लगता है:ind = np.argsort( a[:,1] ); a = a[ind]
poppie

32

स्टीव टोज़ा की विधि के अनुसार आप कई स्तंभों को क्रमबद्ध कर सकते हैं जैसे कि मर्जर्ट जैसे स्थिर प्रकार का उपयोग करके और सूचकांकों को कम से कम महत्वपूर्ण से सबसे महत्वपूर्ण स्तंभों तक छांटना:

a = a[a[:,2].argsort()] # First sort doesn't need to be stable.
a = a[a[:,1].argsort(kind='mergesort')]
a = a[a[:,0].argsort(kind='mergesort')]

यह कॉलम 0, फिर 1, फिर 2 के आधार पर बनता है।


4
फ़र्स्ट सॉर्ट को स्थिर होने की आवश्यकता क्यों नहीं है?
लिटिल बॉबी टेबल्स

10
अच्छा सवाल - स्थिर का अर्थ है कि जब कोई टाई होती है तो आप मूल क्रम को बनाए रखते हैं, और बिना फाइल के मूल क्रम अप्रासंगिक होता है।
जे जे

यह वास्तव में सुपर महत्वपूर्ण बिंदु लगता है। एक सूची है कि चुपचाप सॉर्ट नहीं होता बुरा होगा।
अनाड़ी बिल्ली

19

यदि कोई व्यक्ति अपने कार्यक्रमों के एक महत्वपूर्ण हिस्से में छंटाई का उपयोग करना चाहता है, तो विभिन्न प्रस्तावों के लिए एक प्रदर्शन तुलना है:

import numpy as np
table = np.random.rand(5000, 10)

%timeit table.view('f8,f8,f8,f8,f8,f8,f8,f8,f8,f8').sort(order=['f9'], axis=0)
1000 loops, best of 3: 1.88 ms per loop

%timeit table[table[:,9].argsort()]
10000 loops, best of 3: 180 µs per loop

import pandas as pd
df = pd.DataFrame(table)
%timeit df.sort_values(9, ascending=True)
1000 loops, best of 3: 400 µs per loop

तो, ऐसा लग रहा है कि आर्गन्स के साथ अनुक्रमण अब तक की सबसे तेज विधि है ...


19

से अजगर प्रलेखन विकी , मुझे लगता है कि आप कर सकते हैं:

a = ([[1, 2, 3], [4, 5, 6], [0, 0, 1]]); 
a = sorted(a, key=lambda a_entry: a_entry[1]) 
print a

आउटपुट है:

[[[0, 0, 1], [1, 2, 3], [4, 5, 6]]]

21
इस समाधान के साथ, एक को एक NumPy सरणी के बजाय एक सूची मिलती है, इसलिए यह हमेशा सुविधाजनक नहीं हो सकता है (अधिक मेमोरी लेता है, शायद धीमी है, आदि)।
एरिक ओ लेबिगॉट

यह "समाधान" एक कारक द्वारा सबसे अपवित्र उत्तर द्वारा धीमा है ... ठीक है, वास्तव में अनंत के करीब
Jiv

16

से NumPy मेलिंग सूची है, यहाँ एक और समाधान है:

>>> a
array([[1, 2],
       [0, 0],
       [1, 0],
       [0, 2],
       [2, 1],
       [1, 0],
       [1, 0],
       [0, 0],
       [1, 0],
      [2, 2]])
>>> a[np.lexsort(np.fliplr(a).T)]
array([[0, 0],
       [0, 0],
       [0, 2],
       [1, 0],
       [1, 0],
       [1, 0],
       [1, 0],
       [1, 2],
       [2, 1],
       [2, 2]])

3
सही सामान्यीकरण है a[np.lexsort(a.T[cols])]cols=[1]मूल प्रश्न में कहां ।
रेडियो नियंत्रित

5

मुझे भी ऐसी ही समस्या का समाधान करना पड़ा था।

मेरी समस्या:

मैं एक एसवीडी की गणना करना चाहता हूं और अवरोही क्रम में अपने आइजेनवेल्यूज़ को सॉर्ट करने की आवश्यकता है । लेकिन मैं eigenvalues ​​और eigenvectors के बीच मानचित्रण रखना चाहता हूं। मेरे आइजनवेल्स पहली पंक्ति में थे और उसी कॉलम में उसके नीचे संबंधित आइजनवेक्टर।

इसलिए मैं पहली पंक्ति द्वारा अवरोही क्रम में दो-आयामी सरणी कॉलम-वार को सॉर्ट करना चाहता हूं।

मेरा समाधान

a = a[::, a[0,].argsort()[::-1]]

यह कैसे काम करता है?

a[0,] केवल पहली पंक्ति है जिसे मैं क्रमबद्ध करना चाहता हूं।

अब मैं सूचकांकों के क्रम को प्राप्त करने के लिए आर्सगोर्ट का उपयोग करता हूं।

मैं उपयोग करता हूं [::-1]क्योंकि मुझे अवरोही क्रम की आवश्यकता है।

अंत में मैं a[::, ...]सही क्रम में कॉलम के साथ एक दृश्य प्राप्त करने के लिए उपयोग करता हूं ।


1

थोड़ा और जटिल lexsortउदाहरण - 1 कॉलम पर उतरते हुए, दूसरा 2 पर आरोही। के साथ चाल lexsortयह है कि यह पंक्तियों (इसलिए .T) पर सॉर्ट करता है , और अंतिम को प्राथमिकता देता है।

In [120]: b=np.array([[1,2,1],[3,1,2],[1,1,3],[2,3,4],[3,2,5],[2,1,6]])
In [121]: b
Out[121]: 
array([[1, 2, 1],
       [3, 1, 2],
       [1, 1, 3],
       [2, 3, 4],
       [3, 2, 5],
       [2, 1, 6]])
In [122]: b[np.lexsort(([1,-1]*b[:,[1,0]]).T)]
Out[122]: 
array([[3, 1, 2],
       [3, 2, 5],
       [2, 1, 6],
       [2, 3, 4],
       [1, 1, 3],
       [1, 2, 1]])

0

यहां सभी स्तंभों पर एक और समाधान दिया गया है ( जेजे के उत्तर का अधिक कॉम्पैक्ट तरीका );

ar=np.array([[0, 0, 0, 1],
             [1, 0, 1, 0],
             [0, 1, 0, 0],
             [1, 0, 0, 1],
             [0, 0, 1, 0],
             [1, 1, 0, 0]])

लेक्सोर्ट के साथ क्रमबद्ध करें,

ar[np.lexsort(([ar[:, i] for i in range(ar.shape[1]-1, -1, -1)]))]

आउटपुट:

array([[0, 0, 0, 1],
       [0, 0, 1, 0],
       [0, 1, 0, 0],
       [1, 0, 0, 1],
       [1, 0, 1, 0],
       [1, 1, 0, 0]])

0

बस सॉर्ट का उपयोग करते हुए, कोलम नंबर का उपयोग करें जिसके आधार पर आप सॉर्ट करना चाहते हैं।

a = np.array([1,1], [1,-1], [-1,1], [-1,-1]])
print (a)
a=a.tolist() 
a = np.array(sorted(a, key=lambda a_entry: a_entry[0]))
print (a)

0

यह एक पुराना सवाल है, लेकिन अगर आपको इसे 2 आयाम सरणियों से अधिक के लिए सामान्यीकृत करने की आवश्यकता है, तो यहां समाधान सामान्य से अधिक हो सकता है:

np.einsum('ij->ij', a[a[:,1].argsort(),:])

यह दो आयामों के लिए एक ओवरकिल है और a[a[:,1].argsort()]यह @ स्टीव के उत्तर के अनुसार पर्याप्त होगा, हालांकि उस उत्तर को उच्च आयामों के लिए सामान्यीकृत नहीं किया जा सकता है। आप इस प्रश्न में 3D सरणी का एक उदाहरण पा सकते हैं

आउटपुट:

[[7 0 5]
 [9 2 3]
 [4 5 6]]
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.