it-swarm.com.de

Numpy Array, wie wählt man Indizes aus, die mehrere Bedingungen erfüllen?

Angenommen, ich habe ein numpy-Array x = [5, 2, 3, 1, 4, 5], y = ['f', 'o', 'o', 'b', 'a', 'r']. Ich möchte die Elemente in y auswählen, die den Elementen in x entsprechen, die größer als 1 und kleiner als 5 sind.

Ich habe es versucht

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

aber das geht nicht. Wie würde ich das machen?

105
Bob

Ihr Ausdruck funktioniert, wenn Sie Klammern hinzufügen:

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

IMO OP will nicht np.bitwise_and() (aka &) , will aber np.logical_and() , weil sie logische Werte wie True und False vergleichen - siehe hierzu SO post on logic vs bitweise , um den Unterschied zu sehen.

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

Ein gleichwertiger Weg ist das mit np.all() , indem das Argument axis entsprechend gesetzt wird.

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

durch die Zahlen:

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

die Verwendung von np.all() ist langsamer, aber & und logical_and sind ungefähr gleich.

29
Mark Mikofski

Fügen Sie @ J.F ein Detail hinzu. Die Antworten von Sebastian und Mark Mikofski:
Wenn Sie die entsprechenden Indizes (und nicht die tatsächlichen Werte des Arrays) erhalten möchten, ist der folgende Code geeignet:

Um mehrere (alle) Bedingungen zu erfüllen:

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

Um mehrere (oder) Bedingungen zu erfüllen:

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

Ich benutze gerne np.vectorize für solche Aufgaben. Folgendes berücksichtigen:

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

Der Vorteil ist, dass Sie der vektorisierten Funktion viele weitere Arten von Einschränkungen hinzufügen können.

Ich hoffe es hilft.

5
user4340135

Eigentlich würde ich es so machen:

L1 ist die Indexliste der Elemente, die die Bedingung 1 erfüllen (möglicherweise können Sie somelist.index(condition1) oder np.where(condition1) verwenden, um L1 zu erhalten.)

Ebenso erhalten Sie L2, eine Liste von Elementen, die die Bedingung 2 erfüllen.

Dann finden Sie einen Schnittpunkt mit intersect(L1,L2).

Sie können auch den Schnittpunkt mehrerer Listen finden, wenn Sie mehrere Bedingungen erfüllen müssen.

Dann können Sie den Index in einem anderen Array anwenden, z. B. x.

1
Shuo Yang

Bei 2D-Arrays können Sie dies tun. Erstellen Sie eine 2D-Maske mit der Bedingung. Schreiben Sie die Bedingungsmaske je nach Array in int oder float und multiplizieren Sie sie mit dem ursprünglichen 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.]])
0
Gautam