Hoe selecteer ik elementen van een array gegeven voorwaarde?

Stel dat ik een numpy-array heb x = [5, 2, 3, 1, 4, 5], y = ['f', 'o', 'o', 'b', 'a', 'r']. Ik wil de elementen in yselecteren die overeenkomen met elementen in xdie groter zijn dan 1 en kleiner dan 5.

Ik heb het geprobeerd

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']

maar dit werkt niet. Hoe zou ik dit doen?


Antwoord 1, autoriteit 100%

Je uitdrukking werkt als je haakjes toevoegt:

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

Antwoord 2, autoriteit 17%

IMO OP wil eigenlijk geen np.bitwise_and()(ook bekend als &)maar wil eigenlijk np.logical_and()omdat ze logische waarden vergelijken zoals Trueen False– zie dit SO-bericht op logisch vs. bitwiseom het verschil te zien.

>>> 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')

En een gelijkwaardige manier om dit te doen is met np.all()door het argument axisop de juiste manier in te stellen.

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

door de cijfers:

>>> %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

dus het gebruik van np.all()is langzamer, maar &en logical_andzijn ongeveer hetzelfde.


Antwoord 3, autoriteit 9%

Voeg één detail toe aan @J.F. Sebastian’s en @Mark Mikofski’s antwoorden:
Als men de corresponderende indices wil krijgen (in plaats van de werkelijke waarden van de array), is de volgende code voldoende:

Voor het voldoen aan meerdere (alle) voorwaarden:

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

Voor het voldoen aan meerdere (of) voorwaarden:

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

Antwoord 4, autoriteit 2%

Ik gebruik graag np.vectorizevoor dergelijke taken. Overweeg het volgende:

>>> # 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')

Het voordeel is dat u veel meer soorten beperkingen kunt toevoegen aan de gevectoriseerde functie.

Hopelijk helpt het.


Antwoord 5

Eigenlijk zou ik het zo doen:

L1 is de indexlijst van elementen die voldoen aan voorwaarde 1;(misschien kunt u somelist.index(condition1)of np.where(condition1)gebruiken om L1 te krijgen. )

Op dezelfde manier krijg je L2, een lijst met elementen die voldoen aan voorwaarde 2;

Vervolgens vind je kruising met intersect(L1,L2).

Je kunt ook kruisingen van meerdere lijsten vinden als je aan meerdere voorwaarden moet voldoen.

Dan kun je index toepassen in elke andere array, bijvoorbeeld x.


Antwoord 6

Voor 2D-arrays kunt u dit doen. Maak een 2D-masker met behulp van de voorwaarde. Typ het voorwaardemasker naar int of float, afhankelijk van de array, en vermenigvuldig het met de originele array.

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.]])

Other episodes