2016-08-17 3 views
1

J'ai besoin de trouver des indices de toutes les occurrences d'un motif particulier dans une chaîne (ou un vecteur numérique). Par exemple, étant donné la liste booleen (dataframe):matlabish "strncmp" en python

z = 
15 False 
16 False 
17 False 
18 False 
19 False 
20 False 
21 False 
22 False 
23 False 
24  True 
25  True 
26  True 
27 False 
28 False 
29 False 
30 False 
31 False 
32 False 
33 False 
34 False 
35 False 
36  True 
37 False 
38 False 
39 False 
40  True 
41 False 
42 False 
43 False 
44 False 
45  True 
46  True 
47  True 
48 False 
49 False 

Je suis intéressé par une fonction qui renvoie les indices de toutes les occurrences de trois « vrai » dans une rangée, dans cet exemple, je devrais obtenir l'indice

>> result = some_function(z) 

>> print result 

>> [24, 45] 

Dans matlab c'est assez facile avec la fonction strcmp, qui fait exactement ce dont j'ai besoin. Je suis sûr qu'il y a une fonction similaire dans Python.

J'ai essayé d'utiliser 'if ['True', 'True', 'True'] in z: .... mais je fais quelque chose de mal.

UPD J'ai trouvé une solution très simple et générale à ces problèmes, qui fonctionne avec tout type de données:

def find_subarray_in_array(sub_array, large_array): 
    large_array_view = as_strided(large_array, shape=(len(large_array) - len(sub_array) + 1, len(sub_array)), strides=(large_array.dtype.itemsize,) * 2) 
    return where(numpy.all(large_array_view == sub_array, axis=1))[0] 

où « sub_array » est le modèle qui devrait être trouvé dans le tableau plus large « large_array » .

Répondre

1

Je suppose ici que vos entrées sont des listes:

inds = 
[15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 
31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 
47, 48, 49] 
bools = 
[False,False,False,False,False,False,False,False,False, True, True, 
True,False,False,False,False,False,False,False,False,False, True, 
False,False,False, True,False,False,False,False, True, True, True, 
False,False] 

Vous souhaitez ensuite vérifier le modèle [Vrai, vrai, vrai]

pattern = [True, True, True] 

La comparaison nécessaire est alors fait par:

[inds[i] for i in range(len(bools)) if bools[i:i+len(pattern)] == pattern ] 

Retours:

[24, 45]

+0

@ Arnoldklein, cette approche fonctionne pour vous? –

+0

@RahukMadhavan, oui c'est le cas, mais idéalement, il ne devrait pas utiliser le "inds" explicitement. Fondamentalement, étant donné une liste 1Dim de True/False (sans inds), il devrait retourner leurs index. Mais merci, j'apprécie votre aide. –

+0

si vous avez juste besoin des indices, remplacez simplement inds [i] par i lui-même. –

1

Bien que cela puisse être fait en utilisant la liste compréhensions, vous avez perdu beaucoup de l'avantage de l'utilisation de tableaux numpy ou dataframes pandas, en particulier que vous pouvez vectoriser opérations. La meilleure approche serait d'utiliser numpy.correlate, ce qui vous permet de comparer deux tableaux pour voir à quel point ils correspondent. Vous pouvez l'utiliser pour trouver tous les endroits où votre cible (une séquence de trois valeurs True) correspond parfaitement avec le tableau lui-même (la corrélation est 3, donc 3 éléments correspondent). Cela trouve le centre de la corrélation, donc si vous voulez trouver le début, vous devez soustraire un du résultat. Donc, cela va faire ce que vous voulez (en supposant inds et vals sont des tableaux numpy):

targ = [True, True, True] 
corr = np.correlate(vals.astype('int'), targ, mode='same') 
matches = np.where(corr == len(targ))[0]-len(targ)//2 
result = inds[matches] 

Si les indices seront toujours séquentielle (par exemple 13,14,15,16,...), vous pouvez simplifier ceci:

targ = [True, True, True] 
corr = inds[np.correlate(vals.astype('int'), targ, mode='same') == len(targ)]-len(targ)//2 
+0

très soigné! Merci! –