Numpy.array এ অনন্য সারি সন্ধান করুন


199

আমার একটিতে অনন্য সারি পাওয়া দরকার numpy.array

উদাহরণ স্বরূপ:

>>> a # I have
array([[1, 1, 1, 0, 0, 0],
       [0, 1, 1, 1, 0, 0],
       [0, 1, 1, 1, 0, 0],
       [1, 1, 1, 0, 0, 0],
       [1, 1, 1, 1, 1, 0]])
>>> new_a # I want to get to
array([[1, 1, 1, 0, 0, 0],
       [0, 1, 1, 1, 0, 0],
       [1, 1, 1, 1, 1, 0]])

আমি জানি যে আমি অ্যারে থেকে একটি সেট তৈরি করতে এবং লুপ করতে পারি, তবে আমি একটি কার্যকর খাঁটি numpyসমাধান খুঁজছি । আমি বিশ্বাস করি যে ডাটা টাইপ অকার্যকর সেট করার একটি উপায় আছে এবং তারপরে আমি কেবল ব্যবহার করতে পারি numpy.unique, তবে কীভাবে এটি কাজ করতে হয় তা আমি বুঝতে পারি না।


11
পান্ডাসের একটি ডেটা ফ্রেম.ড্রপ_ডুপ্লেকেট () পদ্ধতি রয়েছে। দেখুন stackoverflow.com/questions/12322779/pandas-unique-dataframe এবং pandas.pydata.org/pandas-docs/dev/generated/...
codeape

ধন্যবাদ, তবে আমি পান্ডা ব্যবহার করতে পারি না।
আকাওয়াল


1
@ অ্যান্ডি হেডেন, শিরোনাম থাকা সত্ত্বেও, এটি এই প্রশ্নের সদৃশ নয়। কোডাপের লিঙ্কটি যদিও একটি সদৃশ।
ওয়া ইয়িপ টুং

5
এই বৈশিষ্ট্যটি স্থানীয়ভাবে 1.13 এ চলেছে
এরিক

উত্তর:


114

NumPy 1.13 হিসাবে, যে কোনও এন-ডিমে অ্যারেতে অনন্য মানগুলির নির্বাচনের জন্য অক্ষটি বেছে নিতে পারেন। অনন্য সারি পেতে, কেউ এটি করতে পারেন:

unique_rows = np.unique(original_array, axis=0)


12
এই ফাংশনটি সম্পর্কে যত্নবান। ডুপ্লিকেট সারি মুছে ফেলাnp.unique(list_cor, axis=0) আপনাকে অ্যারে পেতে ; এটি মূল অ্যারেতে স্বতন্ত্র এমন উপাদানগুলিতে অ্যারে ফিল্টার করে না । উদাহরণস্বরূপ, এখানে দেখুন ..
ব্র্যাড সলোমন

নোট করুন যে আপনি যদি সারিটির মানগুলির ক্রম উপেক্ষা করে অনন্য সারিগুলি চান, তবে আপনি কলামগুলিতে প্রথমে মূল অ্যারেটি বাছাই করতে পারেন:original_array.sort(axis=1)
মার্ঙ্গেজিউর

139

তবুও আরেকটি সম্ভাব্য সমাধান

np.vstack({tuple(row) for row in a})

20
+1 এটি পরিষ্কার, সংক্ষিপ্ত এবং পাইথোনিক। গতি যদি আসল সমস্যা না হয় তবে এই ধরণের সমাধানগুলি এই প্রশ্নটির আইএমওর জটিল, উচ্চতর ভোটযুক্ত উত্তরের চেয়ে বেশি পছন্দ করা উচিত।
বিল চ্যাথাম

3
অসাধারণ! কোঁকড়া ধনুর্বন্ধনী বা সেট () ফাংশনটি কৌশলটি করে।
তিয়ান তিনি

2
@ গ্রেগ ভন উইঙ্কেল আপনি কি এমন কিছু প্রস্তাব দিতে পারেন যা কিছু এমন না যা আদেশ পরিবর্তন করে না?
লাশেতে জৈন

হ্যাঁ, তবে একক আদেশে নয়: x = []; [x.append (tuple (r)) r এর জন্য a যদি tuple (r) x এ নয়]; a_unique = অ্যারে (এক্স);
গ্রেগ ভন উইঙ্কেল

1
ফিউচারওয়্যারিং এড়ানোর জন্য সেটটিকে তালিকার মতো একটি তালিকায় রূপান্তর করুন: np.vstack(list({tuple(row) for row in AIPbiased[i, :, :]})) ফিউচার ওয়ার্নিং: স্ট্যাকের অ্যারেগুলি অবশ্যই "সিকোয়েন্স" টাইপ যেমন তালিকা বা টিপল হিসাবে পাস করতে হবে। নন-সিকোয়েন্স পুনরাবৃত্তির জন্য সমর্থন যেমন জেনারেটর NumPy 1.16 হিসাবে অবচয় করা হয়েছে এবং ভবিষ্যতে একটি ত্রুটি বাড়িয়ে তুলবে।
লিরিমিস্টার

111

স্ট্রাকচার্ড অ্যারে ব্যবহারের আরেকটি বিকল্প হ'ল এমন এক voidধরণের ভিউ ব্যবহার করে যা পুরো সারিতে একক আইটেমের সাথে মিলিত হয়:

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

b = np.ascontiguousarray(a).view(np.dtype((np.void, a.dtype.itemsize * a.shape[1])))
_, idx = np.unique(b, return_index=True)

unique_a = a[idx]

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

সম্পাদনা যোগ করা হয়েছে np.ascontiguousarray@ seberg সুপারিশ অনুসরণ। অ্যারেটি ইতিমধ্যে সামঞ্জস্যপূর্ণ না হলে এটি পদ্ধতিটি ধীর করবে।

সম্পাদনা করুন উপরেরগুলি কিছুটা বাড়িয়ে দেওয়া যেতে পারে, সম্ভবত স্বচ্ছতার ব্যয়ে, এগুলি করে:

unique_a = np.unique(b).view(a.dtype).reshape(-1, a.shape[1])

এছাড়াও, কমপক্ষে আমার সিস্টেমে, লেকসোর্ট পদ্ধতির চেয়ে পারফরম্যান্স অনুসারে এটি সমান বা আরও ভাল:

a = np.random.randint(2, size=(10000, 6))

%timeit np.unique(a.view(np.dtype((np.void, a.dtype.itemsize*a.shape[1])))).view(a.dtype).reshape(-1, a.shape[1])
100 loops, best of 3: 3.17 ms per loop

%timeit ind = np.lexsort(a.T); a[np.concatenate(([True],np.any(a[ind[1:]]!=a[ind[:-1]],axis=1)))]
100 loops, best of 3: 5.93 ms per loop

a = np.random.randint(2, size=(10000, 100))

%timeit np.unique(a.view(np.dtype((np.void, a.dtype.itemsize*a.shape[1])))).view(a.dtype).reshape(-1, a.shape[1])
10 loops, best of 3: 29.9 ms per loop

%timeit ind = np.lexsort(a.T); a[np.concatenate(([True],np.any(a[ind[1:]]!=a[ind[:-1]],axis=1)))]
10 loops, best of 3: 116 ms per loop

3
অনেক ধন্যবাদ. এই উত্তরটি যে আমি খুঁজছেন ছিল, আপনি ব্যাখ্যা করতে পারেন কি এই পদক্ষেপ চলছে: b = a.view(np.dtype((np.void, a.dtype.itemsize * a.shape[1])))?
আকাওয়াল

3
@ আকাওয়াল এটি np.voidসম্পূর্ণ সারিতে বাইটের সংখ্যা আকারের একটি ডেটা ধরণের সাথে আপনার ডেটার একটি ভিউ তৈরি করছে । এটির মতোই দুটি যা আপনার কাছে একটি সারণী থাকে np.uint8এবং এটি np.uint16s হিসাবে দেখতে পান যা প্রতিটি দুটি কলামকে একক একত্রিত করে তবে আরও নমনীয়।
জাইমে

3
@ জাইম, আপনি np.ascontiguousarrayসাধারণত নিরাপদে থাকার জন্য একটি বা অনুরূপ যোগ করতে পারেন (আমি জানি এটি তখন আরও কিছুটা সীমাবদ্ধ তবে প্রয়োজনীয়, তবে ...)। প্রত্যাশার মতো কাজ করার জন্য সারিগুলি অবশ্যই সংগত হতে হবে
seberg

2
@ConstantineEvans এটি একটি সাম্প্রতিক উপরন্তু হল: numpy 1.6 এ, চালানোর চেষ্টা np.uniqueএকটি অ্যারের উপর np.voidআয় যে টাইপ জন্য এর সাথে সম্পর্কিত একটি ত্রুটি বাস্তবায়িত হচ্ছে না mergesort করতে। এটি 1.7 তে সূক্ষ্মভাবে কাজ করে।
জয়মে

9
এটি লক্ষণীয় যে এই পদ্ধতিটি যদি ভাসমান পয়েন্ট সংখ্যার জন্য ব্যবহার করা হয় তবে এমন একটি ক্যাচ রয়েছে যা -0.সমান হিসাবে তুলনা করবে না +0., যখন একটি উপাদান-বাই-উপাদান তুলনা করতে হবে -0.==+0.(যেমন আইআই ফ্ল্যাট মান দ্বারা নির্দিষ্ট)। দেখুন stackoverflow.com/questions/26782038/...
tom10

29

আপনি যদি ধারাবাহিক টিপলস বা অন্য কোনও অনুরূপ ডেটা স্ট্রাকচারে রূপান্তরকরণের মেমরির ব্যয়টি এড়াতে চান, তবে আপনি নম্পির কাঠামোগত অ্যারেগুলি ব্যবহার করতে পারেন।

কৌশলটি হ'ল আপনার আসল অ্যারেটিকে একটি কাঠামোগত অ্যারে হিসাবে দেখতে হবে যেখানে প্রতিটি আইটেম মূল অ্যারের একটি সারির সাথে সম্পর্কিত। এটি কোনও অনুলিপি তৈরি করে না এবং এটি বেশ দক্ষ।

দ্রুত উদাহরণ হিসাবে:

import numpy as np

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

ncols = data.shape[1]
dtype = data.dtype.descr * ncols
struct = data.view(dtype)

uniq = np.unique(struct)
uniq = uniq.view(data.dtype).reshape(-1, ncols)
print uniq

কী চলছে তা বুঝতে, মধ্যস্থতাকারীর ফলাফলগুলি একবার দেখুন।

একবার আমরা জিনিসগুলিকে স্ট্রাকচার্ড অ্যারে হিসাবে দেখি, অ্যারের প্রতিটি উপাদান আপনার মূল অ্যারেতে সারি হয়। (মূলত, এটি টিপলগুলির তালিকার সাথে একই রকম ডেটা স্ট্রাকচার)

In [71]: struct
Out[71]:
array([[(1, 1, 1, 0, 0, 0)],
       [(0, 1, 1, 1, 0, 0)],
       [(0, 1, 1, 1, 0, 0)],
       [(1, 1, 1, 0, 0, 0)],
       [(1, 1, 1, 1, 1, 0)]],
      dtype=[('f0', '<i8'), ('f1', '<i8'), ('f2', '<i8'), ('f3', '<i8'), ('f4', '<i8'), ('f5', '<i8')])

In [72]: struct[0]
Out[72]:
array([(1, 1, 1, 0, 0, 0)],
      dtype=[('f0', '<i8'), ('f1', '<i8'), ('f2', '<i8'), ('f3', '<i8'), ('f4', '<i8'), ('f5', '<i8')])

একবার চালানোর পরে numpy.unique, আমরা একটি কাঠামোগত অ্যারে ফিরে পাবেন:

In [73]: np.unique(struct)
Out[73]:
array([(0, 1, 1, 1, 0, 0), (1, 1, 1, 0, 0, 0), (1, 1, 1, 1, 1, 0)],
      dtype=[('f0', '<i8'), ('f1', '<i8'), ('f2', '<i8'), ('f3', '<i8'), ('f4', '<i8'), ('f5', '<i8')])

আমাদের তখন একটি "সাধারণ" অ্যারে হিসাবে দেখতে হবে ( _শেষ গণনার ফলাফল সংরক্ষণ করে ipython, যার কারণে আপনি দেখছেন _.view...):

In [74]: _.view(data.dtype)
Out[74]: array([0, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 0])

এবং তারপরে একটি 2D অ্যারে পুনরায় আকার দিন ( -1এমন একটি স্থানধারক যা সারিগুলির সঠিক সংখ্যা গণনা করতে কপিগুলিকে বলবে, কলামগুলির সংখ্যা দিন):

In [75]: _.reshape(-1, ncols)
Out[75]:
array([[0, 1, 1, 1, 0, 0],
       [1, 1, 1, 0, 0, 0],
       [1, 1, 1, 1, 1, 0]])

স্পষ্টতই, আপনি যদি আরও সংক্ষিপ্ত হতে চান তবে আপনি এটি লিখতে পারতেন:

import numpy as np

def unique_rows(data):
    uniq = np.unique(data.view(data.dtype.descr * data.shape[1]))
    return uniq.view(data.dtype).reshape(-1, data.shape[1])

data = np.array([[1, 1, 1, 0, 0, 0],
                 [0, 1, 1, 1, 0, 0],
                 [0, 1, 1, 1, 0, 0],
                 [1, 1, 1, 0, 0, 0],
                 [1, 1, 1, 1, 1, 0]])
print unique_rows(data)

যার ফলাফল:

[[0 1 1 1 0 0]
 [1 1 1 0 0 0]
 [1 1 1 1 1 0]]

এটি আসলে খুব ধীর বলে মনে হচ্ছে, টিপলস ব্যবহার করার মতো প্রায় ধীর। এটির মতো স্ট্রাকচার্ড অ্যারে বাছাই করা ধীরে ধীরে ধীরে ধীরে।
cge

3
@ কেজি - বড় আকারের অ্যারে দিয়ে এটি ব্যবহার করে দেখুন। হ্যাঁ, একটি নমপি অ্যারে বাছাই করা তালিকা বাছাই করার চেয়ে ধীর। যদিও আপনি ndarrays ব্যবহার করছেন বেশিরভাগ ক্ষেত্রে গতিই মূল বিবেচনা নয়। এটি মেমরির ব্যবহার। টিউপসগুলির একটি তালিকা এই সমাধানের চেয়ে অনেক বেশি মেমরি ব্যবহার করবে । আপনার কাছে পর্যাপ্ত মেমরি থাকলেও, যুক্তিসঙ্গতভাবে বড় অ্যারে সহ, এটিকে টিপলগুলির তালিকায় রূপান্তর করা গতির সুবিধার চেয়ে বেশি ওভারহেড has
জো কিংটন

@ কেজি - আহ, আমি খেয়াল করিনি আপনি ব্যবহার করছেন lexsort। আমি ভেবেছিলাম আপনি টিপলগুলির একটি তালিকা ব্যবহার করার বিষয়ে উল্লেখ করছেন। হ্যাঁ, lexsortসম্ভবত এই ক্ষেত্রে ভাল বিকল্প। আমি এটি সম্পর্কে ভুলে গিয়েছিলাম, এবং একটি অত্যধিক জটিল সমাধানে ঝাঁপিয়ে পড়েছি।
জো কিংটন

20

np.uniqueযখন আমি এটিকে চালিত করি তখন np.random.random(100).reshape(10,10)সমস্ত অনন্য স্বতন্ত্র উপাদানগুলি ফেরত দেয় তবে আপনি অনন্য সারিগুলি চান, তাই প্রথমে আপনাকে সেগুলি টিউপসগুলিতে স্থাপন করা দরকার:

array = #your numpy array of lists
new_array = [tuple(row) for row in array]
uniques = np.unique(new_array)

আপনি কেবল যা চান তা করার জন্য কেবলমাত্র প্রকারগুলিই পরিবর্তন করতে দেখছি এবং আমি নিশ্চিত নই যে তালিকার পুনরাবৃত্তি টিউপলসে পরিবর্তিত হবে আপনার "লুপিং না করে" দিয়ে ঠিক আছে কিনা?


5
+1 এটি পরিষ্কার, সংক্ষিপ্ত এবং পাইথোনিক। গতি যদি আসল সমস্যা না হয় তবে এই ধরণের সমাধানগুলি এই প্রশ্নটির আইএমওর জটিল, উচ্চতর ভোটযুক্ত উত্তরের চেয়ে বেশি পছন্দ করা উচিত।
বিল চ্যাথাম

আমি এটি গ্রহণযোগ্য সমাধানের চেয়ে বেশি পছন্দ করি। গতি আমার পক্ষে কোনও সমস্যা নয় কারণ আমার কাছে কেবলমাত্র অনুরোধ অনুসারে < 100সারি রয়েছে। এটি সুনির্দিষ্টভাবে বর্ণনা করে যে সারিগুলিতে অনন্য কীভাবে সম্পাদন করা হয়।
রাইরিং

4
এটি আসলে আমার ডেটার জন্য কাজ করে না, uniquesএতে অনন্য উপাদান রয়েছে। সম্ভবত আমি এর প্রত্যাশিত আকারটি ভুল বুঝি array- আপনি কি এখানে আরও সুনির্দিষ্ট হতে পারেন?
ফুবার

@ রায়ান-স্যাক্সে আমি পছন্দ করি যে এটি পাইথোনিক তবে এটি ভাল সমাধান নয় কারণ ফিরে আসা সারিটি uniquesসাজানো হয়েছে (এবং তাই সারিগুলির চেয়ে পৃথক array)। B = np.array([[1,2],[2,1]]); A = np.unique([tuple(row) for row in B]); print(A) = array([[1, 2],[1, 2]])
jmlaron

16

এনপি.উনিক একটি সমতল অ্যারে বাছাই করে কাজ করে, তারপরে প্রতিটি আইটেম আগেরটির সমান কিনা তা দেখে। চ্যাপ্টা না করে নিজেই এটি করা যায়:

ind = np.lexsort(a.T)
a[ind[np.concatenate(([True],np.any(a[ind[1:]]!=a[ind[:-1]],axis=1)))]]

এই পদ্ধতিটি টিপলগুলি ব্যবহার করে না এবং এখানে দেওয়া অন্যান্য পদ্ধতির তুলনায় খুব দ্রুত এবং সহজ হওয়া উচিত।

দ্রষ্টব্য: এর পূর্ববর্তী সংস্করণটির ঠিক পরে [, যার অর্থ ভুল সূচকগুলি ব্যবহৃত হয়েছিল। এছাড়াও, জো Kington একটি ভাল পয়েন্ট যে এই তোলে না অন্তর্বর্তী কপি বিভিন্ন ভুলবেন না। নিম্নলিখিত পদ্ধতিটি একটি সাজানো অনুলিপি তৈরি করে এবং তারপরে এর ব্যবহারগুলি ব্যবহার করে কম করে তোলে:

b = a[np.lexsort(a.T)]
b[np.concatenate(([True], np.any(b[1:] != b[:-1],axis=1)))]

এটি দ্রুত এবং কম স্মৃতি ব্যবহার করে।

এছাড়াও, যদি আপনি অ্যারেটিতে কতগুলি মাত্রা নির্বিশেষে কোনও নাদার্রে অনন্য সারিগুলি সন্ধান করতে চান তবে নিম্নলিখিতগুলি কাজ করবে:

b = a[lexsort(a.reshape((a.shape[0],-1)).T)];
b[np.concatenate(([True], np.any(b[1:]!=b[:-1],axis=tuple(range(1,a.ndim)))))]

একটি আকর্ষণীয় অবশিষ্ট বিষয় হ'ল যদি আপনি একটি স্বেচ্ছাসেবী-মাত্রা অ্যারের একটি স্বেচ্ছাসেবক অক্ষ বরাবর / অনন্য বাছাই করতে চান, এমন কিছু যা আরও কঠিন।

সম্পাদনা:

গতির পার্থক্য প্রদর্শনের জন্য, আমি উত্তরে বর্ণিত তিনটি পৃথক পদ্ধতির আইপথনে কয়েকটি পরীক্ষা চালিয়েছি। সঙ্গে আপনার সঠিক একটি, সেখানে, অত্যধিক একটি পার্থক্য নয় যদিও এই সংস্করণে একটি বিট দ্রুততর:

In [87]: %timeit unique(a.view(dtype)).view('<i8')
10000 loops, best of 3: 48.4 us per loop

In [88]: %timeit ind = np.lexsort(a.T); a[np.concatenate(([True], np.any(a[ind[1:]]!= a[ind[:-1]], axis=1)))]
10000 loops, best of 3: 37.6 us per loop

In [89]: %timeit b = [tuple(row) for row in a]; np.unique(b)
10000 loops, best of 3: 41.6 us per loop

বৃহত্তর এগুলির সাথে, তবে এই সংস্করণটি অনেক বেশি দ্রুত শেষ হচ্ছে:

In [96]: a = np.random.randint(0,2,size=(10000,6))

In [97]: %timeit unique(a.view(dtype)).view('<i8')
10 loops, best of 3: 24.4 ms per loop

In [98]: %timeit b = [tuple(row) for row in a]; np.unique(b)
10 loops, best of 3: 28.2 ms per loop

In [99]: %timeit ind = np.lexsort(a.T); a[np.concatenate(([True],np.any(a[ind[1:]]!= a[ind[:-1]],axis=1)))]
100 loops, best of 3: 3.25 ms per loop

খুব সুন্দর! সাইড নোটে, যদিও এটি বেশ কয়েকটি মধ্যস্থ কপি করে। (যেমন a[ind[1:]]একটি অনুলিপি, ইত্যাদি) অন্যদিকে, আপনি মেষ না শেষ হওয়া পর্যন্ত আপনার সমাধানটি সাধারণত আমার থেকে ২-৩০x দ্রুত হয়।
জো কিংটন

ভাল যুক্তি. যেমনটি দেখা যাচ্ছে, কেবল সূচকগুলি ব্যবহার করে মধ্যস্থতাকারী অনুলিপিগুলি বের করার আমার প্রচেষ্টাটি আমার পদ্ধতিটিকে আরও মেমরি ব্যবহার করেছে এবং অ্যারের একটি সাজানো অনুলিপি তৈরির চেয়ে ধীরে ধীরে শেষ হবে, যেমন__সোর্টার্ড [1:] a_sort এর অনুলিপি নয় ।
cge

কি dtypeআপনার সময় হবে? আমি মনে করি আপনি এটি ভুল পেয়েছেন। আমার সিস্টেমে, np.uniqueআমার উত্তরে বর্ণিত হিসাবে কল করা আপনার দুটি স্বাদের মধ্যে দুটি ব্যবহারের চেয়ে কিছুটা দ্রুত np.lexsort। এবং প্রায় 5x দ্রুত হয় যদি জ্ঞানগুলি আবিষ্কার করতে অ্যারের আকার হয় (10000, 100)। এমনকি যদি আপনি np.uniqueকিছু (নাবালিক) কার্যকরকরণের সময়কে ছাঁটাই করতে পুনরায় সংশোধন করার সিদ্ধান্ত নেন np.anyতবে কলামগুলির তুলনা, বিশেষত উচ্চতর কলামের তুলনায় কল করার চেয়ে প্রতিটি সারিকে একক বস্তুতে ভাঙ্গতে দ্রুত তুলনা চলে runs
জাইমে

@ কেজি: আপনি সম্ভবত 'এনপি.নাই' অর্থ স্ট্যান্ডার্ড 'যে কোনও' ব্যবহারের পরিবর্তে কীওয়ার্ড আর্গুমেন্ট গ্রহণ করবেন না meant
এম তোয়া

@ জাইম - আমি বিশ্বাস করি dtypeযে ন্যায়বাদী a.dtype, অর্থাত্ ডেটা ধরণের ডেটা টাইপ দেখা হচ্ছে, যেমনটি তার উত্তরটিতে জো কিংটন করেছিলেন। যদি অনেকগুলি কলাম থাকে তবে জিনিসগুলিকে দ্রুত রাখার আর একটি (অপূর্ণ!) উপায় lexsortহল কয়েকটি কলামগুলিতে কেবল সাজানো। এটি ডেটা-নির্দিষ্ট কারণ কোনও কলামগুলি পুরোপুরিভাবে সাজানোর জন্য পর্যাপ্ত বৈকল্পিক সরবরাহ করে তা জানতে হবে needs যেমন a.shape = (60000, 500)- সাজানোর প্রথম 3 কলাম করুন: ind = np.lexsort((a[:, 2], a[:, 1], a[:, 0]))। সময় সাশ্রয় মোটামুটি যথেষ্ট, তবে পুনরায় অস্বীকৃতি: এটি সব ক্ষেত্রেই ধরা নাও পারে - এটি ডেটার উপর নির্ভর করে।
n1k31t4

9

@ গ্রেগ পাইথোনিক উত্তরের জন্য এখানে আরও একটি প্রকরণ রয়েছে

np.vstack(set(map(tuple, a)))

9

আমি গতির জন্য প্রস্তাবিত বিকল্পটির তুলনা করেছি এবং এটি পেয়েছি, uniqueআশ্চর্যরূপে , অকার্যকর দৃশ্যের সমাধানটি আর্গুমেন্টের uniqueসাথে নম্পটির নেটিভের চেয়ে কিছুটা দ্রুত axis। আপনি যদি গতি খুঁজছেন, আপনি চাইবেন

numpy.unique(
    a.view(numpy.dtype((numpy.void, a.dtype.itemsize*a.shape[1])))
    ).view(a.dtype).reshape(-1, a.shape[1])

এখানে চিত্র বর্ণনা লিখুন


প্লটটি পুনরুত্পাদন করার কোড:

import numpy
import perfplot


def unique_void_view(a):
    return numpy.unique(
        a.view(numpy.dtype((numpy.void, a.dtype.itemsize*a.shape[1])))
        ).view(a.dtype).reshape(-1, a.shape[1])


def lexsort(a):
    ind = numpy.lexsort(a.T)
    return a[ind[
        numpy.concatenate((
            [True], numpy.any(a[ind[1:]] != a[ind[:-1]], axis=1)
            ))
        ]]


def vstack(a):
    return numpy.vstack({tuple(row) for row in a})


def unique_axis(a):
    return numpy.unique(a, axis=0)


perfplot.show(
    setup=lambda n: numpy.random.randint(2, size=(n, 20)),
    kernels=[unique_void_view, lexsort, vstack, unique_axis],
    n_range=[2**k for k in range(15)],
    logx=True,
    logy=True,
    xlabel='len(a)',
    equality_check=None
    )

1
খুব সুন্দর উত্তর, একটি ছোটখাটো বক্তব্য vstack_dict:, কখনও ডিক ব্যবহার করে না, কোঁকড়ানো ধনুর্বন্ধনী একটি সেট বোঝা এবং তাই এর আচরণটি প্রায় সমান vstatck_set। যেহেতু, vstack_dictপারফরম্যান্স লাইনটি গ্রাফিক গ্রাফের জন্য অনুপস্থিত, দেখে মনে হচ্ছে এটি কেবলমাত্র vstack_setপারফরম্যান্স গ্রাফ দ্বারা আচ্ছাদিত করা হচ্ছে , যেহেতু তারা এতটা অনুরূপ!
আকাওয়াল

উত্তরের জন্য ধন্যবাদ. আমি কেবল একটি vstackবৈকল্পিক অন্তর্ভুক্ত করার চক্রান্ত উন্নত করেছি ।
নিকো Schlömer

8

আমি এই উত্তরগুলির কোনও পছন্দ করি না কারণ কোনও রৈখিক বীজগণিত বা ভেক্টর স্পেস অর্থে ভাসমান-পয়েন্ট অ্যারে পরিচালনা করে না, যেখানে দুটি সারি "সমান" হওয়ার অর্থ "কিছুটা" এর মধ্যে। "।"। একটি উত্তর যা সহনশীলতার প্রান্তে রয়েছে, https://stackoverflow.com/a/26867764/500207 , থ্রেশহোল্ডটি উপাদান-ভিত্তিক এবং দশমিক যথার্থ উভয় হিসাবে গ্রহণ করেছে , যা কিছু ক্ষেত্রে কাজ করে তবে গণিতের মতো সাধারণ নয় সত্য ভেক্টর দূরত্ব।

এখানে আমার সংস্করণ:

from scipy.spatial.distance import squareform, pdist

def uniqueRows(arr, thresh=0.0, metric='euclidean'):
    "Returns subset of rows that are unique, in terms of Euclidean distance"
    distances = squareform(pdist(arr, metric=metric))
    idxset = {tuple(np.nonzero(v)[0]) for v in distances <= thresh}
    return arr[[x[0] for x in idxset]]

# With this, unique columns are super-easy:
def uniqueColumns(arr, *args, **kwargs):
    return uniqueRows(arr.T, *args, **kwargs)

উপরের পাবলিক-ডোমেন ফাংশনটি প্রতিটি জোড় সারির scipy.spatial.distance.pdistমধ্যে ইউক্লিডিয়ান (কাস্টমাইজযোগ্য) দূরত্ব খুঁজে পেতে ব্যবহার করে । তারপরে একে অপরের মধ্যে থাকা সারিগুলি সন্ধান করতে এটি প্রতিটি দূরত্বকে একটি পুরানো সাথে তুলনা করে এবং প্রতিটি- ক্লাস্টার থেকে কেবল একটি সারি দেয়।threshthreshthresh

ইঙ্গিত হিসাবে, দূরত্বটি metricইউক্লিডিয়ান হতে হবে না (ম্যানহাটন-আদর্শ) এবং (ভেক্টরগুলির মধ্যে কোণ ) pdistসহ সূক্ষ্ম দূরত্বগুলি গণনা করতে পারে ।cityblockcosine

যদি thresh=0(ডিফল্ট) হয়, তবে সারিগুলি "অনন্য" হিসাবে বিবেচনা করার জন্য বিট-হুটো হতে হবে। threshব্যবহারের জন্য অন্যান্য ভাল মানগুলি স্কেলড মেশিন-নির্ভুলতা, যেমন thresh=np.spacing(1)*1e3,।


সর্বোত্তম উত্তর. ধন্যবাদ। এটি এখন পর্যন্ত লেখা সবচেয়ে বেশি (গাণিতিক) সাধারণ উত্তর। এটি একটি ম্যাট্রিক্সকে এন-ডাইমেনশনাল স্পেসে ডেটা পয়েন্ট বা নমুনাগুলির একটি সেট হিসাবে বিবেচনা করে এবং একই বা অনুরূপ পয়েন্টগুলির একটি সংকলন (ইউক্যালিডিয়ান দূরত্ব বা অন্য কোনও পদ্ধতি দ্বারা নির্ধারিত মিল) খুঁজে বের করে। এই পয়েন্টগুলি ওভারল্যাপিং ডেটা পয়েন্ট বা খুব নিকটবর্তী পাড়া হতে পারে। শেষে, একই বা অনুরূপ পয়েন্টগুলির সংকলন একই সেটের অন্তর্ভুক্ত বিন্দুগুলির (কোনও প্রথম পয়েন্ট দ্বারা উপরের উত্তরে) দ্বারা প্রতিস্থাপিত হবে। এটি পয়েন্ট ক্লাউড থেকে অপ্রয়োজনীয়তা হ্রাস করতে সহায়তা করে।
সঁচিত

@ সংচিত আহা, এটি একটি ভাল বিষয়, পরিবর্তে "প্রথম" পয়েন্টটি বাছাইয়ের পরিবর্তে (আসলে এটি কার্যকরভাবে এলোমেলো হতে পারে, যেহেতু এটি পাইথন কীভাবে পয়েন্টগুলি একটিতে সংরক্ষণ করে set) উপর নির্ভর করে প্রতিটি threshআকারের পাড়ার প্রতিনিধি হিসাবে , ফাংশনটি অনুমতি দিতে পারে ব্যবহারকারী কীভাবে সেই বিন্দুটি বেছে নেবেন তা উল্লেখ করতে, উদাহরণস্বরূপ, "মিডিয়ান" বা সেন্ট্রয়েডের নিকটতম বিন্দু ইত্যাদি ব্যবহার করুন
আহমেদ ফ্যাসিহ

অবশ্যই। কোনো সন্দেহ নেই. আমি প্রথম পয়েন্টটি উল্লেখ করেছি যেহেতু এটিই আপনার প্রোগ্রামটি করছে যা সম্পূর্ণ সূক্ষ্ম।
সঁচিত

কেবল একটি সংশোধন — আমি ভুল করে উপরে বলেছি যে প্রতি- threshক্লাস্টারের জন্য যে সারিটি বেছে নেওয়া হবে তা নিরবচ্ছিন্ন প্রকৃতির কারণে এলোমেলো হবে set। অবশ্যই আমার পক্ষ থেকে একটি brainfart যে এর মধ্যে setইন্ডেক্সে দোকানে tuples যে হয় thresh-neighborhood, তাই এই findRows কাজ করে আসলে বিনিময়ে, প্রত্যেকের জন্য thresh-cluster, এটা প্রথম সারিতে।
আহমদ ফসিহ

3

drop_duplicatesপান্ডাস থেকে কেন ব্যবহার করবেন না :

>>> timeit pd.DataFrame(image.reshape(-1,3)).drop_duplicates().values
1 loops, best of 3: 3.08 s per loop

>>> timeit np.vstack({tuple(r) for r in image.reshape(-1,3)})
1 loops, best of 3: 51 s per loop

আমি আসলে এই উত্তরটি ভালবাসি। অবশ্যই, এটি সরাসরি আপা ব্যবহার করে না, তবে আমার কাছে এটি দ্রুত যাচাইয়ের সময় বোঝা সহজ।
নিটিলাক্স 12:57

3

Numpy_indexed প্যাকেজ (দাবিত্যাগ: আমি সংশ্লিষ্ট লেখক নই) গোপন সমাধান একটা চমৎকার মধ্যে জেইমি পোস্ট করেছে এবং পরীক্ষিত ইন্টারফেস, প্লাস আরো অনেক বৈশিষ্ট্য:

import numpy_indexed as npi
new_a = npi.unique(a)  # unique elements over axis=0 (rows) by default

1

টিপলগুলির একটি তালিকা প্রদত্ত এনপি.উনিক কাজ করে:

>>> np.unique([(1, 1), (2, 2), (3, 3), (4, 4), (2, 2)])
Out[9]: 
array([[1, 1],
       [2, 2],
       [3, 3],
       [4, 4]])

তালিকার একটি তালিকা সহ এটি উত্থাপন করে a TypeError: unhashable type: 'list'


আমার কাজ করে না বলে মনে হচ্ছে। প্রতিটি টিপল দুটি ফ্লোট সংখ্যার পরিবর্তে দুটি স্ট্রিং রয়েছে
এমজেপি

কাজ করে না, এটি টিপলস নয় এমন উপাদানগুলির তালিকা
ফিরিয়ে দেয়

1

এই পৃষ্ঠার উত্তরের ভিত্তিতে আমি একটি ফাংশন লিখেছি যা ম্যাটল্যাবের unique(input,'rows')ফাংশনটির সামর্থ্যকে প্রতিলিপি করে , স্বতন্ত্রতা পরীক্ষা করার জন্য সহনশীলতা স্বীকার করার জন্য অতিরিক্ত বৈশিষ্ট্য সহ। এছাড়া যেমন যে সূচকের ফেরৎ c = data[ia,:]এবং data = c[ic,:]। আপনি যদি কোনও ত্রুটি বা ত্রুটি দেখতে পান তবে রিপোর্ট করুন।

def unique_rows(data, prec=5):
    import numpy as np
    d_r = np.fix(data * 10 ** prec) / 10 ** prec + 0.0
    b = np.ascontiguousarray(d_r).view(np.dtype((np.void, d_r.dtype.itemsize * d_r.shape[1])))
    _, ia = np.unique(b, return_index=True)
    _, ic = np.unique(b, return_inverse=True)
    return np.unique(b).view(d_r.dtype).reshape(-1, d_r.shape[1]), ia, ic

1

@ জাইম দুর্দান্ত উত্তরের বাইরে, একটি সারি ভেঙে ফেলার আরেকটি উপায় হ'ল ব্যবহার করা a.strides[0](ধরে aনেওয়া সি-সংলগ্ন) যা সমান a.dtype.itemsize*a.shape[0]। তদ্ব্যতীত void(n)একটি শর্টকাট dtype((void,n))। আমরা এই সংক্ষিপ্ততম সংস্করণে অবশেষে পৌঁছেছি:

a[unique(a.view(void(a.strides[0])),1)[1]]

জন্য

[[0 1 1 1 0 0]
 [1 1 1 0 0 0]
 [1 1 1 1 1 0]]

0

3 ডি বা উচ্চতর বহুমাত্রিক নেস্টেড অ্যারেগুলির মতো সাধারণ উদ্দেশ্যে, এটি ব্যবহার করে দেখুন:

import numpy as np

def unique_nested_arrays(ar):
    origin_shape = ar.shape
    origin_dtype = ar.dtype
    ar = ar.reshape(origin_shape[0], np.prod(origin_shape[1:]))
    ar = np.ascontiguousarray(ar)
    unique_ar = np.unique(ar.view([('', origin_dtype)]*np.prod(origin_shape[1:])))
    return unique_ar.view(origin_dtype).reshape((unique_ar.shape[0], ) + origin_shape[1:])

যা আপনার 2D ডেটাসেটকে সন্তুষ্ট করে:

a = np.array([[1, 1, 1, 0, 0, 0],
       [0, 1, 1, 1, 0, 0],
       [0, 1, 1, 1, 0, 0],
       [1, 1, 1, 0, 0, 0],
       [1, 1, 1, 1, 1, 0]])
unique_nested_arrays(a)

দেয়:

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

3 ডি অ্যারে যেমন:

b = np.array([[[1, 1, 1], [0, 1, 1]],
              [[0, 1, 1], [1, 1, 1]],
              [[1, 1, 1], [0, 1, 1]],
              [[1, 1, 1], [1, 1, 1]]])
unique_nested_arrays(b)

দেয়:

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

জাইমে unique return_indexহিসাবে এটি ব্যবহার করা শেষ returnপংক্তিকে আরও সহজ করে তুলবে । কেবলমাত্র arডান অক্ষের সাথে অরজিনালকে সূচক করুন ।
এইচপিএলজ

0

এই উত্তরগুলির কোনওোটাই আমার পক্ষে কাজ করেনি। আমি ধরে নিচ্ছি যে আমার অনন্য সারিগুলিতে স্ট্রিং রয়েছে এবং সংখ্যা নেই। তবে অন্য থ্রেডের এই উত্তরটি কাজ করেছিল:

সূত্র: https://stackoverflow.com/a/38461043/5402386

আপনি .count () এবং .index () তালিকার পদ্ধতিগুলি ব্যবহার করতে পারেন

coor = np.array([[10, 10], [12, 9], [10, 5], [12, 9]])
coor_tuple = [tuple(x) for x in coor]
unique_coor = sorted(set(coor_tuple), key=lambda x: coor_tuple.index(x))
unique_count = [coor_tuple.count(x) for x in unique_coor]
unique_index = [coor_tuple.index(x) for x in unique_coor]

0

আমরা প্রকৃতপক্ষে mxn সংখ্যাযুক্ত নম্পপি অ্যারেটিকে এমএক্স 1 নম্পি স্ট্রিং অ্যারে রূপান্তর করতে পারি, দয়া করে নীচের ফাংশনটি ব্যবহার করে দেখুন, এটি numpy.unique এর মতো গণনা , বিপরীত_ডেক্স এবং ইত্যাদি সরবরাহ করে:

import numpy as np

def uniqueRow(a):
    #This function turn m x n numpy array into m x 1 numpy array storing 
    #string, and so the np.unique can be used

    #Input: an m x n numpy array (a)
    #Output unique m' x n numpy array (unique), inverse_indx, and counts 

    s = np.chararray((a.shape[0],1))
    s[:] = '-'

    b = (a).astype(np.str)

    s2 = np.expand_dims(b[:,0],axis=1) + s + np.expand_dims(b[:,1],axis=1)

    n = a.shape[1] - 2    

    for i in range(0,n):
         s2 = s2 + s + np.expand_dims(b[:,i+2],axis=1)

    s3, idx, inv_, c = np.unique(s2,return_index = True,  return_inverse = True, return_counts = True)

    return a[idx], inv_, c

উদাহরণ:

A = np.array([[ 3.17   9.502  3.291],
  [ 9.984  2.773  6.852],
  [ 1.172  8.885  4.258],
  [ 9.73   7.518  3.227],
  [ 8.113  9.563  9.117],
  [ 9.984  2.773  6.852],
  [ 9.73   7.518  3.227]])

B, inv_, c = uniqueRow(A)

Results:

B:
[[ 1.172  8.885  4.258]
[ 3.17   9.502  3.291]
[ 8.113  9.563  9.117]
[ 9.73   7.518  3.227]
[ 9.984  2.773  6.852]]

inv_:
[3 4 1 0 2 4 0]

c:
[2 1 1 1 2]

-1

সম্পূর্ণ তালিকাহীন ম্যাট্রিক্সকে একটি তালিকা হিসাবে পেতে দিন, তারপরে এই তালিকা থেকে সদৃশগুলি ফেলে দিন এবং অবশেষে আমাদের অনন্য তালিকাটিকে একটি অদ্ভুত ম্যাট্রিক্সে ফিরিয়ে দিন:

matrix_as_list=data.tolist() 
matrix_as_list:
[[1, 1, 1, 0, 0, 0], [0, 1, 1, 1, 0, 0], [0, 1, 1, 1, 0, 0], [1, 1, 1, 0, 0, 0], [1, 1, 1, 1, 1, 0]]

uniq_list=list()
uniq_list.append(matrix_as_list[0])

[uniq_list.append(item) for item in matrix_as_list if item not in uniq_list]

unique_matrix=np.array(uniq_list)
unique_matrix:
array([[1, 1, 1, 0, 0, 0],
       [0, 1, 1, 1, 0, 0],
       [1, 1, 1, 1, 1, 0]])

-3

সর্বাধিক সরল সমাধান হ'ল সারিগুলিকে স্ট্রিং করে একক আইটেম তৈরি করা। প্রতিটি সারি তারপরেই নিম্পি ব্যবহার করে তার স্বতন্ত্রতার জন্য সামগ্রিকভাবে তুলনা করা যেতে পারে। এই সমাধানটি সাধারণীকরণে সক্ষম - আপনার কেবল অন্য সংমিশ্রণের জন্য আপনার অ্যারে পুনরায় আকার এবং স্থানান্তর করতে হবে। প্রদত্ত সমস্যার সমাধান এখানে দেওয়া হল।

import numpy as np

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

uniques, index = np.unique([str(i) for i in original], return_index=True)
cleaned = original[index]
print(cleaned)    

দিতে হবে:

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

আমার নোবেল পুরস্কার মেইল ​​পাঠান


খুব অকার্যকর এবং ত্রুটিযুক্ত প্রবণ, যেমন বিভিন্ন প্রিন্ট অপশন সহ। অন্যান্য বিকল্পগুলি পরিষ্কারভাবে পছন্দসই।
মাইকেল

-3
import numpy as np
original = np.array([[1, 1, 1, 0, 0, 0],
                     [0, 1, 1, 1, 0, 0],
                     [0, 1, 1, 1, 0, 0],
                     [1, 1, 1, 0, 0, 0],
                     [1, 1, 1, 1, 1, 0]])
# create a view that the subarray as tuple and return unique indeies.
_, unique_index = np.unique(original.view(original.dtype.descr * original.shape[1]),
                            return_index=True)
# get unique set
print(original[unique_index])
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.