如何基于已有数组创建含float32与uint32混合类型的NumPy数组?
问题描述
需求:创建包含float32与uint32混合数据类型的NumPy数组,要求axis 2的最后一个元素必须为uint32(满足硬件API要求)。
当前实现代码:
import numpy as np a = np.full((1, 10), 1).astype(np.float32) b = np.full((1, 10), 2).astype(np.float32) c = np.full((1, 10), 3).astype(np.float32) d = np.full((1, 10), 4).astype(np.uint32) arr = np.dstack([a, b, c, d]) # arr.shape = (1, 10, 4)
遇到的问题:用以下两种astype方法转换时,axis 2的元素都会出现重复:
- 直接指定复合类型字符串:
arr.astype("float32, float32, float32, uint1")
- 定义结构化数据类型后转换:
dt = np.dtype([('floats', np.float32, (3, )), ('ints', np.uint32, (1, ))]) arr = np.dstack((a, b, c, d)).astype(dt)
已知手动构造元组的方式可行,但实际数组长度达850k,不确定这种方案是否最优,求正确的实现方法。
解决方案
为啥之前的方法会出问题
- 第一种方法里的
uint1是无效类型(NumPy根本没有这个类型,应该写uint32),而且直接用逗号分隔的类型字符串转换时,NumPy会错误地把每个元素按对应类型重复匹配,导致轴元素重复。 - 第二种方法的结构化类型定义是把数组的每个元素映射成
(3个float32, 1个uint32)的结构,但原数组是(1,10,4)的三维数组,维度不匹配,转换时会错误填充重复数据。
最优实现方案
别先合并成float32数组再转换,直接用结构化数组构造,既能避免不必要的类型转换,还能节省内存,特别适合大数组场景:
import numpy as np # 构造基础数组,直接指定dtype,省去astype转换步骤 a = np.full((1, 10), 1, dtype=np.float32) b = np.full((1, 10), 2, dtype=np.float32) c = np.full((1, 10), 3, dtype=np.float32) d = np.full((1, 10), 4, dtype=np.uint32) # 定义结构化数据类型:每个位置对应3个float32和1个uint32 dt = np.dtype([ ('f1', np.float32), ('f2', np.float32), ('f3', np.float32), ('u1', np.uint32) ]) # 直接创建空的结构化数组,再填充各字段数据 result = np.empty(a.shape, dtype=dt) result['f1'] = a result['f2'] = b result['f3'] = c result['u1'] = d # 如果需要保持(1,10,4)的三维形状,用view做零拷贝转换(内存布局匹配时可用) result_3d = result.view(np.dtype([('f', np.float32, 3), ('u', np.uint32)])).reshape(result.shape + (4,))
大数组场景的优势
- 直接构造结构化数组不需要中间的float32数组(比如
dstack生成的那个),内存占用更高效,850k长度的数组能省不少内存转换的开销。 view转换是零拷贝操作,不会复制数据,性能比astype高得多。
内容的提问来源于stack exchange,提问作者Yousef Alnaser
相关产品推荐
相关产品推荐

