কলাম অনুসারে 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
ডেভিড, আপনি প্রশ্নের বিন্দু পেতে না। তিনি প্রতিটি সারির মধ্যে ক্রম একই রাখতে চান।
মার্কোরোসি

@ মার্কোরোসি আমি বিষয়টিটি পেয়েছি, তবে উদাহরণটি খুব খারাপভাবেই তৈরি হয়েছিল কারণ যেমনটি আমি বলেছিলাম, একাধিক সম্ভাব্য উত্তর রয়েছে (যা তবে ওপিটির অনুরোধটি সন্তুষ্ট করতে পারে নি)। আমার মন্তব্যের উপর ভিত্তি করে পরবর্তী সম্পাদনাটি সত্যই অনুমোদিত হয়েছে (মজার বিষয়টি যদিও আমার প্রত্যাখ্যান হয়েছিল)। সুতরাং এখন সবকিছু ঠিক আছে।
ডেভিড

উত্তর:


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
আমার নকল 1.6.1rc1 এ এটি উত্থাপিত হয়ValueError: new type not compatible with array.
ক্লিপপিট

9
"সঠিক" উপায়টি কম কুরুচিপূর্ণ করা উচিত এমন কোনও বৈশিষ্ট্য অনুরোধটি ফাইল করা কি বোধগম্য হবে?
এন্ডোলিথ

4
অ্যারেতে মানগুলি কী হবে float? আমার কি কিছু পরিবর্তন করা উচিত?
মার্কো

1
এবং হাইব্রিড টাইপের জন্য a = np.array([['a',1,2,3],['b',4,5,6],['c',0,0,1]])আমার কী পদ্ধতির অনুসরণ করা উচিত?
ইপাসকোল

10
স্টিভের চেয়ে এই পদ্ধতির একটি বড় সুবিধা হ'ল এটি খুব বড় অ্যারেগুলিকে স্থানে বাছাই করতে দেয়। পর্যাপ্ত পরিমাণে অ্যারের জন্য, সূচিতাগুলি ফিরে আসা মেসেজগুলি np.argsortতাদের স্মৃতিতে যথেষ্ট পরিমাণে সময় নিতে পারে এবং তারপরে একটি অ্যারের সাথে সূচীকরণ করা হলেও অ্যারেটির অনুলিপিও সাজানো হচ্ছে।
ali_m

735

আমি মনে করি এটি কাজ করে: a[a[:,1].argsort()]

এটি দ্বিতীয় কলামকে ইঙ্গিত করে aএবং সেই অনুসারে এর ভিত্তিতে এটি সাজান।


2
এটি পরিষ্কার নয়, 1এখানে কী আছে? সূচকটি বাছাই করা হবে?
ওরেজভানি

29
[:,1]এর দ্বিতীয় কলামটি নির্দেশ করে a
স্টিভ তেজোয়া

60
যদি আপনি বিপরীত সাজান চান, এটি হতে সংশোধন করুনa[a[:,1].argsort()[::-1]]
স্টিভেন সি হাওয়েল

1
দেখতে সহজ এবং কাজ! এর চেয়ে দ্রুত np.sortবা না?
ভ্যাক্লাভ পাভালেক

14
আমি এটি পড়তে সহজ বলে মনে করি:ind = np.argsort( a[:,1] ); a = a[ind]
পপপি

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
ভাল প্রশ্ন - স্থিতিশীল মানে যখন কোনও টাই থাকে তখন আপনি মূল শৃঙ্খলা বজায় রাখবেন এবং অরসোর্ট করা ফাইলের মূল ক্রমটি অপ্রাসঙ্গিক।
জেজে

এটি সত্যিই অত্যন্ত গুরুত্বপূর্ণ পয়েন্ট মত মনে হচ্ছে। চুপচাপ বাছাই করে না এমন একটি তালিকা থাকা খারাপ হবে।
আনাড়ি বিড়াল

20

পাইথন ডকুমেন্টেশন উইকি থেকে আমার মনে হয় আপনি এটি করতে পারেন:

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]]]

20
এই সমাধানের মাধ্যমে, একটি নুমপি অ্যারের পরিবর্তে একটি তালিকা পেয়েছে, সুতরাং এটি সর্বদা সুবিধাজনক হতে পারে না (আরও স্মৃতি গ্রহণ করে, সম্ভবত ধীর হয় ইত্যাদি)।
এরিক হে লেবিগোট

18

যদি কেউ তাদের প্রোগ্রামগুলির সমালোচনামূলক অংশে বাছাইয়ের ব্যবহার করতে চায় তবে এখানে বিভিন্ন প্রস্তাবের জন্য পারফরম্যান্স তুলনা করা হয়েছে:

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

সুতরাং, দেখে মনে হচ্ছে আরগোসোর্টের সাথে সূচীকরণ এখন পর্যন্ত দ্রুত পদ্ধতি ...


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

আমারও একই সমস্যা ছিল।

আমার সমস্যা:

আমি একটি এসভিডি গণনা করতে চাই এবং আমার ইগেনভ্যালুগুলি ক্রমোন্নত ক্রম অনুসারে বাছাই করা দরকার । তবে আমি ইগেনভ্যালু এবং ইগেনভেেক্টরগুলির মধ্যে ম্যাপিংটি রাখতে চাই। আমার ইগেনভ্যালুগুলি প্রথম সারিতে ছিল এবং একই কলামে এর নীচে সংশ্লিষ্ট আইজেনভেেক্টর ছিল।

সুতরাং আমি প্রথম সারিটির উত্থানের ক্রমে একটি দ্বি-মাত্রিক অ্যারে কলাম-অনুসারে বাছাই করতে চাই।

আমার সমাধান

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

তাহলে এটা কিভাবে কাজ করে?

a[0,] আমি কেবল প্রথম সারিতেই বাছাই করতে চাই।

সূচীর ক্রম পেতে এখন আমি আরগোর্ট ব্যবহার করি।

আমি ব্যবহার করি [::-1]কারণ আমার ক্রমবর্ধমান ক্রম দরকার।

শেষ অবধি আমি a[::, ...]কলামগুলি ডান ক্রমে দেখতে পেয়েছি ।


1

আরও কিছু জটিল lexsortউদাহরণ - 1 ম কলামে অবতরণ, দ্বিতীয়ত দ্বিতীয় দিকে আরোহণ। কৌশলগুলি 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]])

Lexsort দিয়ে বাছাই করুন,

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()]@ স্টিভের উত্তরে যথেষ্ট হবে তবে উত্তরটি উচ্চ মাত্রায় সাধারণ করা যায় না। আপনি এই প্রশ্নের মধ্যে 3 ডি অ্যারের উদাহরণ খুঁজে পেতে পারেন

আউটপুট:

[[7 0 5]
 [9 2 3]
 [4 5 6]]
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.