Yanıtlar:
Evet, aramak için bir NumPy dizisi array
ve bir değer verilen cevap item
:
itemindex = numpy.where(array==item)
Sonuç, önce tüm satır indekslerini, ardından tüm sütun indekslerini içeren bir demettir.
Örneğin, bir dizi iki boyutsa ve öğenizi iki konumda içeriyorsa,
array[itemindex[0][0]][itemindex[1][0]]
öğenize eşit olur ve böylece
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
burada biraz daha yararlı olurdu:itemindex = np.argwhere(array==item)[0]; array[tuple(itemindex)]
where
herhangi bir dizi üzerinde çalışır ve bir 3D dizi, vb. kullanıldığında uzunluk 3 bir demet dönecektir.
Yalnızca bir değerin ilk oluşumunun dizinine ihtiyacınız varsa, kullanabilirsiniz nonzero
(veya where
bu durumda aynı şey anlamına gelir):
>>> 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
Birçok değerin her birinin ilk dizinine ihtiyacınız varsa , yukarıdakiyle aynı şekilde tekrar tekrar yapabilirsiniz, ancak daha hızlı olabilecek bir hile vardır. Aşağıda, her bir alt dizinin ilk öğesinin indeksleri bulunur :
>>> nonzero(r_[1, diff(t)[:-1]])
(array([0, 3, 5, 6, 7, 8]),)
Hem 3'lü dizinin hem de 8'li dizinin her ikisinin de başlangıcını bulduğuna dikkat edin:
[ 1 , 1, 1, 2 , 2, 3 , 8 , 3 , 8 , 8]
Dolayısıyla , her bir değerin ilk oluşumunu bulmaktan biraz farklıdır . Programınızda, istediğinizi elde etmek için sıralı bir sürümüyle çalışabilirsiniz t
:
>>> st = sorted(t)
>>> nonzero(r_[1, diff(st)[:-1]])
(array([0, 3, 5, 7]),)
r_
mısınız?
r_
bitiştirir; veya daha doğrusu, dilim nesnelerini her eksen boyunca birleştirmeye çevirir. Onun hstack
yerine kullanmış olabilirdim ; bu daha az kafa karıştırıcı olabilir. Hakkında daha fazla bilgi için belgelere bakın r_
. Ayrıca bir c_
.
vals, locs = np.unique(t, return_index=True)
Ayrıca bir NumPy dizisini havadan listeye dönüştürebilir ve dizinini alabilirsiniz. Örneğin,
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
Yazdırılacaktır 1.
[find_list.index(index_list[i]) for i in range(len(index_list))]
find_list
bir NumPy dizisine object
(veya uygun olan daha spesifik bir şeye) dönüştürebilir ve yapabilirsiniz find_arr[index_list]
.
Sadece çok performanslı ve kullanışlı numbanp.ndenumerate
ilk dizini bulmak için alternatif :
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.
Bu oldukça hızlıdır ve çok boyutlu dizilerle doğal olarak ilgilenir :
>>> 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,)
Bu, veya tuşlarını kullanan herhangi bir yaklaşımdan çok daha hızlı olabilir (çünkü işlemi kısa devre yapar) .np.where
np.nonzero
Bununla birlikte , çok boyutlu dizilerle np.argwhere
de zarif bir şekilde başa çıkabilir (manuel olarak bir tupa dökmeniz gerekir ve kısa devre yapmazsınız), ancak eşleşme bulunmazsa başarısız olur:
>>> tuple(np.argwhere(arr1 == 2)[0])
(2, 2, 2)
>>> tuple(np.argwhere(arr2 == 2)[0])
(5,)
@njit
bir kısaltmadır jit(nopython=True)
işlev tamamen böylece çağrıları tercüman Python tümüyle kaldırıldığından emin ilk çalıştırma anında on-the-fly derlenmiş olacak yani.
Bunu başka bir şeye dizin olarak kullanacaksanız, diziler yayınlanabilirse, boole dizinlerini kullanabilirsiniz; açık endekslere ihtiyacınız yoktur. Bunu yapmanın en basit yolu, bir doğruluk değerine dayalı olarak indekslemektir.
other_array[first_array == item]
Herhangi bir boole işlemi çalışır:
a = numpy.arange(100)
other_array[first_array > 50]
Sıfır olmayan yöntem de booleans alır:
index = numpy.nonzero(first_array == item)[0][0]
İki sıfır, bir dizi indeks içindir (ilk_dizinin 1D olduğu varsayılarak) ve daha sonra indeksler dizisindeki ilk öğe içindir.
l.index(x)
En küçük döndüren ı öyle ki ben listedeki x ilk geçtiği endeksidir.
index()
Python'daki işlevin, ilk eşleşmeyi bulduktan sonra durması için uygulandığını güvenle varsayabiliriz ve bu da optimum ortalama performansla sonuçlanır.
NumPy dizisindeki ilk eşleşmeden sonra duran bir öğeyi bulmak için bir yineleyici ( ndenumerate ) kullanın.
In [67]: l=range(100)
In [68]: l.index(2)
Out[68]: 2
NumPy dizisi:
In [69]: a = np.arange(100)
In [70]: next((idx for idx, val in np.ndenumerate(a) if val==2))
Out[70]: (2L,)
Her iki yöntemin index()
ve next
öğe bulunamazsa bir hata döndürdüğünü unutmayın . İle next
öğenin bulunmaması durumunda özel bir değer döndürmek için ikinci bir bağımsız değişken kullanılabilir.
In [77]: next((idx for idx, val in np.ndenumerate(a) if val==400),None)
NumPy ( argmax
, where
ve nonzero
) öğesinde bir dizideki bir öğeyi bulmak için kullanılabilecek başka işlevler de vardır , ancak hepsinin tüm oluşumları arayan tüm diziyi geçme dezavantajı vardır , bu nedenle ilk öğeyi bulmak için optimize edilmez. Bunu da not edin where
ve nonzero
dizileri döndürün, böylece dizini almak için ilk öğeyi seçmeniz gerekir.
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),)
Büyük diziler için , aranan öğe dizinin%timeit
başındayken ( IPython kabuğunda kullanarak) bir yineleyici kullanan çözümün daha hızlı olduğunu kontrol etmek yeterlidir:
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
Bu açık bir NumPy GitHub sorunudur .
Ayrıca bakınız: Numpy: değerin ilk dizinini hızlı bulun
%timeit next((idx for idx, val in np.ndenumerate(a) if val==99999))
mu? Neden 1000 kat daha yavaş olduğunu merak ediyorsanız - bunun nedeni, sayısal diziler üzerindeki python döngülerinin kötü bir şekilde yavaş olmasıdır.
argmax
ve where
bu durumda çok daha hızlı
Tek boyutlu sıralı diziler için, NumPy tamsayısı (konum) döndüren numpy.searchsorted kullanmak çok daha basit ve verimli O (log (n)) olacaktır . Örneğin,
arr = np.array([1, 1, 1, 2, 3, 3, 4])
i = np.searchsorted(arr, 3)
Dizinin zaten sıralandığından emin olun
Ayrıca, döndürülen dizinin i gerçekten aranan öğeyi içerip içermediğini kontrol edin, çünkü searchsorted'ın ana hedefi düzeni korumak için öğelerin nereye ekleneceği dizinleri bulmaktır.
if arr[i] == 3:
print("present")
else:
print("not present")
Herhangi bir ölçüt üzerinde dizin oluşturmak için aşağıdakine benzer bir şey yapabilirsiniz:
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
Ve işte list.index () 'in yaptığı şeyi yapmak için hızlı bir işlev, ancak bulunmazsa bir istisna oluşturmaz. Dikkat - bu büyük dizilerde muhtemelen çok yavaş. Bir yöntem olarak kullanmayı tercih ederseniz, bunu diziler için maymun yaması yapabilirsiniz.
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]
Np.where () öğesinden ilk öğeyi seçmenin bir alternatifi, aşağıdaki gibi bir üreteç ifadesini numaralandırma ile birlikte kullanmaktır:
>>> 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
İki boyutlu bir dizi için:
>>> 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)
Bu yaklaşımın avantajı, ilk eşleşme bulunduktan sonra dizinin öğelerini kontrol etmeyi durdurması, oysa np.where tüm eşleşme için öğeleri kontrol etmesidir. Dizinin başlarında eşleşme varsa bir üreteç ifadesi daha hızlı olur.
None
bir yedek olarak geri dönecek olsaydı, bu olur next((i for i, x_i in enumerate(x) if x_i == 2), None)
.
NumPy'de bunu başarmak için bir araya getirilebilecek birçok işlem var. Bu, öğeye eşit elemanların endekslerini döndürür:
numpy.nonzero(array - item)
Daha sonra tek bir öğe almak için listelerin ilk öğelerini alabilirsiniz.
Numpy_indexed paketi (reddi, onun yazarım) numpy.ndarray için list.index bir vectorized eşdeğerini içermektedir; yani:
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]
Bu çözüm performansı vektörleştirdi, ndarralara genelleşti ve eksik değerlerle başa çıkmanın çeşitli yollarına sahip.
Not: bu python 2.7 sürümü için
Sorunla başa çıkmak için bir lambda işlevi kullanabilirsiniz ve hem NumPy dizisi hem de liste üzerinde çalışır.
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]
Ve kullanabilirsiniz
result[0]
filtrelenen öğelerin ilk dizinini almak için.
Python 3.6 için şunu kullanın:
list(result)
onun yerine
result
<filter object at 0x0000027535294D30>
Python 3 ile sonuçlanır (Python 3.6.3 üzerinde test edilmiştir). Belki de Python 3 için güncelleme?