339 votes

Initialisation des tableaux NumPy (remplir avec des valeurs identiques)

J'ai besoin de créer un tableau NumPy de longueur n dont chaque élément est v .

Y a-t-il quelque chose de mieux que :

a = empty(n)
for i in range(n):
    a[i] = v

Je sais. zeros y ones fonctionnerait pour v = 0, 1. Je pourrais utiliser v * ones(n) mais il ne fonctionnera pas lorsque v es None et aussi serait beaucoup plus lent.

1 votes

Sur mon ordinateur, pour le cas 0, en utilisant a = np.zeros(n) dans la boucle est plus rapide que a.fill(0) . Cela va à l'encontre de ce à quoi je m'attendais puisque je pensais que a=np.zeros(n) aurait besoin d'allouer et d'initialiser une nouvelle mémoire. Si quelqu'un peut expliquer cela, je l'apprécierais.

0 votes

Vous ne pouvez pas mettre None dans un tableau numpy, car les cellules sont créées avec un type de données spécifique alors que None a son propre type et est en fait un pointeur.

0 votes

@Camion Oui, je le sais maintenant :) Bien sûr. v * ones(n) est toujours horrible, car elle utilise la multiplication coûteuse. Remplacer * con + cependant, et v + zeros(n) s'avère être étonnamment bon dans certains cas ( stackoverflow.com/questions/5891410/ ).

473voto

EOL Points 24342

Introduction de NumPy 1.8 np.full() qui est une méthode plus directe que empty() suivi par fill() pour créer un tableau rempli d'une certaine valeur :

>>> np.full((3, 5), 7)
array([[ 7.,  7.,  7.,  7.,  7.],
       [ 7.,  7.,  7.,  7.,  7.],
       [ 7.,  7.,  7.,  7.,  7.]])

>>> np.full((3, 5), 7, dtype=int)
array([[7, 7, 7, 7, 7],
       [7, 7, 7, 7, 7],
       [7, 7, 7, 7, 7]])

C'est sans doute le site de créer un tableau rempli de certaines valeurs, car il décrit explicitement ce qui est réalisé (et il peut en principe être très efficace puisqu'il effectue une tâche très spécifique).

1 votes

Cette méthode full() fonctionne bien pour moi mais je ne trouve pas de documentation à son sujet. Quelqu'un peut-il m'indiquer le bon endroit ?

1 votes

Vous pouvez au moins faire help(numpy.full) dans un shell Python. Je suis également surpris que cela ne figure pas dans la documentation Web.

0 votes

Sur mon système (Python 2.7, Numpy 1.8), np.full() est en fait légèrement plus lent que np.empty() suivi de np.fill().

107voto

Yariv Points 1635

Mis à jour pour Numpy 1.7.0 : (Hat-tip à @Rolf Bartstra.)

a=np.empty(n); a.fill(5) est le plus rapide.

Par ordre décroissant de vitesse :

%timeit a=np.empty(10000); a.fill(5)
100000 loops, best of 3: 5.85 us per loop

%timeit a=np.empty(10000); a[:]=5 
100000 loops, best of 3: 7.15 us per loop

%timeit a=np.ones(10000)*5
10000 loops, best of 3: 22.9 us per loop

%timeit a=np.repeat(5,(10000))
10000 loops, best of 3: 81.7 us per loop

%timeit a=np.tile(5,[10000])
10000 loops, best of 3: 82.9 us per loop

17 votes

Ajout d'un timing pour les plus récents et directs np.full() serait utile. Sur ma machine, avec NumPy 1.8.1, il est environ 15% plus lent que la méthode moins directe fill() (ce qui est inattendu, car full() a le potentiel d'aller légèrement plus vite).

0 votes

@DavidSanders : Je ne suis pas sûr de vous suivre : fill() est la solution la plus rapide. La solution de la multiplication est beaucoup plus lente.

2 votes

Note : si la vitesse est vraiment un souci, utiliser une taille de 10000 au lieu de 1e4 fait une différence notable, pour une raison quelconque ( full() est presque 50% plus lent, avec 1e4 ).

74voto

Paul Points 13042

Je crois fill est le moyen le plus rapide de le faire.

a = np.empty(10)
a.fill(7)

Vous devriez également toujours éviter d'itérer comme vous le faites dans votre exemple. Un simple a[:] = v accomplira ce que votre itération fait en utilisant numpy diffusion .

1 votes

Merci. En regardant fill J'ai vu que repeat convient encore mieux à mes besoins.

0 votes

Pourriez-vous mettre à jour votre réponse pour dire que votre recommandation de a[:]=v est en fait globalement plus rapide que le fill ?

0 votes

@max Est-ce plus rapide ? La diffusion est un moyen plus général de remplir un tableau et je suppose qu'elle est plus lente ou égale au cas d'utilisation très étroit de fill .

17voto

Rolf Bartstra Points 300

Apparemment, non seulement les vitesses absolues mais aussi la vitesse commander (comme signalé par l'utilisateur1579844) dépendent de la machine ; voici ce que j'ai trouvé :

a=np.empty(1e4); a.fill(5) est le plus rapide ;

Par ordre décroissant de vitesse :

timeit a=np.empty(1e4); a.fill(5) 
# 100000 loops, best of 3: 10.2 us per loop
timeit a=np.empty(1e4); a[:]=5
# 100000 loops, best of 3: 16.9 us per loop
timeit a=np.ones(1e4)*5
# 100000 loops, best of 3: 32.2 us per loop
timeit a=np.tile(5,[1e4])
# 10000 loops, best of 3: 90.9 us per loop
timeit a=np.repeat(5,(1e4))
# 10000 loops, best of 3: 98.3 us per loop
timeit a=np.array([5]*int(1e4))
# 1000 loops, best of 3: 1.69 ms per loop (slowest BY FAR!)

Essayez donc de vous renseigner, et utilisez ce qui est le plus rapide sur votre plateforme.

8voto

Rolf Bartstra Points 300

Vous pouvez utiliser numpy.tile , par exemple :

v = 7
rows = 3
cols = 5
a = numpy.tile(v, (rows,cols))
a
Out[1]: 
array([[7, 7, 7, 7, 7],
       [7, 7, 7, 7, 7],
       [7, 7, 7, 7, 7]])

Bien que tile est destiné à "carreler" un tableau (au lieu d'un scalaire, comme dans ce cas), il fera le travail, créant des tableaux pré-remplis de n'importe quelle taille et dimension.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X