J'ai un tableau numpy si A code>. J'aimerais retourner le nombre de zéros avant un non-zéro dans A code> de manière efficace que dans une boucle. P>
a = np.array ([0,1,2]) code> alors np.nonzero (a) [0] [0] code> retourne 1. Toutefois si A = NP.Array ([0,0,0]) Code> 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. P>
6 Réponses :
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
Je suis surpris de savoir pourquoi personne n'a pas utilisé np.wheres code> mais np.where (a) [0] [0] Si NP.Shape (NP. ) [0]) [0]! = 0 autre np.shape (a) [0] code> fera le tour p>
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
Voici une version itérative Cyron, qui peut être votre meilleure mise s'il s'agit d'un goulot d'étranglement sérieux 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. P> Un test rapide d'un étui extrêmement favorable avec ipython avec quelques méthodes différentes p> 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. P> p>
+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.
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.
É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.
Si vous ne vous souciez pas de la vitesse, j'ai un petit tour pour faire le travail:
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.