Jawaban:
Ya, inilah jawaban yang diberikan array NumPy array
,, dan nilai item
,, untuk mencari:
itemindex = numpy.where(array==item)
Hasilnya adalah tuple dengan pertama semua indeks baris, lalu semua indeks kolom.
Misalnya, jika array dua dimensi dan berisi item Anda di dua lokasi, maka
array[itemindex[0][0]][itemindex[1][0]]
akan sama dengan item Anda dan begitu juga
array[itemindex[0][1]][itemindex[1][1]]
rows, columns = np.where(array==item); first_idx = sorted([r for r, c in zip(rows, columns) if c == 0])[0]
np.argwhere
akan sedikit lebih berguna di sini:itemindex = np.argwhere(array==item)[0]; array[tuple(itemindex)]
where
bekerja pada array apa pun, dan akan mengembalikan tuple dengan panjang 3 saat digunakan pada array 3D, dll.
Jika Anda memerlukan indeks kemunculan pertama hanya satu nilai , Anda dapat menggunakan nonzero
(atau where
, yang jumlahnya sama dengan hal ini):
>>> 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
Jika Anda memerlukan indeks pertama dari masing-masing banyak nilai , Anda jelas dapat melakukan hal yang sama seperti di atas berulang kali, tetapi ada trik yang mungkin lebih cepat. Berikut ini menemukan indeks elemen pertama dari setiap berikutnya :
>>> nonzero(r_[1, diff(t)[:-1]])
(array([0, 3, 5, 6, 7, 8]),)
Perhatikan bahwa ia menemukan awal dari kedua urutan 3s dan kedua berikutnya dari 8s:
[ 1 , 1, 1, 2 , 2, 3 , 8 , 3 , 8 , 8]
Jadi itu sedikit berbeda dari menemukan kemunculan pertama dari setiap nilai. Dalam program Anda, Anda mungkin dapat bekerja dengan versi yang diurutkan t
untuk mendapatkan yang Anda inginkan:
>>> st = sorted(t)
>>> nonzero(r_[1, diff(st)[:-1]])
(array([0, 3, 5, 7]),)
r_
itu?
r_
menggabungkan; atau, lebih tepatnya, ia menerjemahkan objek irisan menjadi gabungan sepanjang setiap sumbu. Saya bisa menggunakannya hstack
sebagai gantinya; yang mungkin kurang membingungkan. Lihat dokumentasi untuk informasi lebih lanjut tentang r_
. Ada juga a c_
.
vals, locs = np.unique(t, return_index=True)
Anda juga dapat mengonversi array NumPy ke daftar di udara dan mendapatkan indeksnya. Sebagai contoh,
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
Ini akan mencetak 1.
[find_list.index(index_list[i]) for i in range(len(index_list))]
find_list
ke array NumPy object
(atau apa pun yang lebih spesifik yang sesuai) dan lakukan saja find_arr[index_list]
.
Hanya untuk menambahkan yang sangat performant dan praktis numbaalternatif berdasarkan np.ndenumerate
untuk menemukan indeks pertama:
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.
Ini cukup cepat dan berhubungan secara alami dengan array multidimensi :
>>> 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,)
Ini bisa jauh lebih cepat (karena itu hubungan arus pendek operasi) daripada pendekatan apa pun menggunakan np.where
atau np.nonzero
.
Namun np.argwhere
dapat juga menangani array multidimensi dengan anggun (Anda perlu secara manual melemparkannya ke tuple dan tidak mengalami hubungan pendek) tetapi akan gagal jika tidak ditemukan kecocokan:
>>> tuple(np.argwhere(arr1 == 2)[0])
(2, 2, 2)
>>> tuple(np.argwhere(arr2 == 2)[0])
(5,)
@njit
adalah singkatan jit(nopython=True)
yaitu fungsi akan sepenuhnya dikompilasi on-the-fly pada saat menjalankan pertama sehingga panggilan juru bahasa Python sepenuhnya dihapus.
Jika Anda akan menggunakan ini sebagai indeks ke sesuatu yang lain, Anda dapat menggunakan indeks boolean jika array dapat disiarkan; Anda tidak perlu indeks eksplisit. Cara termudah mutlak untuk melakukan ini adalah dengan hanya indeks berdasarkan nilai kebenaran.
other_array[first_array == item]
Semua operasi boolean berfungsi:
a = numpy.arange(100)
other_array[first_array > 50]
Metode bukan nol juga membutuhkan boolean:
index = numpy.nonzero(first_array == item)[0][0]
Dua nol adalah untuk tupel indeks (dengan asumsi first_array adalah 1D) dan kemudian item pertama dalam array indeks.
l.index(x)
mengembalikan i terkecil sehingga saya adalah indeks kemunculan pertama x dalam daftar.
Orang dapat dengan aman berasumsi bahwa index()
fungsi dalam Python diimplementasikan sehingga berhenti setelah menemukan kecocokan pertama, dan ini menghasilkan kinerja rata-rata yang optimal.
Untuk menemukan elemen yang berhenti setelah pertandingan pertama dalam array NumPy gunakan iterator ( ndenumerate ).
In [67]: l=range(100)
In [68]: l.index(2)
Out[68]: 2
Array NumPy:
In [69]: a = np.arange(100)
In [70]: next((idx for idx, val in np.ndenumerate(a) if val==2))
Out[70]: (2L,)
Perhatikan bahwa kedua metode index()
dan next
mengembalikan kesalahan jika elemen tidak ditemukan. Dengan next
, seseorang dapat menggunakan argumen kedua untuk mengembalikan nilai khusus jika elemen tidak ditemukan, misalnya
In [77]: next((idx for idx, val in np.ndenumerate(a) if val==400),None)
Ada fungsi-fungsi lain di NumPy ( argmax
,, where
dan nonzero
) yang dapat digunakan untuk menemukan elemen dalam array, tetapi mereka semua memiliki kelemahan untuk menelusuri seluruh array untuk mencari semua kejadian, sehingga tidak dioptimalkan untuk menemukan elemen pertama. Perhatikan juga itu where
dan nonzero
kembalikan array, jadi Anda harus memilih elemen pertama untuk mendapatkan indeks.
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),)
Hanya memeriksa bahwa untuk array besar, solusi menggunakan iterator lebih cepat ketika item yang dicari adalah di awal array (menggunakan %timeit
di shell IPython):
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
Ini adalah masalah NumPy GitHub terbuka .
Lihat juga: Numpy: cari indeks nilai pertama dengan cepat
%timeit next((idx for idx, val in np.ndenumerate(a) if val==99999))
bekerja? Jika Anda bertanya-tanya mengapa 1000 kali lebih lambat - itu karena loop python atas array numpy terkenal lambat.
argmax
dan where
jauh lebih cepat dalam hal ini (elemen yang dicari di akhir array)
Untuk array yang diurutkan satu dimensi , akan jauh lebih sederhana dan efisien O (log (n)) untuk menggunakan numpy.searchsorted yang mengembalikan integer NumPy (posisi). Sebagai contoh,
arr = np.array([1, 1, 1, 2, 3, 3, 4])
i = np.searchsorted(arr, 3)
Pastikan array sudah diurutkan
Juga periksa apakah indeks yang dikembalikan saya benar-benar berisi elemen yang dicari, karena tujuan utama pencarian adalah untuk menemukan indeks di mana elemen harus dimasukkan untuk menjaga ketertiban.
if arr[i] == 3:
print("present")
else:
print("not present")
Untuk mengindeks pada kriteria apa pun, Anda dapat melakukannya seperti berikut ini:
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
Dan inilah fungsi cepat untuk melakukan apa yang list.index () lakukan, kecuali tidak menimbulkan pengecualian jika tidak ditemukan. Waspadalah - ini mungkin sangat lambat pada array besar. Anda mungkin bisa menambal monyet ini ke array jika Anda lebih suka menggunakannya sebagai metode.
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]
Alternatif untuk memilih elemen pertama dari np.where () adalah dengan menggunakan ekspresi generator bersama dengan penghitungan, seperti:
>>> 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
Untuk array dua dimensi yang akan dilakukan:
>>> 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)
Keuntungan dari pendekatan ini adalah bahwa ia berhenti memeriksa elemen-elemen array setelah kecocokan pertama ditemukan, sedangkan np.where memeriksa semua elemen untuk kecocokan. Ekspresi generator akan lebih cepat jika ada kecocokan di awal array.
None
sebagai fallback, itu akan menjadi next((i for i, x_i in enumerate(x) if x_i == 2), None)
.
Ada banyak operasi di NumPy yang mungkin bisa disatukan untuk mencapai ini. Ini akan mengembalikan indeks elemen yang sama dengan item:
numpy.nonzero(array - item)
Anda kemudian dapat mengambil elemen pertama dari daftar untuk mendapatkan elemen tunggal.
The numpy_indexed paket (disclaimer, saya penulisnya) berisi setara Vectorized dari list.index untuk numpy.ndarray; itu adalah:
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]
Solusi ini memiliki kinerja vektor, digeneralisasikan ke ndarray, dan memiliki berbagai cara untuk menangani nilai yang hilang.
Catatan: ini untuk versi python 2.7
Anda dapat menggunakan fungsi lambda untuk mengatasi masalah, dan berfungsi baik pada array dan daftar 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]
Dan Anda bisa menggunakannya
result[0]
untuk mendapatkan indeks pertama dari elemen yang difilter.
Untuk python 3.6, gunakan
list(result)
dari pada
result
<filter object at 0x0000027535294D30>
pada Python 3 (diuji pada Python 3.6.3). Mungkin pembaruan untuk Python 3?