Conversion de type en place d'un tableau NumPy

avec un tableau minuscule de int32 , Comment puis-je le convertir en float32 en place ? Donc en gros, je voudrais faire

a = a.astype(numpy.float32)

sans copier le tableau. Il est grand.

La raison pour cela est que j'ai deux algorithmes pour le calcul des a . L'un d'eux retourne un tableau de int32 , l'autre renvoie un tableau de float32 (et c'est inhérent à toutes les deux différents algorithmes). Tous les autres calculs supposent que a est un tableau de float32 .

actuellement je fais la conversion dans une fonction C appelée via ctypes . Y a-t-il un moyen de faire ça en Python?

105
demandé sur Sven Marnach 2010-12-08 19:01:46

5 réponses

vous pouvez faire une vue avec un dtype différent, puis Copier en place dans la vue:

import numpy as np
x = np.arange(10, dtype='int32')
y = x.view('float32')
y[:] = x

print(y)

rendements

array([ 0.,  1.,  2.,  3.,  4.,  5.,  6.,  7.,  8.,  9.], dtype=float32)

pour montrer que la conversion était en place, notez que la copie de x à y modifié x :

print(x)

imprime

array([         0, 1065353216, 1073741824, 1077936128, 1082130432,
       1084227584, 1086324736, 1088421888, 1090519040, 1091567616])
89
répondu unutbu 2017-10-28 17:19:07

mise à jour: cette fonction n'évite la copie que si elle le peut, ce n'est donc pas la bonne réponse à cette question. la réponse d'unutbu est la bonne.


a = a.astype(numpy.float32, copy=False)

numpy astype a un drapeau de copie. Pourquoi ne devrions-nous pas l'utiliser ?

140
répondu Vikas 2018-06-25 08:30:57

vous pouvez changer le type de tableau sans Convertir comme ceci:

a.dtype = numpy.float32

mais d'abord vous devez changer tous les entiers à quelque chose qui sera interprété comme le flotteur correspondant. Une façon très lente de faire cela serait d'utiliser le module struct de python comme ceci:

def toi(i):
    return struct.unpack('i',struct.pack('f',float(i)))[0]

...appliquée à chaque membre de votre groupe.

mais peut-être un moyen plus rapide serait d'utiliser les outils ctypeslib de numpy (qui Je ne suis pas familier avec)

- edit -

puisque ctypeslib ne semble pas fonctionner, alors je procéderais à la conversion avec la méthode typique numpy.astype , mais procéder dans les tailles de blocs qui sont dans vos limites de mémoire:

a[0:10000] = a[0:10000].astype('float32').view('int32')

...puis changez le dtype une fois fait.

Voici une fonction qui accomplit la tâche pour tous les types dtypes compatibles (ne fonctionne que pour les types dtypes avec articles de même taille) et manipule des matrices en forme arbitraire avec le contrôle de l'utilisateur sur la taille du bloc:

import numpy

def astype_inplace(a, dtype, blocksize=10000):
    oldtype = a.dtype
    newtype = numpy.dtype(dtype)
    assert oldtype.itemsize is newtype.itemsize
    for idx in xrange(0, a.size, blocksize):
        a.flat[idx:idx + blocksize] = \
            a.flat[idx:idx + blocksize].astype(newtype).view(oldtype)
    a.dtype = newtype

a = numpy.random.randint(100,size=100).reshape((10,10))
print a
astype_inplace(a, 'float32')
print a
14
répondu Paul 2010-12-08 23:02:27

a = np.subtract(a, 0., dtype=np.float32)

-3
répondu MIO 2017-11-17 20:21:37

utilisez ceci:

In [105]: a
Out[105]: 
array([[15, 30, 88, 31, 33],
       [53, 38, 54, 47, 56],
       [67,  2, 74, 10, 16],
       [86, 33, 15, 51, 32],
       [32, 47, 76, 15, 81]], dtype=int32)

In [106]: float32(a)
Out[106]: 
array([[ 15.,  30.,  88.,  31.,  33.],
       [ 53.,  38.,  54.,  47.,  56.],
       [ 67.,   2.,  74.,  10.,  16.],
       [ 86.,  33.,  15.,  51.,  32.],
       [ 32.,  47.,  76.,  15.,  81.]], dtype=float32)
-4
répondu Ankit Barik 2015-02-19 15:53:07