J'ai essayé de trouver des entrées dans un tableau contenant une sous-chaîne avec np.where et une condition in:
import numpy as np
foo = "aa"
bar = np.array(["aaa", "aab", "aca"])
np.where(foo in bar)
cela ne retourne qu'un tableau vide.
Pourquoi est-ce si?
Et existe-t-il une bonne solution alternative?
Nous pouvons utiliser np.core.defchararray.find
pour trouver la position de la chaîne foo
dans chaque élément de bar
, ce qui retournerait -1
s'il n'est pas trouvé. Ainsi, il pourrait être utilisé pour détecter si foo
est présent ou non dans chaque élément en vérifiant la présence de -1
dans la sortie de find
. Enfin, nous utiliserions np.flatnonzero
pour obtenir les index des correspondances. Donc, nous aurions une implémentation, comme si -
np.flatnonzero(np.core.defchararray.find(bar,foo)!=-1)
Exemple de cycle -
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])
Vous pouvez aussi faire quelque chose comme ça:
mask = [foo in x for x in bar]
filter = bar[ np.where( mask * bar != '') ]
La façon dont vous essayez d'utiliser np.where
est incorrecte. Le premier argument de np.where
devrait être un tableau booléen, et vous le transmettez simplement à un booléen.
foo in bar
>>> False
np.where(False)
>>> (array([], dtype=int32),)
np.where(np.array([True, True, False]))
>>> (array([0, 1], dtype=int32),)
Le problème est que numpy ne définit pas l'opérateur in
comme une opération booléenne élément-wise .
Une façon dont vous pouvez accomplir ce que vous voulez est avec une compréhension de liste.
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]
Regardez quelques exemples d'utilisation de in
:
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)
Cela ressemble à in
lorsqu'il est utilisé avec un tableau fonctionne comme si le tableau était une liste. ndarray
a une méthode __contains__
, donc in
fonctionne, mais c'est probablement simple.
Mais dans tous les cas, notez que in alist
ne vérifie pas les sous-chaînes. La strings
__contains__
effectue le test de la sous-chaîne, mais je ne connais aucune classe intégrée qui propage le test jusqu'aux chaînes du composant.
Comme Divakar
montre qu'il existe une collection de fonctions numpy qui applique des méthodes de chaîne à des éléments individuels d'un tableau.
In [42]: np.char.find(bar, 'aa')
Out[42]: array([ 0, 0, -1])
Docstring:
Ce module contient un ensemble de fonctions pour les opérations et méthodes de chaîne vectorisée. L'alias préféré pourdefchararray
estnumpy.char
.
Pour des opérations comme celle-ci, je pense que les vitesses de np.char
sont à peu près les mêmes qu'avec:
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)
D'autres tests suggèrent que la ndarray
__contains__
opère sur la version flat
du tableau, c'est-à-dire que la forme n'affecte pas son comportement.