NumPy 数组的就地类型转换

给定一个 int32的 NumPy 数组,如何将其转换为 float32就位?所以基本上,我想做的是

a = a.astype(numpy.float32)

不需要复制数组,它很大。

这样做的原因是,我有两个算法来计算 a。其中一个返回一个 int32数组,另一个返回一个 float32数组(这是两种不同算法所固有的)。所有进一步的计算都假设 afloat32的数组。

目前,我在一个通过 ctypes调用的 C 函数中进行转换。有没有在 Python 中实现这一点的方法?

138598 次浏览

您可以更改数组类型,而不必像下面这样进行转换:

a.dtype = numpy.float32

但是首先你必须把所有的整数都改成一些可以被解释为对应的浮点数的东西。这样做的一个非常慢的方法是像下面这样使用 python 的 struct模块:

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

应用于数组的每个成员。

但也许更快的方法是利用 numpy 的 ctypeeslib 工具(我不熟悉这个工具)

- 编辑-

由于 ctypeeslib 似乎不起作用,那么我将继续使用典型的 numpy.astype方法进行转换,但是使用内存限制内的块大小进行转换:

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

然后改变 dtype。

下面是一个函数,它可以完成任何兼容 dtype 的任务(只适用于大小相同的 dtype) ,并且可以处理任意形状的数组,用户可以控制块大小:

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

您可以使用不同的 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])

更新: 这个函数只有在可以的情况下才会避免复制,因此这不是这个问题的正确答案。Unutbu 的回答是正确的。


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

Numpy astype 有一个拷贝标志。为什么我们不应该使用它?

用这个:

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)

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

import numpy as np
arr_float = np.arange(10, dtype=np.float32)
arr_int = arr_float.view(np.float32)

使用 view ()和参数‘ dtype’更改数组的位置。

读取数据所花费的时间

t1=time.time() ; V=np.load ('udata.npy');t2=time.time()-t1 ; print( t2 )

95.7923333644867

V.dtype

Dtype (’> f8’)

V.shape

(3072,1024,4096)

创建新数组

t1=time.time() ; V64=np.array( V, dtype=np.double); t2=time.time()-t1 ; print( t2 )

1291.669689655304

简单的就地 numpy 转换

t1=time.time() ; V64=np.array( V, dtype=np.double); t2=time.time()-t1 ; print( t2 )

205.64322113990784

使用 astype

t1=time.time() ; V = V.astype(np.double) ; t2=time.time()-t1 ; print( t2 )

400.6731758117676

使用视图

t1=time.time() ; x=V.view(np.double);V[:,:,:]=x ;t2=time.time()-t1 ; print( t2 )

556.5982494354248

请注意,每次我清除变量。因此,简单地让 python 处理转换是最有效的。