web-dev-qa-db-fra.com

Comment supprimer tous les éléments zéro d'un tableau NumPy?

J'ai un rang 1 numpy.array dont je veux faire un boxplot. Cependant, je veux exclure toutes les valeurs égales à zéro dans le tableau. Actuellement, j'ai résolu cela en bouclant le tableau et en copiant la valeur dans un nouveau tableau s'il n'est pas égal à zéro. Cependant, comme le tableau se compose de 86 000 000 de valeurs et que je dois le faire plusieurs fois, cela demande beaucoup de patience.

Existe-t-il une façon plus intelligente de procéder?

24
ruben baetens

C'est un cas où vous souhaitez utiliser des tableaux masqués, il conserve la forme de votre tableau et il est automatiquement reconnu par toutes les fonctions numpy et matplotlib.

X = np.random.randn(1e3, 5)
X[np.abs(X)< .1]= 0 # some zeros
X = np.ma.masked_equal(X,0)
plt.boxplot(X) #masked values are not plotted

#other functionalities of masked arrays
X.compressed() # get normal array with masked values removed
X.mask # get a boolean array of the mask
X.mean() # it automatically discards masked values
21
Andrea Zonca

Pour un tableau NumPy a, vous pouvez utiliser

a[a != 0]

pour extraire les valeurs différentes de zéro.

53
Sven Marnach

Une simple ligne de code peut vous procurer un tableau qui exclut toutes les valeurs "0":

np.argwhere(*array*)

exemple:

import numpy as np
array = [0, 1, 0, 3, 4, 5, 0]
array2 = np.argwhere(array)
print array2

[1, 3, 4, 5]
6
David Guest

Je voudrais vous suggérer d'utiliser simplement NaN pour des cas comme celui-ci, où vous aimerez ignorer certaines valeurs, tout en gardant la statistique statistique aussi significative que possible. Alors

In []: X= randn(1e3, 5)
In []: X[abs(X)< .1]= NaN
In []: isnan(X).sum(0)
Out[: array([82, 84, 71, 81, 73])
In []: boxplot(X)

enter image description here

3
eat

Vous pouvez indexer avec un tableau booléen. Pour un tableau NumPy A:

res = A[A != 0]

Vous pouvez utiliser indexation de tableau booléen comme ci-dessus, conversion de type bool, np.nonzero , ou np.where . Voici une analyse comparative des performances:

# Python 3.7, NumPy 1.14.3

np.random.seed(0)

A = np.random.randint(0, 5, 10**8)

%timeit A[A != 0]          # 768 ms
%timeit A[A.astype(bool)]  # 781 ms
%timeit A[np.nonzero(A)]   # 1.49 s
%timeit A[np.where(A)]     # 1.58 s
2
jpp

J'ai décidé de comparer le temps d'exécution des différentes approches mentionnées ici. J'ai utilisé ma bibliothèque simple_benchmark pour cela.

L'indexation booléenne avec array[array != 0] semble être la solution la plus rapide (et la plus courte).

enter image description here

Pour les tableaux plus petits, l'approche MaskedArray est très lente par rapport aux autres approches, mais elle est aussi rapide que l'approche d'indexation booléenne. Cependant, pour les tableaux de taille moyenne, il n'y a pas beaucoup de différence entre eux.

Voici le code que j'ai utilisé:

from simple_benchmark import BenchmarkBuilder

import numpy as np

bench = BenchmarkBuilder()

@bench.add_function()
def boolean_indexing(arr):
    return arr[arr != 0]

@bench.add_function()
def integer_indexing_nonzero(arr):
    return arr[np.nonzero(arr)]

@bench.add_function()
def integer_indexing_where(arr):
    return arr[np.where(arr != 0)]

@bench.add_function()
def masked_array(arr):
    return np.ma.masked_equal(arr, 0)

@bench.add_arguments('array size')
def argument_provider():
    for exp in range(3, 25):
        size = 2**exp
        arr = np.random.random(size)
        arr[arr < 0.1] = 0  # add some zeros
        yield size, arr

r = bench.run()
r.plot()
0
MSeifert