क्या किसी सरणी में किसी चीज़ के पहले सूचकांक को वापस करने के लिए एक नम्पी फ़ंक्शन है?


461

मुझे पता है कि किसी चीज़ के पहले सूचकांक को वापस करने के लिए पायथन सूची के लिए एक विधि है:

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

क्या NumPy सरणियों के लिए ऐसा कुछ है?


जवाबों:


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/…
माइकल क्लेरक्स

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 के दोनों और 8 के बाद के दोनों की शुरुआत को पाता है:

[ , १, १, , २, , 1 , , 1 ,,]

इसलिए यह प्रत्येक मूल्य की पहली घटना को खोजने से थोड़ा अलग है । अपने कार्यक्रम में, आप tजो चाहते हैं उसे पाने के लिए हल किए गए संस्करण के साथ काम करने में सक्षम हो सकते हैं:

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

4
क्या आप बता सकते हैं कि क्या r_है?
ज्योफ

1
@Geoff, संघात r_; या, अधिक सटीक रूप से, यह प्रत्येक अक्ष के साथ समतल वस्तुओं का अनुवाद करता है। मैं hstackइसके बजाय इस्तेमाल कर सकता था ; यह कम भ्रामक हो सकता है। के बारे में अधिक जानकारी के लिए प्रलेखन देखें r_। ए भी है c_
वेबजॉर्न लजोसा

+1, अच्छा है! (बनाम एनपी। वे) आपका समाधान उस मामले में बहुत सरल (और शायद तेज) है जहां यह 1 डी सरणी में दिए गए मूल्य की केवल पहली घटना है जिसकी हमें जरूरत है
doug

3
उत्तरार्द्ध मामले (सभी मूल्यों के पहले सूचकांक को खोजने) द्वारा दिया गया हैvals, locs = np.unique(t, return_index=True)
पूछना

49

आप हवा में सूचीबद्ध करने और इसके सूचकांक प्राप्त करने के लिए एक NumPy सरणी भी बदल सकते हैं। उदाहरण के लिए,

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

पूरी तरह से ऑफ-टॉपिक, लेकिन यह पहली बार है जब मैंने वाक्यांश "हवा में" देखा है - जो मैंने सबसे अधिक देखा है, उसके स्थान पर, शायद "मक्खी पर" है।
flow2k

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.whereया से np.nonzero


हालाँकि बहुआयामी सरणियों के साथ np.argwhereभी इनायत से पेश आ सकते हैं (आपको इसे मैन्युअल रूप से एक टपल में डालने की आवश्यकता होगी और यह शॉर्ट-सर्कुलेट नहीं है) लेकिन अगर कोई मैच नहीं मिला तो यह विफल हो जाएगा:

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

दो शून्य सूचकांकों के टापल के लिए हैं (पहले_हारे 1D मान रहा है) और फिर सूचकांकों की सरणी में पहला आइटम।


10

l.index(x)सबसे छोटा मैं लौटाता हूं जैसे कि मैं सूची में x की पहली घटना का सूचकांक हूं

एक सुरक्षित रूप से मान सकता है कि index()पायथन में फ़ंक्शन को लागू किया गया है ताकि यह पहला मैच खोजने के बाद बंद हो जाए, और यह एक इष्टतम औसत प्रदर्शन का परिणाम है।

NumPy सरणी में पहले मैच के बाद एक तत्व को रोकने के लिए एक इट्रेटर ( ndenumerate ) का उपयोग करें ।

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, एक एक विशेष मूल्य के मामले में तत्व नहीं पाया जाता है, उदाहरण के लिए वापस जाने के लिए एक दूसरा तर्क का उपयोग कर सकते

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),)

समय की तुलना

बस जाँच कर रहे हैं कि बड़े सरणियों के लिए एक पुनरावृत्त का उपयोग कर समाधान तेजी से होता है जब खोज की गई वस्तु सरणी की शुरुआत में होती है ( %timeitIPython शेल में उपयोग ):

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

यह एक खुला NumPy GitHub मुद्दा है

यह भी देखें: Numpy: तेजी से मूल्य का पहला सूचकांक खोजें


1
मुझे लगता है कि आपको सबसे खराब स्थिति (अंतिम तत्व) के लिए एक समय भी शामिल करना चाहिए ताकि पाठकों को पता चले कि उनके दृष्टिकोण का उपयोग करने पर सबसे खराब स्थिति में उनके साथ क्या होता है।
MSeifert

@ संदेश मैं सबसे बुरे मामले के समाधान के लिए एक उचित समय प्राप्त नहीं कर सकता - मैं इस जवाब को हटाने जा रहा हूं जब तक मुझे पता नहीं चले कि इसमें क्या गलत है
user2314737

1
काम नहीं %timeit next((idx for idx, val in np.ndenumerate(a) if val==99999))करता है? यदि आप सोच रहे हैं कि यह 1000 गुना धीमा क्यों है - यह इसलिए है क्योंकि सुन्न सरणियों पर अजगर छोरों को बेहद धीमा है।
MSeifert

कोई @MSeifert मुझे लगता है कि पता नहीं था, लेकिन मैं यह भी सच है कि हैरान कर रहा हूँ argmaxऔर whereइस मामले में बहुत तेजी से कर रहे हैं (सरणी के अंत में तत्व की खोज)
user2314737

उन्हें उतना तेज होना चाहिए जैसे कि तत्व शुरुआत में है। वे हमेशा पूरे सरणी को संसाधित करते हैं, इसलिए वे हमेशा एक ही समय लेते हैं (कम से कम उन्हें चाहिए)।
MSeifert

9

एक-आयामी सॉर्ट किए गए सरणियों के लिए, यह बहुत अधिक सरल और कुशल O (लॉग (n)) होगा जो numpy.searchsorted का उपयोग करता है जो एक NumPy पूर्णांक (स्थिति) देता है। उदाहरण के लिए,

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

बस सुनिश्चित करें कि सरणी पहले से ही सॉर्ट की गई है

यह भी जांचें कि क्या लौटा हुआ इंडेक्स I में वास्तव में खोजा गया तत्व है, क्योंकि खोजे का मुख्य उद्देश्य सूचकांकों को खोजना है जहां तत्वों को क्रम बनाए रखने के लिए डाला जाना चाहिए।

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

2
searchsorted nlog (n) नहीं है क्योंकि यह खोज करने से पहले सरणी को सॉर्ट नहीं करता है, यह मानता है कि तर्क सरणी पहले से ही सॉर्ट है। 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

1D सरणियों के लिए, मैं अनुशंसा करूंगा np.flatnonzero(array == value)[0], जो दोनों के बराबर है np.nonzero(array == value)[0][0]और np.where(array == value)[0][0]लेकिन 1-तत्व ट्यूल को अनबॉक्स करने की कुरूपता से बचा जाता है।


4

Np.where () से पहले एलिमेंट को चुनने के लिए एक विकल्प है कि एक एनीमल के साथ एक जनरेटर एक्सप्रेशन का उपयोग करें, जैसे:

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

इस दृष्टिकोण का लाभ यह है कि यह पहला मैच मिलने के बाद सरणी के तत्वों की जांच करना बंद कर देता है, जबकि np.where एक मैच के लिए सभी तत्वों की जांच करता है। अगर सरणी में पहले से मेल खाता है तो एक जनरेटर अभिव्यक्ति तेज होगी।


मामले में सरणी में एक मैच नहीं हो सकता है, इस विधि से आप आसानी से एक वापसी मूल्य निर्दिष्ट कर सकते हैं। यदि पहला उदाहरण Noneकमबैक के रूप में लौटना होता, तो यह बन जाता next((i for i, x_i in enumerate(x) if x_i == 2), None)
एर्लेंड मैग्नस विगगेन

4

NumPy में बहुत सारे ऑपरेशन हैं जो शायद इसे पूरा करने के लिए एक साथ रखे जा सकते हैं। यह आइटम के बराबर तत्वों के सूचकांकों को लौटाएगा:

numpy.nonzero(array - item)

फिर आप एकल तत्व प्राप्त करने के लिए सूचियों के पहले तत्वों को ले सकते हैं।


5
वह सभी तत्वों के सूचक नहीं देगा जो आइटम के बराबर नहीं हैं ?
2

3

Numpy_indexed पैकेज (त्याग, मैं उसके लेखक हूँ) numpy.ndarray के लिए list.index के एक vectorized बराबर होता है; अर्थात्:

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]

इस समाधान में वेक्टरकृत प्रदर्शन है, ndarrays को सामान्य करता है, और लापता मूल्यों से निपटने के विभिन्न तरीके हैं।


-1

नोट: यह अजगर 2.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]

फ़िल्टर किए गए तत्वों का पहला सूचकांक प्राप्त करने के लिए।

अजगर 3.6 के लिए, का उपयोग करें

list(result)

के बजाय

result

इसका परिणाम <filter object at 0x0000027535294D30>पायथन 3 (पायथन 3.6.3 पर परीक्षण) पर होता है। शायद पायथन 3 के लिए अपडेट करें?
पीटर मोर्टेंसन
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.