webentwicklung-frage-antwort-db.com.de

In-Place-Typkonvertierung eines NumPy-Arrays

Bei einem NumPy-Array von int32, wie konvertiere ich es in float32vorhanden? Also im Grunde würde ich gerne tun

a = a.astype(numpy.float32)

ohne das Array zu kopieren. Es ist groß.

Der Grund dafür ist, dass ich zwei Algorithmen für die Berechnung von a habe. Einer von ihnen gibt ein Array von int32, der andere liefert ein Array von float32 (und das ist den zwei verschiedenen Algorithmen inhärent). Alle weiteren Berechnungen setzen voraus, dass a ein Array von float32.

Momentan mache ich die Konvertierung in eine C-Funktion, die über ctypes aufgerufen wird. Gibt es eine Möglichkeit, dies in Python zu tun?

121
Sven Marnach

Sie können eine Ansicht mit einem anderen D-Typ erstellen und dann direkt in die Ansicht kopieren:

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

print(y)

ausbeuten

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

Beachten Sie, dass beim Kopieren von vonx nach y geändert x:

print(x)

druckt

array([         0, 1065353216, 1073741824, 1077936128, 1082130432,
       1084227584, 1086324736, 1088421888, 1090519040, 1091567616])
102
unutbu

Update: Diese Funktion vermeidet nur das Kopieren, wenn dies möglich ist. Daher ist dies nicht die richtige Antwort auf diese Frage. die Antwort von unutb ist die richtige.


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

der Typ numpy hat ein Kopierflag. Warum sollten wir es nicht benutzen?

155
Vikas

Sie können den Array-Typ ändern, ohne wie folgt zu konvertieren:

a.dtype = numpy.float32

aber zuerst müssen Sie alle ganzen Zahlen in etwas ändern, das als das entsprechende float interpretiert wird. Eine sehr langsame Möglichkeit wäre, das struct -Modul von Python wie folgt zu verwenden:

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

... auf jedes Mitglied Ihres Arrays angewendet.

Aber vielleicht wäre eine schnellere Möglichkeit, die ctypeslib-Tools von numpy zu verwenden (mit denen ich nicht vertraut bin).

- edit -

Da ctypeslib nicht zu funktionieren scheint, würde ich die Konvertierung mit der typischen numpy.astype - Methode fortsetzen, aber mit Blockgrößen, die innerhalb Ihrer Speichergrenzen liegen:

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

... dann ändere den dtype wenn du fertig bist.

Hier ist eine Funktion, die die Aufgabe für alle kompatiblen Datentypen erledigt (funktioniert nur für Datentypen mit Elementen gleicher Größe) und beliebig geformte Arrays verarbeitet, wobei der Benutzer die Blockgröße steuern kann:

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
Paul
import numpy as np
arr_float = np.arange(10, dtype=np.float32)
arr_int = arr_float.view(np.float32)

verwenden Sie view () und den Parameter 'dtype', um das Array zu ändern.

0
蒋志强