web-dev-qa-db-de.com

Suchen Sie nach Einträgen mit einem Teilstring in einem Numpy-Array?

Ich habe versucht, Einträge in einem Array zu finden, das eine Teilzeichenfolge mit np.where und einer in-Bedingung enthält:

import numpy as np
foo = "aa"
bar = np.array(["aaa", "aab", "aca"])
np.where(foo in bar)

dies gibt nur ein leeres Array zurück.
Warum ist das so?
Und gibt es eine gute alternative Lösung?

6
SiOx

Wir können np.core.defchararray.find verwenden, um die Position von foo string in jedem Element von bar zu finden, das -1 zurückgibt, wenn es nicht gefunden wird. Somit könnte es verwendet werden, um zu erkennen, ob in jedem Element eine foo vorhanden ist oder nicht, indem auf der Ausgabe von find nach -1 gesucht wird. Schließlich würden wir np.flatnonzero verwenden, um die Indexe der Übereinstimmungen zu erhalten. Also, wir hätten eine Implementierung wie folgt:

np.flatnonzero(np.core.defchararray.find(bar,foo)!=-1)

Probelauf -

In [91]: bar
Out[91]: 
array(['aaa', 'aab', 'aca'], 
      dtype='|S3')

In [92]: foo
Out[92]: 'aa'

In [93]: np.flatnonzero(np.core.defchararray.find(bar,foo)!=-1)
Out[93]: array([0, 1])

In [94]: bar[2] = 'jaa'

In [95]: np.flatnonzero(np.core.defchararray.find(bar,foo)!=-1)
Out[95]: array([0, 1, 2])
9
Divakar

Sie können auch Folgendes tun:

mask = [foo in x for x in bar]  
filter = bar[ np.where( mask * bar != '') ]
1
htran

Die Art und Weise, wie Sie versuchen, np.where zu verwenden, ist falsch. Das erste Argument von np.where sollte ein boolesches Array sein, und Sie übergeben es einfach als boolesches Array.

foo in bar
>>> False
np.where(False)
>>> (array([], dtype=int32),)
np.where(np.array([True, True, False]))
>>> (array([0, 1], dtype=int32),)

Das Problem ist, dass numpy den Operator in nicht als elementweise boolesche Operation definiert.

Eine Möglichkeit, das zu erreichen, was Sie wollen, ist ein Listenverständnis.

foo = 'aa'
bar = np.array(['aaa', 'aab', 'aca'])
out = [i for i, v in enumerate(bar) if foo in v]
# out = [0, 1]

bar = ['aca', 'bba', 'baa', 'aaf', 'ccc']
out = [i for i, v in enumerate(bar) if foo in v]
# out = [2, 3]
0
Chris Mueller

Schauen Sie sich einige Beispiele für die Verwendung von in an:

In [19]: bar = np.array(["aaa", "aab", "aca"])

In [20]: 'aa' in bar
Out[20]: False

In [21]: 'aaa' in bar
Out[21]: True

In [22]: 'aab' in bar
Out[22]: True

In [23]: 'aab' in list(bar) 

Es sieht aus wie in, wenn es mit einem Array verwendet wird, als ob das Array eine Liste wäre. ndarray hat eine __contains__ Methode, also funktioniert in, aber es ist wahrscheinlich einfach.

Beachten Sie jedoch in jedem Fall, dass in alist nicht nach Teilzeichenfolgen sucht. Die strings__contains__ führt den Teilzeichenfolgentest durch, aber ich kenne keine eingebaute Klasse, die den Test auf die Komponentenzeichenfolgen überträgt.

Wie Divakar zeigt, gibt es eine Sammlung von Numpy-Funktionen, mit denen String-Methoden auf einzelne Elemente eines Arrays angewendet werden.

In [42]: np.char.find(bar, 'aa')
Out[42]: array([ 0,  0, -1])

Docstring:
Dieses Modul enthält eine Reihe von Funktionen für vektorisierte Zeichenfolgenoperationen und -methoden. Der bevorzugte Alias ​​für defchararray ist numpy.char.

Für Operationen wie diese denke ich, sind die np.char Geschwindigkeiten ungefähr gleich wie bei:

In [49]: np.frompyfunc(lambda x: x.find('aa'), 1, 1)(bar)
Out[49]: array([0, 0, -1], dtype=object)

In [50]: np.frompyfunc(lambda x: 'aa' in x, 1, 1)(bar)
Out[50]: array([True, True, False], dtype=object)

Weitere Tests legen nahe, dass der ndarray__contains__ auf die flat-Version des Arrays angewendet werden kann - das heißt, dass die Form das Verhalten nicht beeinflusst.

0
hpaulj