8
votes

Trouvez le nombre de zéros avant non-zéro dans une matrice numpue

J'ai un tableau numpy A . J'aimerais retourner le nombre de zéros avant un non-zéro dans A de manière efficace que dans une boucle.

si a = np.array ([0,1,2]) alors np.nonzero (a) [0] [0] retourne 1. Toutefois si A = NP.Array ([0,0,0]) Cela ne fonctionne pas (je voudrais la réponse 3 dans ce cas). Et aussi si A est très grand et le premier non-zéro est proche du début, cela semble inefficace.


3 commentaires

Question connexe: Stackoverflow.com/ Questions / 7632963 / ...


Ticket associé: Github.com/numpy/numpy/issues/2269


@ shx2 hmm .. que le billet s'arrête fondamentalement il y a 2 ans et cela pointe ensuite vers un autre billet qui se tait il y a 10 mois.


6 Réponses :


1
votes

Qu'est-ce qui ne va pas avec l'approche naïve:

def countLeadingZeros(x):
""" Count number of elements up to the first non-zero element, return that count """
    ctr = 0
    for k in x:
        if k == 0:
            ctr += 1
        else: #short circuit evaluation, we found a non-zero so return immediately
            return ctr
    return ctr #we get here in the case that x was all zeros


0 commentaires

1
votes

Je suis surpris de savoir pourquoi personne n'a pas utilisé np.wheres mais

np.where (a) [0] [0] Si NP.Shape (NP. ) [0]) [0]! = 0 autre np.shape (a) [0] fera le tour xxx


0 commentaires

4
votes

En ajoutant un numéro non nul à la fin de la matrice, vous pouvez toujours utiliser NP.Nonzero pour obtenir le résultat souhaité.

A = np.array([0,1,2])
B = np.array([0,0,0])

np.min(np.nonzero(np.hstack((A, 1))))   # --> 1
np.min(np.nonzero(np.hstack((B, 1))))   # --> 3


0 commentaires

5
votes

Voici une version itérative Cyron, qui peut être votre meilleure mise s'il s'agit d'un goulot d'étranglement sérieux xxx

Ceci est similaire à la réponse de @ mTRW mais avec indexation à des vitesses natives. Mon Cython est un peu sommaire, il peut donc y avoir d'autres améliorations à faire.

Un test rapide d'un étui extrêmement favorable avec ipython avec quelques méthodes différentes xxx

Cependant, j'utiliserais quelque chose comme ça si j'avais des preuves (avec un profileur) que c'était un goulot d'étranglement. Beaucoup de choses peuvent sembler inefficaces mais ne valent jamais votre temps pour réparer.


1 commentaires

+1 pour tester. Intéressant que même avec si peu d'itérations, la boucle Python est ~ 10 fois plus lentement que le Cyron. Si l'élément non zéro était plus tard dans le grand tableau, l'avantage Cyron serait encore plus grand.



4
votes
i = np.argmax(A!=0)
if i==0 and np.all(A==0): i=len(A)
This should be the most performant solution without extensions. Also easily vectorized to act along multiple axes.

3 commentaires

Étrangement, cela semble beaucoup plus lent dans mes timings. Environ 30ms. Qu'est ce que tu obtiens?


Aucune idée; par rapport à quoi? Je m'attendrais à ce que les performances soient similaires à non nulle, sauf que nous évitons la construction de la matrice de sortie de NONZERO.


Une comparaison intéressante serait avec le code @ MR-E tests.



-2
votes

Si vous ne vous souciez pas de la vitesse, j'ai un petit tour pour faire le travail: xxx


0 commentaires