অবতরণ ক্রমে আরগসর্ট ব্যবহার করা কি সম্ভব?


180

নিম্নলিখিত কোড বিবেচনা করুন:

avgDists = np.array([1, 8, 6, 9, 4])
ids = avgDists.argsort()[:n]

এটি আমাকে nক্ষুদ্রতম উপাদানগুলির সূচক দেয় । সর্বোচ্চ উপাদানগুলির argsortসূচকগুলি পাওয়ার জন্য এটি কি উতরমান ক্রমে একই ব্যবহার সম্ভব n?


3
এটা সহজ না ids = np.array(avgDists).argsort()[-n:]?
জাইমে

2
@ জাইম: না, এটি কাজ করে না। 'সঠিক উত্তর' হ'ল [3, 1, 2]। আপনার লাইন উত্পাদন করে [2, 1, 3](উদাহরণস্বরূপ যদি n == 3)
ডাব

2
@ ড্র্রুক ভাল, তারপর এটি তৈরি করুন ids = np.array(avgDists).argsort()[-n:][::-1]। জিনিসটি পুরো তালিকার একটি অনুলিপি তৈরি করা এড়িয়ে চলেছে, আপনি যখন -সামনে এটি যুক্ত করেন তখন যা পাবেন । ওপির ছোট উদাহরণের জন্য প্রাসঙ্গিক নয়, এটি বৃহত্তর ক্ষেত্রে হতে পারে।
জাইমে

1
@ জাইম: আপনি ঠিক বলেছেন। আমার আপডেট হওয়া উত্তরটি দেখুন। শেষের টুকরোটি সম্পর্কে আপনার মন্তব্য থেকে সিনট্যাক্সটি সম্পূর্ণ বিপরীত: np.array(avgDists).argsort()[::-1][:n]এটি করবে। এছাড়াও, আপনি যদি ন্যালি ব্যবহার করতে চলেছেন তবে আপাতে থাকুন। প্রথমে তালিকাটিকে একটি অ্যারেতে রূপান্তর করুন: avgDist=np.array(avgDists)তারপরে তা হয়ে যায়avgDist.argsort()[::-1][:n}
ডগ করুন

উত্তর:


227

আপনি যদি কোনও অ্যারে অবহেলা করেন তবে সর্বনিম্ন উপাদানগুলি সর্বোচ্চ উপাদান এবং তদ্বিপরীত হয়ে ওঠে। সুতরাং, nসর্বোচ্চ উপাদানগুলির সূচকগুলি হ'ল :

(-avgDists).argsort()[:n]

এই সম্পর্কে কারণ আরেকটি উপায়, যেমন উল্লেখ মন্তব্য , পর্যবেক্ষণ করতে যে বড় উপাদান আসছে হয় গত argsort হবে। সুতরাং, আপনি nসর্বোচ্চ উপাদানগুলি খুঁজে পেতে আর্গোর্টের লেজ থেকে পড়তে পারেন :

avgDists.argsort()[::-1][:n]

উভয় পদ্ধতি হ'ল সময় জটিলতায় ও (এন লগ এন) , কারণ argsortকলটি এখানে প্রধান প্রভাবশালী শব্দ। তবে দ্বিতীয় পদ্ধতির একটি দুর্দান্ত সুবিধা রয়েছে: এটি অ্যারের একটি ও (এন) উপকারের পরিবর্তে একটি ও (1) ফালি দিয়ে প্রতিস্থাপন করে । আপনি যদি লুপের অভ্যন্তরে ছোট অ্যারে নিয়ে কাজ করছেন তবে আপনি সেই প্রত্যাখ্যান এড়ানো থেকে কিছুটা পারফরম্যান্স লাভ পেতে পারেন এবং যদি আপনি বিশাল অ্যারে নিয়ে কাজ করছেন তবে আপনি মেমরির ব্যবহারে সঞ্চয় করতে পারবেন কারণ প্রত্যাখ্যান পুরো অ্যারের একটি অনুলিপি তৈরি করে।

নোট করুন যে এই পদ্ধতিগুলি সর্বদা সমতুল্য ফলাফল দেয় না: যদি কোনও স্থিতিশীল সাজানোর প্রয়োগের জন্য অনুরোধ করা হয় argsort, উদাহরণস্বরূপ কীওয়ার্ড যুক্তিটি পাস করে kind='mergesort', তবে প্রথম কৌশলটি বাছাইয়ের স্থায়িত্ব সংরক্ষণ করবে, তবে দ্বিতীয় কৌশলটি স্থিতিশীলতা ভঙ্গ করবে (অর্থাত্ সমান অবস্থানে) আইটেমগুলি বিপরীত হয়ে যাবে)।

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

100 টি ফ্ল্যাট এবং একটি দৈর্ঘ্যের 30 টি লেজের ছোট অ্যারে ব্যবহার করে দর্শন পদ্ধতিটি প্রায় 15% দ্রুত ছিল

>>> avgDists = np.random.rand(100)
>>> n = 30
>>> timeit (-avgDists).argsort()[:n]
1.93 µs ± 6.68 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
>>> timeit avgDists.argsort()[::-1][:n]
1.64 µs ± 3.39 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
>>> timeit avgDists.argsort()[-n:][::-1]
1.64 µs ± 3.66 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

বৃহত্তর অ্যারেগুলির জন্য, আর্গোর্টটি প্রভাবশালী এবং কোনও উল্লেখযোগ্য সময় পার্থক্য নেই

>>> avgDists = np.random.rand(1000)
>>> n = 300
>>> timeit (-avgDists).argsort()[:n]
21.9 µs ± 51.2 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
>>> timeit avgDists.argsort()[::-1][:n]
21.7 µs ± 33.3 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
>>> timeit avgDists.argsort()[-n:][::-1]
21.9 µs ± 37.1 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)

দয়া করে নোট করুন যে নীচে নেডিমের মন্তব্যটি ভুল। বিপরীত হওয়ার আগে বা পরে ছাঁটাই করা হবে কিনা তা দক্ষতার কোনও পার্থক্য নেই, কারণ এই উভয়ই ক্রিয়াকলাপ অ্যারের একটি দৃষ্টিভঙ্গি কেবল আলাদাভাবে চালিয়ে যাচ্ছে এবং আসলে ডেটা অনুলিপি করছে না।


14
এটা তোলে reversing আগে ফালি এমনকি অধিক দক্ষ হয়, অর্থাত,np.array(avgDists).argsort()[:-n][::-1]
nedim

3
যদি মূল অ্যারেতে ন্যান থাকে তবে এই উত্তরগুলির সমতুল্য নয়। এই জাতীয় ক্ষেত্রে, প্রথম সমাধানটি শুরুতে নয় বরং ন্যানদের সাথে আরও প্রাকৃতিক ফলাফল দেবে বলে মনে হয়।
feilchenfeldt

1
একটি স্থিতিশীল সাজানোর পছন্দ হলে এগুলি কীভাবে তুলনা করতে পারে? সম্ভবত কাটা কৌশল সমান আইটেম বিপরীত?
এরিক

1
@ user3666197 আমি অনুভব করেছি এটি উত্তরটির সাথে প্রাসঙ্গিক নয়। প্রত্যাখ্যান একটি অনুলিপি তৈরি করে বা না (এটি করে) এখানে সত্যই গুরুত্বপূর্ণ নয়, প্রাসঙ্গিক তথ্য হ'ল প্রত্যাখ্যানের গণনা করা ও (এন) জটিলতা বনাম অন্য টুকরো যা ও (1) গ্রহণ করে
wim

1
@ ব্যবহারকারী 36666১ ,7 হ্যাঁ, এটি একটি ভাল পয়েন্ট - যদি কোনও অ্যারে 50% উপলব্ধ মেমরি গ্রহণ করে তবে আমরা অবশ্যই এটি অনুলিপি করা এবং স্বাপিং এড়াতে চাইব। আমি আবার সম্পাদনা করব যে এখানে একটি অনুলিপি তৈরি হয়েছে তা উল্লেখ করার জন্য।
wim

70

পাইথনের মতোই, এতে [::-1]ফিরে আসা অ্যারেটিকে বিপরীত করে দেয় argsort()এবং [:n]এটি শেষ এন উপাদানগুলিকে দেয়:

>>> avgDists=np.array([1, 8, 6, 9, 4])
>>> n=3
>>> ids = avgDists.argsort()[::-1][:n]
>>> ids
array([3, 1, 2])

এই পদ্ধতি সুবিধা যে idsএকটি হল দৃশ্য avgDists সংখ্যা:

>>> ids.flags
  C_CONTIGUOUS : False
  F_CONTIGUOUS : False
  OWNDATA : False
  WRITEABLE : True
  ALIGNED : True
  UPDATEIFCOPY : False

('ওয়ানডাটাটা' মিথ্যা বলে ইঙ্গিত দেয় এটি একটি অনুলিপি নয়)

এটি করার আরেকটি উপায় হ'ল:

(-avgDists).argsort()[:n]

সমস্যাটি হ'ল এই উপায়টি অ্যারেতে প্রতিটি উপাদানকে নেতিবাচক তৈরি করতে পারে:

>>> (-avgDists)
array([-1, -8, -6, -9, -4])

এএনডি এটির জন্য একটি অনুলিপি তৈরি করে:

>>> (-avgDists_n).flags['OWNDATA']
True

সুতরাং আপনি যদি প্রতিটি সময়, খুব খুব ছোট ডেটা সেট সহ:

>>> import timeit
>>> timeit.timeit('(-avgDists).argsort()[:3]', setup="from __main__ import avgDists")
4.2879798610229045
>>> timeit.timeit('avgDists.argsort()[::-1][:3]', setup="from __main__ import avgDists")
2.8372560259886086

দর্শন পদ্ধতিটি যথেষ্ট গতিযুক্ত (এবং 1/2 স্মৃতি ব্যবহার করে ...)


4
এই উত্তরটি ভাল, তবে আমি অনুভব করি যে আপনার কথাটি সত্যিকারের পারফরম্যান্সের বৈশিষ্ট্যগুলিকে ভুলভাবে উপস্থাপন করে: "এমনকি এই খুব ছোট ডেটা সেট করেও দেখার পদ্ধতিটি যথেষ্ট দ্রুত" । বাস্তবে, প্রত্যাখ্যান হ'ল ও (এন) এবং আর্গোর্টটি হ'ল (এন লগ এন) । এর অর্থ বৃহত্তর ডেটা সেটগুলির জন্য সময় স্বাতন্ত্র্য হ্রাস পাবে - ও (এন লগ এন) পদটি প্রাধান্য পাচ্ছে , তবে আপনার পরামর্শটি ও (এন) অংশটির অপ্টিমাইজেশন । সুতরাং জটিলতা একইরকম থেকে যায় এবং এটি এই বিশেষভাবে সেট করা ছোট ডেটাগুলির জন্য যে আমরা কোনও উল্লেখযোগ্য পার্থক্য দেখি।
Wim

2
অ্যাসিপটোটিক্যালি সমতুল্য জটিলতা এখনও বোঝাতে পারে যে একটি অ্যালগরিদম হ'ল তাত্পর্যপূর্ণভাবে অপরের চেয়ে দ্বিগুণ তত দ্রুত। এই ধরনের পার্থক্য দূরে ফেলে দেওয়ার পরিণতি হতে পারে। উদাহরণস্বরূপ, এমনকি সময়ের স্বতন্ত্রতা (শতাংশ হিসাবে) 0 এড়ানোর পরেও, আমি বাজি রাখতে ইচ্ছুক হব যে অবহেলা সহ অ্যালগরিদম এখনও দ্বিগুণ মেমরি ব্যবহার করে।
বাগ 21

@ বাগ এটি করতে পারে, তবে এটি এই ক্ষেত্রে হয় না। আমি আমার উত্তরে কিছু সময় যুক্ত করেছি। সংখ্যাগুলি দেখায় যে বৃহত্তর অ্যারেগুলির জন্য এই পদ্ধতির একই সময়সীম রয়েছে, যা এই অনুমানকে সমর্থন করে যে আর্গসর্ট প্রভাবশালী। প্রত্যাখ্যানের জন্য, আমি অনুমান করব যে আপনি মেমরির ব্যবহার সম্পর্কে ঠিক বলেছেন, তবে ব্যবহারকারীরা এখনও পছন্দ করতে পারেন যদি তারা ন্যানের অবস্থানের বিষয়ে যত্নশীল হন এবং / অথবা কোনও স্থিতিশীল বাছাইয়ের প্রয়োজন হয়।
wim

6

আপনি ফ্লিপ কমান্ডগুলি ব্যবহার করতে পারেন numpy.flipud()বা কমান্ডটি numpy.fliplr()ব্যবহার করে বাছাইয়ের পরে অবতরণ ক্রমে সূচকগুলি পেতে পারেন argsort। আমি সাধারণত যা করি তা স্থির করে।



5

পরিবর্তে np.argsortআপনি ব্যবহার করতে পারবেন np.argpartition- আপনার যদি কেবল সর্বনিম্ন / সর্বোচ্চ এন উপাদানগুলির সূচকগুলির প্রয়োজন হয়।

এটির জন্য পুরো অ্যারেটি সাজানোর দরকার নেই তবে কেবল যে অংশটি আপনার প্রয়োজন হবে তবে নোট করুন যে "আপনার পার্টিশনের অভ্যন্তরের ক্রম" অপরিজ্ঞাত, সুতরাং এটি সঠিক সূচকগুলি দিলে সেগুলি সঠিকভাবে অর্ডার নাও করতে পারে:

>>> avgDists = [1, 8, 6, 9, 4]
>>> np.array(avgDists).argpartition(2)[:2]  # indices of lowest 2 items
array([0, 4], dtype=int64)

>>> np.array(avgDists).argpartition(-2)[-2:]  # indices of highest 2 items
array([1, 3], dtype=int64)

অথবা, আপনি যদি দুজনকে একসাথে ব্যবহার করছেন, তা হ'ল আর্গোর্ট এবং আরগ পার্টিশন, আরগ পার্টিশন অপারেশনে অপারেশনটি করাতে হবে।
ডেমোঙ্গোলেম

3

আপনি অ্যারের একটি অনুলিপি তৈরি করতে এবং তারপরে প্রতিটি উপাদানকে -1 দিয়ে গুণতে পারেন।
প্রভাব হিসাবে আগে বৃহত্তম উপাদানগুলি সবচেয়ে ছোট হয়ে উঠত।
অনুলিপিগুলিতে অনুলিপিগুলিতে অনুলিপিগুলি হ'ল মূলের n সর্বাধিক উপাদান।


এটি সহজেই অ্যারেটিকে উপেক্ষা করে করা হয়, যেমনটি অন্যান্য -array
উত্তরে

2

@ কানমণির ইঙ্গিত হিসাবে, বাস্তবায়নের ব্যাখ্যার আরও সহজতর ব্যবহার numpy.flipনিম্নলিখিত নীচের মত হতে পারে :

import numpy as np

avgDists = np.array([1, 8, 6, 9, 4])
ids = np.flip(np.argsort(avgDists))
print(ids)

সদস্য ফাংশনের চেয়ে দর্শনার্থীর প্যাটার্নটি ব্যবহার করে, ক্রিয়াকলাপের ক্রমটি পড়া আরও সহজ।


1

আপনার উদাহরণ সহ:

avgDists = np.array([1, 8, 6, 9, 4])

এন সর্বাধিক মানের সূচকগুলি পান:

ids = np.argpartition(avgDists, -n)[-n:]

সেগুলি সাজানো ক্রম অনুসারে বাছাই করুন:

ids = ids[np.argsort(avgDists[ids])[::-1]]

ফলাফল প্রাপ্ত করুন (এন = 4 এর জন্য):

>>> avgDists[ids]
array([9, 8, 6, 4])

-1

আরোগোর্টের পক্ষে যুক্তি হিসাবে কেবল একটি '-' ব্যবহার করা অন্য উপায় হ'ল: "df [np.argsort (-df [:, 0])]", প্রদান করা ডিএফ ডেটাফ্রেম এবং আপনি এটি প্রথমটি অনুসারে বাছাই করতে চান কলাম (কলাম নম্বর '0' দ্বারা উপস্থাপিত) যথাযথ হিসাবে কলাম-নাম পরিবর্তন করুন। অবশ্যই, কলামটি একটি সংখ্যাযুক্ত হতে হবে।

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