web-dev-qa-db-fra.com

Initialisation de numpy matrix sur autre chose que zéro ou un

J'ai le code suivant:

r = numpy.zeros(shape = (width, height, 9))

Il crée une matrice largeur x hauteur x 9 remplie de zéros. Au lieu de cela, j'aimerais savoir s'il existe une fonction ou un moyen de les initialiser à la place de NaN.

Y a-t-il? Sans avoir à recourir à faire manuellement des boucles et autres?

Merci

155
devoured elysium

Vous avez rarement besoin de boucles pour les opérations vectorielles dans numpy. Vous pouvez créer un tableau non initialisé et affecter toutes les entrées à la fois:

>>> a = numpy.empty((3,3,))
>>> a[:] = numpy.nan
>>> a
array([[ NaN,  NaN,  NaN],
       [ NaN,  NaN,  NaN],
       [ NaN,  NaN,  NaN]])

J'ai chronométré les alternatives a[:] = numpy.nan ici et a.fill(numpy.nan) tel que posté par Blaenk:

$ python -mtimeit "import numpy as np; a = np.empty((100,100));" "a.fill(np.nan)"
10000 loops, best of 3: 54.3 usec per loop
$ python -mtimeit "import numpy as np; a = np.empty((100,100));" "a[:] = np.nan" 
10000 loops, best of 3: 88.8 usec per loop

Les timings indiquent une préférence pour ndarray.fill(..) comme alternative plus rapide. OTOH, j'aime l'implémentation pratique de Numpy où vous pouvez attribuer des valeurs à des tranches entières à la fois, l'intention du code est très claire.

223
u0b34a0f6ae

Une autre option consiste à utiliser numpy.full , une option disponible dans NumPy 1.8+

_a = np.full([height, width, 9], np.nan)
_

C'est assez flexible et vous pouvez le remplir avec n'importe quel autre numéro que vous voulez.

127
pietro

J'ai comparé les alternatives suggérées pour la vitesse et trouvé que, pour les vecteurs/matrices assez grands pour être remplis, toutes les alternatives, à l'exception de val * ones et de array(n * [val]), sont toutes aussi rapides.

enter image description here


Code pour reproduire l'intrigue:

import numpy
import perfplot

val = 42.0


def fill(n):
    a = numpy.empty(n)
    a.fill(val)
    return a


def colon(n):
    a = numpy.empty(n)
    a[:] = val
    return a


def full(n):
    return numpy.full(n, val)


def ones_times(n):
    return val * numpy.ones(n)


def list(n):
    return numpy.array(n * [val])


perfplot.show(
    setup=lambda n: n,
    kernels=[fill, colon, full, ones_times, list],
    n_range=[2**k for k in range(20)],
    logx=True,
    logy=True,
    xlabel='len(a)'
    )
35
Nico Schlömer

Connaissez-vous numpy.nan?

Vous pouvez créer votre propre méthode telle que:

def nans(shape, dtype=float):
    a = numpy.empty(shape, dtype)
    a.fill(numpy.nan)
    return a

Ensuite

nans([3,4])

serait sortie

array([[ NaN,  NaN,  NaN,  NaN],
       [ NaN,  NaN,  NaN,  NaN],
       [ NaN,  NaN,  NaN,  NaN]])

J'ai trouvé ce code dans un fil de discussion .

25

Vous pouvez toujours utiliser la multiplication si vous ne rappelez pas immédiatement les méthodes .empty ou .full:

>>> np.nan * np.ones(shape=(3,2))
array([[ nan,  nan],
       [ nan,  nan],
       [ nan,  nan]])

Bien sûr, cela fonctionne avec toute autre valeur numérique:

>>> 42 * np.ones(shape=(3,2))
array([[ 42,  42],
       [ 42,  42],
       [ 42, 42]])

Mais le @ (@a0b34a0f6ae) réponse acceptée est 3 fois plus rapide (cycles du processeur, pas cycles du cerveau pour se souvenir de la syntaxe numpy;):

$ python -mtimeit "import numpy as np; X = np.empty((100,100));" "X[:] = np.nan;"
100000 loops, best of 3: 8.9 usec per loop
(predict)laneh@predict:~/src/predict/predict/webapp$ master
$ python -mtimeit "import numpy as np; X = np.ones((100,100));" "X *= np.nan;"
10000 loops, best of 3: 24.9 usec per loop
10
hobs

Comme dit, numpy.empty () est la voie à suivre. Cependant, pour les objets, fill () pourrait ne pas faire exactement ce que vous pensez qu'il fait:

In[36]: a = numpy.empty(5,dtype=object)
In[37]: a.fill([])
In[38]: a
Out[38]: array([[], [], [], [], []], dtype=object)
In[39]: a[0].append(4)
In[40]: a
Out[40]: array([[4], [4], [4], [4], [4]], dtype=object)

Un moyen peut être, par exemple:

In[41]: a = numpy.empty(5,dtype=object)
In[42]: a[:]= [ [] for x in range(5)]
In[43]: a[0].append(4)
In[44]: a
Out[44]: array([[4], [], [], [], []], dtype=object)
4
ntg

Une autre alternative est numpy.broadcast_to(val,n) qui renvoie en temps constant quelle que soit la taille et qui est également la plus efficace en termes de mémoire (il renvoie une vue de l'élément répété). La mise en garde est que la valeur renvoyée est en lecture seule.

Vous trouverez ci-dessous une comparaison des performances de toutes les autres méthodes proposées avec le même repère que réponse de Nico Schlömer .

enter image description here

4

Une autre possibilité non encore mentionnée ici est d’utiliser la vignette NumPy:

a = numpy.tile(numpy.nan, (3, 3))

Donne également

array([[ NaN,  NaN,  NaN],
       [ NaN,  NaN,  NaN],
       [ NaN,  NaN,  NaN]])

Je ne sais pas sur la comparaison de vitesse.

2
JHBonarius