Biorąc pod uwagę tablicę NumPy int32
, jak przekonwertować ją na float32
miejsce ? Więc zasadniczo chciałbym to zrobić
a = a.astype(numpy.float32)
bez kopiowania tablicy. To jest duże.
Powodem tego jest to, że mam dwa algorytmy do obliczania a
. Jeden z nich zwraca tablicę int32
, a drugi tablicę float32
(i jest to nieodłączne dla dwóch różnych algorytmów). Wszystkie dalsze obliczenia zakładają, że a
jest to tablica float32
.
Obecnie wykonuję konwersję w funkcji C o nazwie via ctypes
. Czy można to zrobić w Pythonie?
ctypes
jest tak samo „w Pythonie”, jak używanienumpy
. :)Odpowiedzi:
Możesz utworzyć widok z innym typem, a następnie skopiować lokalnie do widoku:
import numpy as np x = np.arange(10, dtype='int32') y = x.view('float32') y[:] = x print(y)
plony
array([ 0., 1., 2., 3., 4., 5., 6., 7., 8., 9.], dtype=float32)
Aby pokazać, że konwersja była na miejscu, pamiętaj, że kopiowanie z
x
do zostałoy
zmienionex
:wydruki
array([ 0, 1065353216, 1073741824, 1077936128, 1082130432, 1084227584, 1086324736, 1088421888, 1090519040, 1091567616])
źródło
np.arange(10, dtype=np.int32).view(np.float32)
na Numpy 1.8.2, dostajęarray([ 0.00000000e+00, 1.40129846e-45, ... [snip] ... 1.26116862e-44], dtype=float32)
.y[:] = x
.a = np.arange(10, dtype='float32'); b = a[::-1]; c = np.vstack((a,b)); d = c.view('float64')
Ten kod zajmuje 10 + 10 float32 i daje w wyniku 10 zamiast 20 float64x.astype(float)
konwersja. Nie polecałbym tego, chyba że twój skrypt graniczy z MemoryError.Aktualizacja: Ta funkcja unika kopiowania tylko wtedy, gdy jest to możliwe, dlatego nie jest to poprawna odpowiedź na to pytanie. Odpowiedź unutbu jest właściwa.
a = a.astype(numpy.float32, copy=False)
numpy astype ma flagę kopiowania. Dlaczego nie powinniśmy tego używać?
źródło
Możesz zmienić typ tablicy bez konwersji w ten sposób:
ale najpierw musisz zmienić wszystkie liczby całkowite na coś, co zostanie zinterpretowane jako odpowiadająca im liczba zmiennoprzecinkowa. Bardzo powolnym sposobem na zrobienie tego byłoby użycie
struct
modułu Pythona w następujący sposób:def toi(i): return struct.unpack('i',struct.pack('f',float(i)))[0]
... zastosowana do każdego elementu tablicy.
Ale być może szybszym sposobem byłoby wykorzystanie narzędzi ctypeslib firmy Numpy (których nie znam)
- edytować -
Ponieważ ctypeslib wydaje się nie działać, kontynuowałbym konwersję typową
numpy.astype
metodą, ale kontynuowałbym w blokach o rozmiarach mieszczących się w granicach pamięci:a[0:10000] = a[0:10000].astype('float32').view('int32')
... a następnie zmień typ po zakończeniu.
Oto funkcja, która wykonuje zadanie dla dowolnych zgodnych dtypów (działa tylko dla dtypów z elementami o tej samej wielkości) i obsługuje tablice o dowolnym kształcie z kontrolą użytkownika nad rozmiarem bloku:
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
źródło
a.view(numpy.float32)
. Najtrudniejszą częścią jest konwersja danych.numpy.ctypeslib
pomaga tylko przy ponownej interpretacji danych, a nie przy ich rzeczywistej konwersji.import numpy as np arr_float = np.arange(10, dtype=np.float32) arr_int = arr_float.view(np.float32)
użyj view () i parametru 'dtype', aby zmienić tablicę w miejscu.
źródło
int
, ta odpowiedź tylko zinterpretowałaby istniejące dane jako inny typ, o co nie pytałem.dtype
,order
orazsubok
wymagania, aby powrócić kopię tablicy? Ja tego nie rozwiązuję.Użyj tego:
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)
źródło
a = np.subtract(a, 0., dtype=np.float32)
źródło
numpy.subtract
zwraca kopię, prawda? Tylko nazwaa
ponownie wykorzystana dla kolejnej porcji danych ... Proszę wyjaśnić, jeśli się mylę.