অ্যারেতে কোনও কিছুর প্রথম সূচকটি ফেরত দেওয়ার জন্য কি কোনও ন্যামপি ফাংশন রয়েছে?


461

আমি জানি পাইথন তালিকার কোনও কিছুর প্রথম সূচক ফেরত দেওয়ার জন্য একটি পদ্ধতি রয়েছে:

>>> l = [1, 2, 3]
>>> l.index(2)
1

নুমপাই অ্যারেগুলির মতো কিছু আছে কি?


3
এফওয়াইআই:
নম্পপি

উত্তর:


522

হ্যাঁ, অনুসন্ধানের জন্য এখানে একটি উত্তরপ্য অ্যারে array, এবং একটি মান দেওয়া উত্তর রয়েছে item:

itemindex = numpy.where(array==item)

ফলাফলটি প্রথমে সমস্ত সারি সূচক, তারপরে সমস্ত কলাম সূচক সহ একটি টুপল।

উদাহরণস্বরূপ, যদি কোনও অ্যারে দুটি মাত্রা হয় এবং এতে আপনার আইটেমটি দুটি স্থানে থাকে

array[itemindex[0][0]][itemindex[1][0]]

আপনার আইটেমের সমান হবে এবং তাই হবে

array[itemindex[0][1]][itemindex[1][1]]

numpy.where


1
আপনি যদি প্রথম সারিতে সন্ধান করছেন যেখানে কোনও আইটেম প্রথম কলামে বিদ্যমান রয়েছে, এটি কাজ করে (যদিও এটি উপস্থিত না থাকলে একটি সূচক ত্রুটি নিক্ষেপ করবে)rows, columns = np.where(array==item); first_idx = sorted([r for r, c in zip(rows, columns) if c == 0])[0]
BrT

27
আপনি যদি প্রথম মানটি সন্ধানের পরে এটি অনুসন্ধান বন্ধ করতে চান তবে কী হবে? আমি কখনই ()
সন্ধানের

2
আহ! : আপনার কর্মক্ষমতা আগ্রহী হন, তাহলে, এই প্রশ্নের উত্তর পরীক্ষা stackoverflow.com/questions/7632963/...
মাইকেল Clerx

11
np.argwhereএখানে কিছুটা বেশি দরকারী হবে:itemindex = np.argwhere(array==item)[0]; array[tuple(itemindex)]
এরিক

3
এটি লক্ষণীয় যে এই উত্তরটি অ্যারে 2D বলে ধরেছে। whereযে কোনও অ্যারেতে কাজ করে এবং 3 ডি অ্যারে ইত্যাদি ব্যবহার করার সময় 3 টি দৈর্ঘ্যের দ্বিগুণ ফিরে আসবে
পি ক্যামিলারি

69

আপনার যদি কেবলমাত্র একটি মানটির প্রথম উপস্থিতির সূচক প্রয়োজন হয় তবে আপনি ব্যবহার করতে পারেন nonzero(বা where, যা এই ক্ষেত্রে একই জিনিসটির সমান):

>>> t = array([1, 1, 1, 2, 2, 3, 8, 3, 8, 8])
>>> nonzero(t == 8)
(array([6, 8, 9]),)
>>> nonzero(t == 8)[0][0]
6

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

>>> nonzero(r_[1, diff(t)[:-1]])
(array([0, 3, 5, 6, 7, 8]),)

লক্ষ্য করুন যে এটি 3s এবং পরবর্তী 8s এর উভয় অনুচ্ছেদের উভয়ের সূচনা খুঁজে পেয়েছে:

[ 1 , 1, 1, 2 , 2, 3 , 8 , 3 , 8 , 8]

সুতরাং এটি প্রতিটি মানের প্রথম উপস্থিতি সন্ধানের চেয়ে কিছুটা আলাদা । আপনার প্রোগ্রামে tআপনি যা চান তা পেতে আপনি একটি সাজানো সংস্করণ দিয়ে কাজ করতে সক্ষম হতে পারেন:

>>> st = sorted(t)
>>> nonzero(r_[1, diff(st)[:-1]])
(array([0, 3, 5, 7]),)

4
আপনি কি দয়া করে ব্যাখ্যা করতে পারেন r_?
জেফ

1
@ জিফ, কনটেটেটস r_; বা, আরও স্পষ্টভাবে, এটি প্রতিটি অক্ষের সাথে টুকরো টুকরোকে সংমিশ্রণে অনুবাদ করে। আমি hstackপরিবর্তে ব্যবহার করতে পারে ; এটি কম বিভ্রান্তিকর হতে পারে। আরও তথ্যের জন্য ডকুমেন্টেশন দেখুন r_। এছাড়াও আছে একটি c_
Vebjorn Ljosa

+1, সুন্দর! (NP.where বনাম) আপনার সমাধান অনেক ক্ষেত্রে যেখানে এটি শুধুমাত্র একটি 1D অ্যারের মধ্যে একটি প্রদত্ত মূল্যের প্রথম সংঘটন এর সহজ (এবং সম্ভবত আরও দ্রুত) যে আমরা প্রয়োজন
ডগ

3
পরবর্তী কেস (সমস্ত মানের প্রথম সূচক সন্ধান করা) দেওয়া হয়েছেvals, locs = np.unique(t, return_index=True)
askewchan

49

আপনি একটি নুমপি অ্যারে বাতাসে তালিকাতে রূপান্তর করতে এবং এর সূচকটি পেতে পারেন। উদাহরণ স্বরূপ,

l = [1,2,3,4,5] # Python list
a = numpy.array(l) # NumPy array
i = a.tolist().index(2) # i will return index of 2
print i

এটি মুদ্রণ করবে 1।


এটি প্রথম লেখা হওয়ার পরে এটি হতে পারে গ্রন্থাগারটি পরিবর্তন হয়েছে। তবে এটিই প্রথম সমাধান যা আমার পক্ষে কাজ করেছিল।
amracel

1
একটি তালিকা বোধগম্যতা ব্যবহার করে তালিকার একাধিক মান খুঁজে পেতে আমি এর ভাল ব্যবহার করেছি:[find_list.index(index_list[i]) for i in range(len(index_list))]
ম্যাট ওয়েনহ্যাম

1
@MattWenham যদি বড় যথেষ্ট, প্রথমে আপনাকে রূপান্তর করতে পারেন find_listএকটি NumPy অ্যারেতে object(অথবা কিছু আরও নির্দিষ্ট করে সঠিক) এবং শুধু কি find_arr[index_list]
নরফানর

পুরোপুরি অফ-টপিক, তবে এই প্রথম আমি "বাতাসে" শব্দটি দেখছি - যা আমি তার জায়গায় সর্বাধিক দেখেছি সম্ভবত এটি "উড়ানের দিকে"।
ফ্লো 2 কে

18

একটি খুব পারফরম্যান্ট এবং সহজ যোগ করতে np.ndenumerateপ্রথম সূচকটি অনুসন্ধানের ভিত্তিতে বিকল্প :

from numba import njit
import numpy as np

@njit
def index(array, item):
    for idx, val in np.ndenumerate(array):
        if val == item:
            return idx
    # If no item was found return None, other return types might be a problem due to
    # numbas type inference.

এটি বেশ দ্রুত এবং বহুমাত্রিক অ্যারেগুলির সাথে প্রাকৃতিকভাবে ডিল করে :

>>> arr1 = np.ones((100, 100, 100))
>>> arr1[2, 2, 2] = 2

>>> index(arr1, 2)
(2, 2, 2)

>>> arr2 = np.ones(20)
>>> arr2[5] = 2

>>> index(arr2, 2)
(5,)

এটি ব্যবহার বা ব্যবহারের কোনও পদ্ধতির তুলনায় এটি আরও দ্রুত হতে পারে (কারণ এটি অপারেশনকে সংক্ষিপ্তসার্কিট করছে) ।np.wherenp.nonzero


তবে np.argwhereএছাড়াও মোকাবেলা পারে অত্যন্ত শৃঙ্খলার বহুমাত্রিক অ্যারে সঙ্গে (ম্যানুয়ালি একটি tuple সামনে ছুঁড়ে আপনার যা দরকার হবে এবং তা না স্বল্প circuited করা হয়েছে) কিন্তু যদি কোন মিল খুঁজে পাওয়া যায় এটা ব্যর্থ হবে:

>>> tuple(np.argwhere(arr1 == 2)[0])
(2, 2, 2)
>>> tuple(np.argwhere(arr2 == 2)[0])
(5,)

2
@njitএর একটি সংক্ষিপ্ত রূপটি হ'ল jit(nopython=True)প্রথম রান করার সময় ফাংশনটি ফ্লাইটটি অন ফ্লাইটে সম্পূর্ণরূপে সংকলিত হবে যাতে পাইথন ইন্টারপ্রেটার কল সম্পূর্ণভাবে মুছে ফেলা হয়।
বার্টোলো-ওট্রিট

14

যদি আপনি এটিকে অন্য কোনও সূচী হিসাবে ব্যবহার করতে চলেছেন তবে অ্যারেগুলি সম্প্রচারযোগ্য হলে আপনি বুলিয়ান সূচকগুলি ব্যবহার করতে পারেন; আপনার সুস্পষ্ট সূচকের দরকার নেই। এটি করার নিখুঁত সহজ উপায় হ'ল একটি সত্য মানের উপর ভিত্তি করে সূচক।

other_array[first_array == item]

যে কোনও বুলিয়ান অপারেশন কাজ করে:

a = numpy.arange(100)
other_array[first_array > 50]

ননজারো পদ্ধতিতে বুলিয়ানও লাগে:

index = numpy.nonzero(first_array == item)[0][0]

দুটি জিরো হ'ল সূচকগুলির দ্বিগুণ জন্য (ধরে নিলে প্রথম_আরে 1 ডি হয়) এবং তারপরে সূচকের অ্যারেতে প্রথম আইটেম।


10

l.index(x)সর্বনিম্ন i টি ফেরৎ দেয় যে আমি তালিকার x এর প্রথম উপস্থিতির সূচক।

কেউ নিরাপদে ধরে নিতে পারেন যে index()পাইথনের ফাংশনটি এমনভাবে বাস্তবায়িত হয়েছে যাতে এটি প্রথম ম্যাচটি সন্ধান করার পরে বন্ধ হয়ে যায় এবং এর ফলে সর্বোত্তম গড় পারফরম্যান্স হয়।

নুমপি অ্যারেতে প্রথম ম্যাচের পরে থামার উপাদান খুঁজে পাওয়ার জন্য একটি পুনরুক্তি ( এনডেনিউরেট ) ব্যবহার করুন।

In [67]: l=range(100)

In [68]: l.index(2)
Out[68]: 2

NumPy অ্যারে:

In [69]: a = np.arange(100)

In [70]: next((idx for idx, val in np.ndenumerate(a) if val==2))
Out[70]: (2L,)

নোট করুন যে উভয় পদ্ধতি index()এবং nextউপাদানটি খুঁজে পাওয়া না গেলে একটি ত্রুটি ফেরান। এর সাথে next, উপাদানটি খুঁজে পাওয়া যায় না, এমন ক্ষেত্রে একটি বিশেষ মান ফেরত দিতে দ্বিতীয় তর্কটি ব্যবহার করতে পারে eg

In [77]: next((idx for idx, val in np.ndenumerate(a) if val==400),None)

NumPy ( argmax, whereএবং nonzero) এর মধ্যে অন্যান্য ফাংশন রয়েছে যা অ্যারেতে উপাদান খুঁজে পেতে ব্যবহার করা যেতে পারে, তবে তাদের সকলেরই সমস্ত উপস্থিতি সন্ধান করার জন্য পুরো অ্যারেটি দিয়ে যাওয়ার প্রবণতা রয়েছে, সুতরাং প্রথম উপাদানটি খুঁজে পাওয়ার জন্য এটি অনুকূলিত হয় না। এছাড়াও মনে রাখবেন whereএবং nonzeroরিটার্ন অ্যারে, তাই আপনি সূচক পেতে প্রথম উপাদান নির্বাচন করতে হবে।

In [71]: np.argmax(a==2)
Out[71]: 2

In [72]: np.where(a==2)
Out[72]: (array([2], dtype=int64),)

In [73]: np.nonzero(a==2)
Out[73]: (array([2], dtype=int64),)

সময়ের তুলনা

সন্ধান করা%timeit আইটেমি অ্যারের শুরুতে ( আইপিথন শেল ব্যবহার করে ) যখন বড় অ্যারের জন্য সমাধানটি একটি পুনরুক্তি ব্যবহারকারীর দ্বারা সমাধান করা দ্রুত হয় :

In [285]: a = np.arange(100000)

In [286]: %timeit next((idx for idx, val in np.ndenumerate(a) if val==0))
100000 loops, best of 3: 17.6 µs per loop

In [287]: %timeit np.argmax(a==0)
1000 loops, best of 3: 254 µs per loop

In [288]: %timeit np.where(a==0)[0][0]
1000 loops, best of 3: 314 µs per loop

এটি ওপেন নম্পপি গিটহাব ইস্যু

আরও দেখুন: নম্পি : মানটির প্রথম সূচকটি দ্রুত সন্ধান করুন


1
আমি মনে করি আপনার নিকৃষ্টতম পরিস্থিতি (শেষ উপাদান) জন্যও সময় অন্তর্ভুক্ত করা উচিত যাতে পাঠকরা জানতে পারেন যে তারা যখন আপনার পদ্ধতির ব্যবহার করে তখন সবচেয়ে খারাপ ক্ষেত্রে তাদের সাথে কী ঘটে।
এমসিফার্ট

@ সাইফের্ট আমি সবচেয়ে খারাপ ক্ষেত্রে পুনরাবৃত্তি সমাধানের জন্য যুক্তিসঙ্গত সময় পেতে পারি না - আমি এতে এই উত্তরটি মুছে ফেলব যতক্ষণ না এটির সমস্যা আছে তা না পাওয়া পর্যন্ত
ব্যবহারকারী 2314737

1
%timeit next((idx for idx, val in np.ndenumerate(a) if val==99999))কাজ করে না ? আপনি যদি ভাবছেন যে এটি কেন 1000 গুণ বেশি ধীর - এটি কারণ ন্যাপি অ্যারেগুলিতে পাইথন লুপগুলি কুখ্যাতভাবে ধীর।
এমসিফার্ট

কোন @MSeifert আমি যে জানেন না, কিন্তু আমি যে দ্বারা ধাঁধা করছি argmaxএবং whereএই ক্ষেত্রে অনেক দ্রুত হয় (অ্যারে শেষে উপাদান অনুসন্ধান করা হয়েছে)
user2314737

এগুলি তত দ্রুত হওয়া উচিত যেন উপাদানটি শুরুতে থাকে। তারা সর্বদা পুরো অ্যারে প্রক্রিয়া করে তাই তারা সর্বদা একই সময় নেয় (কমপক্ষে তাদের উচিত)।
এমসিফার্ট

9

এক-মাত্রিক সাজানো অ্যারেগুলির জন্য, numpy.searchsorted যা NumPy পূর্ণসংখ্যা (অবস্থান) প্রদান করে তা ব্যবহার করা আরও অনেক সহজ এবং দক্ষ ও (লগ (এন)) হবে । উদাহরণ স্বরূপ,

arr = np.array([1, 1, 1, 2, 3, 3, 4])
i = np.searchsorted(arr, 3)

অ্যারে ইতিমধ্যে বাছাই করা হয়েছে তা নিশ্চিত করুন

ফিরে আসা সূচকগুলিতে আমি আসলে অনুসন্ধানের উপাদানটি রেখেছি কিনা তাও পরীক্ষা করে দেখুন, যেহেতু অনুসন্ধানের মূল উদ্দেশ্য সূচকগুলি সন্ধান করা যেখানে উপাদানগুলি শৃঙ্খলা বজায় রাখতে হবে।

if arr[i] == 3:
    print("present")
else:
    print("not present")

2
অনুসন্ধানটি এনলগ নয় (এন) যেহেতু এটি অনুসন্ধানের আগে অ্যারেটিকে বাছাই করে না, এটি ধরে নিয়েছে যে আর্গুমেন্ট অ্যারে ইতিমধ্যে সাজানো হয়েছে। numpy.searchsorted (উপরের লিঙ্ক) এর ডকুমেন্টেশন দেখুন
অলোক নায়ক

6

যে কোনও মানদণ্ডে সূচী করতে আপনি নীচের মতো কিছু করতে পারেন:

In [1]: from numpy import *
In [2]: x = arange(125).reshape((5,5,5))
In [3]: y = indices(x.shape)
In [4]: locs = y[:,x >= 120] # put whatever you want in place of x >= 120
In [5]: pts = hsplit(locs, len(locs[0]))
In [6]: for pt in pts:
   .....:         print(', '.join(str(p[0]) for p in pt))
4, 4, 0
4, 4, 1
4, 4, 2
4, 4, 3
4, 4, 4

এবং list.index () কী করে তা করার জন্য এখানে একটি দ্রুত ফাংশন রয়েছে, যদি এটি না পাওয়া যায় তবে ব্যতিক্রম বাড়াবে না। সাবধান - এটি বড় অ্যারেগুলিতে সম্ভবত খুব ধীর। আপনি সম্ভবত এটি একটি পদ্ধতি হিসাবে ব্যবহার করতে চাইলে আপনি সম্ভবত বানরটিকে এই অ্যারেতে প্যাচ করতে পারেন।

def ndindex(ndarray, item):
    if len(ndarray.shape) == 1:
        try:
            return [ndarray.tolist().index(item)]
        except:
            pass
    else:
        for i, subarray in enumerate(ndarray):
            try:
                return [i] + ndindex(subarray, item)
            except:
                pass

In [1]: ndindex(x, 103)
Out[1]: [4, 0, 3]

5

1 ডি অ্যারেগুলির জন্য, আমি প্রস্তাব দেব np.flatnonzero(array == value)[0], যা উভয়ের সমতুল্য np.nonzero(array == value)[0][0]এবং np.where(array == value)[0][0]তবে 1-উপাদান টিউপলকে আনবক্সিংয়ের কদর্যতা এড়ানো উচিত।


4

এনপি.হোয়ার () থেকে প্রথম উপাদানটি নির্বাচনের বিকল্প হ'ল গণনার সাথে জেনারেটর এক্সপ্রেশন ব্যবহার করা যেমন:

>>> import numpy as np
>>> x = np.arange(100)   # x = array([0, 1, 2, 3, ... 99])
>>> next(i for i, x_i in enumerate(x) if x_i == 2)
2

একটি দ্বিমাত্রিক অ্যারের জন্য যেটি করবে:

>>> x = np.arange(100).reshape(10,10)   # x = array([[0, 1, 2,... 9], [10,..19],])
>>> next((i,j) for i, x_i in enumerate(x) 
...            for j, x_ij in enumerate(x_i) if x_ij == 2)
(0, 2)

এই পদ্ধতির সুবিধাটি হ'ল এটি প্রথম ম্যাচের সন্ধান পাওয়ার পরে অ্যারের উপাদানগুলি পরীক্ষা করা বন্ধ করে দেয়, যেখানে এনপি.হোমেনার ম্যাচের জন্য সমস্ত উপাদান পরীক্ষা করে। জেনারেটর এক্সপ্রেশনটি দ্রুততর হবে যদি অ্যারেতে শুরুর দিকে মিল থাকে।


অ্যারেতে কোনও মিল নাও থাকতে পারে, এই পদ্ধতিটি আপনাকে সুবিধামত একটি ফলব্যাক মান নির্দিষ্ট করতে দেয়। প্রথম উদাহরণটি যদি Noneফ্যালব্যাক হিসাবে ফিরে আসে তবে তা হয়ে উঠত next((i for i, x_i in enumerate(x) if x_i == 2), None)
এরলেন্ড ম্যাগনাস ভিগেন

4

NumPy এ প্রচুর অপারেশন রয়েছে যা সম্ভবত এটি সম্পাদন করার জন্য একত্র করা যেতে পারে। এটি আইটেমের সমতুল্য উপাদানগুলির সূচকগুলি ফিরিয়ে দেবে:

numpy.nonzero(array - item)

তারপরে আপনি তালিকার প্রথম উপাদানগুলিকে একক উপাদান পেতে পারেন।


5
এটি আইটেমের সমান নয় এমন সমস্ত উপাদানগুলির সূচকগুলি দেবে না ?
অলপ্লেস্টিক

3

Numpy_indexed প্যাকেজ (দাবিত্যাগ, আমি সংশ্লিষ্ট লেখক নই) numpy.ndarray জন্য list.index একটি ভেক্টরকৃত সমতুল্য উপস্থিত রয়েছে; এটাই:

sequence_of_arrays = [[0, 1], [1, 2], [-5, 0]]
arrays_to_query = [[-5, 0], [1, 0]]

import numpy_indexed as npi
idx = npi.indices(sequence_of_arrays, arrays_to_query, missing=-1)
print(idx)   # [2, -1]

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


-1

দ্রষ্টব্য: এটি অজগর ২.7 সংস্করণের জন্য

সমস্যাটি মোকাবেলা করতে আপনি একটি ল্যাম্বদা ফাংশন ব্যবহার করতে পারেন এবং এটি NumPy অ্যারে এবং তালিকার উভয় ক্ষেত্রেই কাজ করে।

your_list = [11, 22, 23, 44, 55]
result = filter(lambda x:your_list[x]>30, range(len(your_list)))
#result: [3, 4]

import numpy as np
your_numpy_array = np.array([11, 22, 23, 44, 55])
result = filter(lambda x:your_numpy_array [x]>30, range(len(your_list)))
#result: [3, 4]

এবং আপনি ব্যবহার করতে পারেন

result[0]

ফিল্টার উপাদানগুলির প্রথম সূচক পেতে।

পাইথন ৩.6 এর জন্য ব্যবহার করুন

list(result)

পরিবর্তে

result

<filter object at 0x0000027535294D30>পাইথন 3 এ ফলাফল (পাইথন 3.6.3 এ পরীক্ষিত)। পাইথন 3 এর জন্য সম্ভবত আপডেট করবেন?
পিটার মর্টেনসেন
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.