Преобразование типа на месте массива NumPy
учитывая NumPy массив int32, как мне преобразовать его в float32на месте? Так что в принципе, я хотел бы сделать
a = a.astype(numpy.float32)
без копирования массива. Она большая.
причина этого в том, что у меня есть два алгоритма для вычисления a. Один из них возвращает массив int32, другой возвращает массив float32 (и это присуще двум различным алгоритмам). Все дальнейшие вычисления предполагают, что a это массив float32.
в настоящее время я делаю преобразование в функцию C, называемую via ctypes. Есть ли способ сделать это в Python?
5 ответов:
вы можете создать представление с другим типом dtype, а затем скопировать на место в представление:
import numpy as np x = np.arange(10, dtype='int32') y = x.view('float32') y[:] = x print(y)доходность
array([ 0., 1., 2., 3., 4., 5., 6., 7., 8., 9.], dtype=float32)чтобы показать, что преобразование было на месте, обратите внимание, что копирование С
xдоyизменилx:print(x)печать
array([ 0, 1065353216, 1073741824, 1077936128, 1082130432, 1084227584, 1086324736, 1088421888, 1090519040, 1091567616])
Update: эта функция только избегает копирования, если это возможно, поэтому это не правильный ответ на этот вопрос. unutbu это - это правильно.
a = a.astype(numpy.float32, copy=False)numpy astype имеет флаг копирования. Почему бы нам не использовать его ?
вы можете изменить тип массива без преобразования такой:
a.dtype = numpy.float32но сначала вы должны изменить все целые числа на что-то, что будет интерпретироваться как соответствующий float. Очень медленный способ сделать это-использовать python
structмодуль такой:def toi(i): return struct.unpack('i',struct.pack('f',float(i)))[0]...применяется к каждому члену массива.
но, возможно, более быстрым способом было бы использовать инструменты ctypeslib numpy (которые мне незнакомы с)
- edit -
поскольку ctypeslib, похоже, не работает, я бы продолжил преобразование с типичным
numpy.astypeметод, но действуйте в размерах блоков, которые находятся в пределах вашей памяти:a[0:10000] = a[0:10000].astype('float32').view('int32')...затем измените dtype, когда закончите.
вот функция, которая выполняет задачу для любых совместимых dtypes (работает только для dtypes с одинаковыми размерами элементов) и обрабатывает произвольно сформированные массивы с пользовательским управлением над размером блока:
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
используйте этот:
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)
Comments