Jika Anda mencari baris pertama di mana item ada di kolom pertama, ini berfungsi (meskipun akan menyebabkan kesalahan indeks jika tidak ada)rows, columns = np.where(array==item); first_idx = sorted([r for r, c in zip(rows, columns) if c == 0])[0]
BrT
29
Bagaimana jika Anda ingin berhenti mencari setelah menemukan nilai pertama? Saya tidak berpikir di mana () sebanding dengan menemukan ()
np.argwhereakan sedikit lebih berguna di sini:itemindex = np.argwhere(array==item)[0]; array[tuple(itemindex)]
Eric
3
Perlu dicatat bahwa jawaban ini menganggap array adalah 2D. wherebekerja pada array apa pun, dan akan mengembalikan tuple dengan panjang 3 saat digunakan pada array 3D, dll.
P. Camilleri
70
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 :
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 tuntuk mendapatkan yang Anda inginkan:
>>> st = sorted(t)>>> nonzero(r_[1, diff(st)[:-1]])(array([0,3,5,7]),)
@ Geoff, r_menggabungkan; atau, lebih tepatnya, ia menerjemahkan objek irisan menjadi gabungan sepanjang setiap sumbu. Saya bisa menggunakannya hstacksebagai gantinya; yang mungkin kurang membingungkan. Lihat dokumentasi untuk informasi lebih lanjut tentang r_. Ada juga a c_.
Vebjorn Ljosa
+1, bagus! (vs NP.where) solusi Anda jauh lebih sederhana (dan mungkin lebih cepat) dalam kasus di mana itu hanya kemunculan pertama dari nilai yang diberikan dalam array 1D yang kita butuhkan
doug
3
Kasus terakhir (menemukan indeks pertama dari semua nilai) diberikan olehvals, locs = np.unique(t, return_index=True)
askewchan
@askewchan versi Anda secara fungsional setara, tapi jauh lebih lambat
Jivan
50
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 2print i
Mungkin perpustakaan telah berubah sejak ini pertama kali ditulis. Tetapi ini adalah solusi pertama yang berhasil untuk saya.
amracel
1
Saya telah memanfaatkan ini untuk menemukan beberapa nilai dalam daftar menggunakan pemahaman daftar:[find_list.index(index_list[i]) for i in range(len(index_list))]
Matt Wenham
1
@ MatWenham Jika cukup besar, Anda dapat mengonversi Anda find_listke array NumPy object(atau apa pun yang lebih spesifik yang sesuai) dan lakukan saja find_arr[index_list].
Narfanar
Benar-benar di luar topik, tetapi ini adalah pertama kalinya saya melihat frasa "di udara" - apa yang paling sering saya lihat, sebagai gantinya, mungkin "on the fly".
flow2k
18
Hanya untuk menambahkan yang sangat performant dan praktis numbaalternatif berdasarkan np.ndenumerateuntuk menemukan indeks pertama:
from numba import njit
import numpy as np
@njitdef 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 :
Ini bisa jauh lebih cepat (karena itu hubungan arus pendek operasi) daripada pendekatan apa pun menggunakan np.whereatau np.nonzero.
Namun np.argwheredapat 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:
@njitadalah singkatan jit(nopython=True)yaitu fungsi akan sepenuhnya dikompilasi on-the-fly pada saat menjalankan pertama sehingga panggilan juru bahasa Python sepenuhnya dihapus.
bartolo-otrit
14
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 nextmengembalikan 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,, wheredan 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 wheredan nonzerokembalikan array, jadi Anda harus memilih elemen pertama untuk mendapatkan indeks.
Hanya memeriksa bahwa untuk array besar, solusi menggunakan iterator lebih cepat ketika item yang dicari adalah di awal array (menggunakan %timeitdi 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
Saya pikir Anda juga harus memasukkan waktu untuk kasus terburuk (elemen terakhir) supaya pembaca tahu apa yang terjadi pada mereka dalam kasus terburuk ketika mereka menggunakan pendekatan Anda.
MSeifert
@ MSeifert Saya tidak bisa mendapatkan waktu yang masuk akal untuk solusi iterator kasus terburuk - Saya akan menghapus jawaban ini sampai saya mengetahui apa yang salah dengan itu
user2314737
1
tidak %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.
MSeifert
@MSeifert tidak, saya tidak tahu itu, tapi saya juga bingung dengan kenyataan bahwa argmaxdan wherejauh lebih cepat dalam hal ini (elemen yang dicari di akhir array)
user2314737
Mereka harus secepat jika elemen di awal. Mereka selalu memproses seluruh array sehingga mereka selalu mengambil waktu yang sama (paling tidak seharusnya).
MSeifert
9
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")
searchsorted bukan nlog (n) karena tidak mengurutkan array sebelum pencarian, ini mengasumsikan bahwa array argumen sudah diurutkan. lihat dokumentasi numpy.searchsorted (tautan di atas)
Alok Nayak
6
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 >= 120In[5]: pts = hsplit(locs, len(locs[0]))In[6]:for pt in pts:.....:print(', '.join(str(p[0])for p in pt))4,4,04,4,14,4,24,4,34,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:passelse:for i, subarray in enumerate(ndarray):try:return[i]+ ndindex(subarray, item)except:passIn[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.
Jika tidak ada kecocokan dalam array sama sekali, metode ini juga memungkinkan Anda menentukan nilai cadangan. Jika contoh pertama dikembalikan Nonesebagai fallback, itu akan menjadi next((i for i, x_i in enumerate(x) if x_i == 2), None).
Erlend Magnus Viggen
4
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.
Jawaban:
Ya, inilah jawaban yang diberikan array NumPy
array
,, dan nilaiitem
,, untuk mencari: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
akan sama dengan item Anda dan begitu juga
numpy. Di mana saja
sumber
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
(atauwhere
, yang jumlahnya sama dengan hal ini):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 :
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:sumber
r_
itu?r_
menggabungkan; atau, lebih tepatnya, ia menerjemahkan objek irisan menjadi gabungan sepanjang setiap sumbu. Saya bisa menggunakannyahstack
sebagai gantinya; yang mungkin kurang membingungkan. Lihat dokumentasi untuk informasi lebih lanjut tentangr_
. Ada juga ac_
.vals, locs = np.unique(t, return_index=True)
Anda juga dapat mengonversi array NumPy ke daftar di udara dan mendapatkan indeksnya. Sebagai contoh,
Ini akan mencetak 1.
sumber
[find_list.index(index_list[i]) for i in range(len(index_list))]
find_list
ke array NumPyobject
(atau apa pun yang lebih spesifik yang sesuai) dan lakukan sajafind_arr[index_list]
.Hanya untuk menambahkan yang sangat performant dan praktis numbaalternatif berdasarkan
np.ndenumerate
untuk menemukan indeks pertama:Ini cukup cepat dan berhubungan secara alami dengan array multidimensi :
Ini bisa jauh lebih cepat (karena itu hubungan arus pendek operasi) daripada pendekatan apa pun menggunakan
np.where
ataunp.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:sumber
@njit
adalah singkatanjit(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.
Semua operasi boolean berfungsi:
Metode bukan nol juga membutuhkan boolean:
Dua nol adalah untuk tupel indeks (dengan asumsi first_array adalah 1D) dan kemudian item pertama dalam array indeks.
sumber
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 ).
Array NumPy:
Perhatikan bahwa kedua metode
index()
dannext
mengembalikan kesalahan jika elemen tidak ditemukan. Dengannext
, seseorang dapat menggunakan argumen kedua untuk mengembalikan nilai khusus jika elemen tidak ditemukan, misalnyaAda fungsi-fungsi lain di NumPy (
argmax
,,where
dannonzero
) 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 ituwhere
dannonzero
kembalikan array, jadi Anda harus memilih elemen pertama untuk mendapatkan indeks.Perbandingan waktu
Hanya memeriksa bahwa untuk array besar, solusi menggunakan iterator lebih cepat ketika item yang dicari adalah di awal array (menggunakan
%timeit
di shell IPython):Ini adalah masalah NumPy GitHub terbuka .
Lihat juga: Numpy: cari indeks nilai pertama dengan cepat
sumber
%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
danwhere
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,
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.
sumber
Untuk mengindeks pada kriteria apa pun, Anda dapat melakukannya seperti berikut ini:
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.
sumber
Untuk array 1D, saya akan merekomendasikan
np.flatnonzero(array == value)[0]
, yang setara dengan keduanyanp.nonzero(array == value)[0][0]
dannp.where(array == value)[0][0]
tetapi menghindari keburukan unboxing tuple 1-elemen.sumber
Alternatif untuk memilih elemen pertama dari np.where () adalah dengan menggunakan ekspresi generator bersama dengan penghitungan, seperti:
Untuk array dua dimensi yang akan dilakukan:
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.
sumber
None
sebagai fallback, itu akan menjadinext((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:
Anda kemudian dapat mengambil elemen pertama dari daftar untuk mendapatkan elemen tunggal.
sumber
The numpy_indexed paket (disclaimer, saya penulisnya) berisi setara Vectorized dari list.index untuk numpy.ndarray; itu adalah:
Solusi ini memiliki kinerja vektor, digeneralisasikan ke ndarray, dan memiliki berbagai cara untuk menangani nilai yang hilang.
sumber
Catatan: ini untuk versi python 2.7
Anda dapat menggunakan fungsi lambda untuk mengatasi masalah, dan berfungsi baik pada array dan daftar NumPy.
Dan Anda bisa menggunakannya
untuk mendapatkan indeks pertama dari elemen yang difilter.
Untuk python 3.6, gunakan
dari pada
sumber
<filter object at 0x0000027535294D30>
pada Python 3 (diuji pada Python 3.6.3). Mungkin pembaruan untuk Python 3?