Bir dizi verilen koşulun öğelerini nasıl seçerim?


156

Bir numpy dizi olduğunu varsayalım x = [5, 2, 3, 1, 4, 5], y = ['f', 'o', 'o', 'b', 'a', 'r']. 1'den büyük ve 5'ten küçük yöğelere karşılık gelen öğeleri seçmek istiyorum x.

denedim

x = array([5, 2, 3, 1, 4, 5])
y = array(['f','o','o','b','a','r'])
output = y[x > 1 & x < 5] # desired output is ['o','o','a']

ama bu işe yaramıyor. Bunu nasıl yaparım?

Yanıtlar:


220

Parantez eklerseniz ifadeniz çalışır:

>>> y[(1 < x) & (x < 5)]
array(['o', 'o', 'a'], 
      dtype='|S1')

1
Bu güzel .. vecMask = 1 <x, diğer vektör maskeleriyle birleştirilebilen vecMask = (False, True, ...) gibi bir vektör maskesi oluşturur. Her eleman, bir kaynak vektörün elemanlarını (Doğru) ya da almamak (Yanlış) koşuludur. Bu tam sürüm numpy.extract (vecMask, vecSrc) veya numpy.where (vecMask, vecSrc, vecSrc2) ile de kullanılabilir.
MasterControlProgram

6
@JennyYueJin: Öncelik yüzünden olur. (Bitsel) &önceliğe göre daha yüksek önceliğe sahiptir <ve >bu da (mantıksal) değerinden daha yüksek önceliğe sahiptir and. x > 1 and x < 5önce eşitsizlikleri sonra mantıksal birleşimi değerlendirir; ve (içindeki değerler) x > 1 & x < 5bitsel birleşimini , ardından eşitsizlikleri değerlendirir. eşitsizlikleri önce değerlendirmeye zorlar, bu nedenle tüm işlemler amaçlanan sırada gerçekleşir ve sonuçların hepsi iyi tanımlanır. Dokümanlara buradan bakın. 1x(x > 1) & (x < 5)
calavicci

@ ru111 Python 3.6 üzerinde de çalışır (çalışmayı durdurması için bir neden yoktur).
jfs

"ValueError: Birden fazla öğeye sahip bir dizinin gerçek değeri belirsiz. A.any () veya a.all ()" kullanın
ru111

@ ru111 yazmalısınız (0 < x) & (x < 10)(cevapta gösterildiği gibi), bunun yerine 0 < x < 10herhangi bir Python sürümünde numpy dizileri için çalışmaz.
jfs

34

IMO OP aslında istemiyor np.bitwise_and()(aka &) ama aslında istiyor ve np.logical_and()çünkü mantıksal değerleri karşılaştırıyorlar Trueve False- farkı görmek için mantıksal ve bitsel olarak bu SO yazısına bakın.

>>> x = array([5, 2, 3, 1, 4, 5])
>>> y = array(['f','o','o','b','a','r'])
>>> output = y[np.logical_and(x > 1, x < 5)] # desired output is ['o','o','a']
>>> output
array(['o', 'o', 'a'],
      dtype='|S1')

Ve bunu yapmanın eşdeğer yolu np.all(), axisargümanı uygun şekilde ayarlamaktır .

>>> output = y[np.all([x > 1, x < 5], axis=0)] # desired output is ['o','o','a']
>>> output
array(['o', 'o', 'a'],
      dtype='|S1')

sayılarla:

>>> %timeit (a < b) & (b < c)
The slowest run took 32.97 times longer than the fastest. This could mean that an intermediate result is being cached.
100000 loops, best of 3: 1.15 µs per loop

>>> %timeit np.logical_and(a < b, b < c)
The slowest run took 32.59 times longer than the fastest. This could mean that an intermediate result is being cached.
1000000 loops, best of 3: 1.17 µs per loop

>>> %timeit np.all([a < b, b < c], 0)
The slowest run took 67.47 times longer than the fastest. This could mean that an intermediate result is being cached.
100000 loops, best of 3: 5.06 µs per loop

böylece kullanarak np.all()yavaş olmakla &ve logical_andaynı.


7
Değerlendirilenler hakkında nasıl konuştuğunuz konusunda biraz dikkatli olmanız gerekir. Örneğin, output = y[np.logical_and(x > 1, x < 5)], x < 5 olup bu değerlendirme fonksiyonu dışında olur, çünkü ikinci bağımsız değişken olmasına rağmen, (muhtemelen büyük bir dizi oluşturma) değerlendirildi. IOW, logical_andönceden değerlendirilmiş iki argümanı geçer. Bu olağan durum farklıdır a and bki, beğer değerlendirilmez atruelike olduğunu.
DSM

15
boole diziler için bitwise_and () ve logical_and () arasında bir fark yoktur
jfs

21

@JF Sebastian'ın ve @Mark Mikofski'nin cevaplarına bir ayrıntı ekleyin:
Eğer kişi ilgili dizinleri (dizinin gerçek değerleri yerine) almak istiyorsa, aşağıdaki kod işe yarar :

Birden fazla (tümü) koşulu yerine getirmek için:

select_indices = np.where( np.logical_and( x > 1, x < 5) )[0] #   1 < x <5

Birden çok (veya) koşulu yerine getirmek için:

select_indices = np.where( np.logical_or( x < 1, x > 5 ) )[0] # x <1 or x >5

2
Numpy.where öğesinin yalnızca bir dizin dizisi döndürmeyeceğini, bunun yerine diziler içeren bir demet (bu durumda, koşul.nonzero () çıktısı) döndüreceğini (the array of indices you want,)unutmayın, bu nedenle istediğiniz select_indices = np.where(...)[0]sonucu almanız gerekir . ve bekliyoruz.
calavicci

5

Bu np.vectorizetür görevler için kullanmayı seviyorum . Aşağıdakileri göz önünde bulundur:

>>> # Arrays
>>> x = np.array([5, 2, 3, 1, 4, 5])
>>> y = np.array(['f','o','o','b','a','r'])

>>> # Function containing the constraints
>>> func = np.vectorize(lambda t: t>1 and t<5)

>>> # Call function on x
>>> y[func(x)]
>>> array(['o', 'o', 'a'], dtype='<U1')

Avantajı, vektörize fonksiyona çok daha fazla tür kısıtlama ekleyebilirsiniz.

Umarım yardımcı olur.


1
Bu NumPy'de endeksleme yapmak için iyi bir yol değildir (çok yavaş olacaktır).
Alex Riley

1

Aslında bunu şu şekilde yaparım:

L1, koşul 1'i karşılayan öğelerin dizin listesidir; (belki L1 almak için somelist.index(condition1)veya kullanabilirsiniz np.where(condition1).)

Benzer şekilde, koşul 2'yi karşılayan elementlerin bir listesi olan L2'yi alırsınız;

Sonra kullanarak kavşak bulabilirsiniz intersect(L1,L2).

Ayrıca, tatmin etmek için birden fazla koşul alırsanız birden çok listenin kesişimini de bulabilirsiniz.

Ardından başka bir diziye dizin uygulayabilirsiniz, örneğin, x.


0

2B diziler için bunu yapabilirsiniz. Koşulu kullanarak bir 2B maske oluşturun. Koşul maskesini diziye bağlı olarak int veya float olarak belirleyin ve orijinal diziyle çarpın.

In [8]: arr
Out[8]: 
array([[ 1.,  2.,  3.,  4.,  5.],
       [ 6.,  7.,  8.,  9., 10.]])

In [9]: arr*(arr % 2 == 0).astype(np.int) 
Out[9]: 
array([[ 0.,  2.,  0.,  4.,  0.],
       [ 6.,  0.,  8.,  0., 10.]])
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.