python - numpy شرح




هل هناك وظيفة Numpy لإرجاع المؤشر الأول لشيء ما في صفيف؟ (9)

إذا كنت بحاجة إلى فهرس التواجد الأول لقيمة واحدة فقط ، فيمكنك استخدام 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]),)

أعلم أن هناك طريقة لقائمة python لإرجاع المؤشر الأول لشيء ما

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

هل هناك شيء من هذا القبيل للصفائف المحفر؟


إذا كنت ستستخدم هذا كمؤشر إلى شيء آخر ، فيمكنك استخدام المؤشرات المنطقية إذا كانت المصفوفات قابلة للبث ؛ لا تحتاج لمؤشرات واضحة. الطريقة الأبسط المطلق للقيام بذلك هي ببساطة استنادًا إلى قيمة الحقيقة.

other_array[first_array == item]

أي عملية منطقية تعمل:

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

تأخذ الطريقة غير الصفرية منطقيًا أيضًا:

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

الأصفار هما ل tuple من المؤشرات (على افتراض first_array هو 1D) ثم العنصر الأول في مجموعة من المؤشرات.


بديل لاستخدام العنصر الأول من 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 بالتحقق من جميع العناصر للمطابقة. سيكون التعبير عن المولد أسرع إذا كان هناك تطابق مبكر في الصفيف.


فقط لإضافة بديل numba جدا و numba مفيد على أساس 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 وهي غير مختصرة) ولكنها ستفشل إذا لم يتم العثور على تطابق:

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

لمصفوفات 1D ، أوصي np.flatnonzero(array == value)[0] ، أي ما يعادل كلا np.nonzero(array == value)[0][0] و np.where(array == value)[0][0] ولكن يتجنب قبح إلغاء تجميع فئة 1 عنصر.


نعم ، هذه هي الإجابة المقدمة على صفيف مصفوفة ، مصفوفة ، وقيمة ، عنصر ، للبحث عنها.

itemindex = numpy.where(array==item)

والنتيجة هي الصفوف مع أول كل مؤشرات الصف ، ثم كل مؤشرات العمود.

على سبيل المثال ، إذا كان المصفوفة مكونين ، وكان يحتوي على عنصرك في موقعين

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

سيكون مساويا للعنصر الخاص بك ، وكذلك

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

numpy.where


يمكنك أيضا تحويل مجموعة 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.


يمكنك استخدام وظيفة lambda للتعامل مع المشكلة ، ويعمل على حد سواء على مجموعة مصفوفة وقائمة.

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

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]

للحصول على أول فهرس للعناصر التي تمت تصفيتها.


l.index(x) بارجاع الأصغر i بحيث يكون i هو مؤشر التواجد الأول لـ x في القائمة.

يمكن للمرء أن يفترض بأمان أن الدالة index() في Python يتم تنفيذها بحيث تتوقف بعد العثور على أول تطابق ، وينتج عن ذلك أداء متوسط ​​مثالي.

للعثور على عنصر وقف بعد المباراة الأولى في مجموعة numpy استخدام np.ndenumerate ( np.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 ، and argmax ) التي يمكن استخدامها للعثور على عنصر في صفيف ، ولكن جميعها لها العيب في المرور بالصفيف بأكمله بحثًا عن كل التكرارات ، وبالتالي لا يتم تحسينها للعثور على العنصر الأول. لاحظ أيضًا أنه في 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 في %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

هذا هو قضية Numpy Github مفتوحة.

انظر أيضا: Numpy: العثور على أول مؤشر للقيمة بسرعة





numpy