结构化数组使用需谨慎:dtype定义要预留字符串长度和浮点精度,填充须分字段赋值或用字典列表转换,布尔索引需整体置于外层,排序必须指定order参数。

用 np.dtype 定义复合字段时,类型码写错会静默失败
比如想存姓名(字符串)、年龄(整数)、身高(浮点),写成 dtype=[('name', 'U10'), ('age', 'i4'), ('height', 'f4')] 看似合理,但若实际数据里身高有小数点后三位以上,f4(32位浮点)就可能丢精度——而 NumPy 不报错,只默默截断。更隐蔽的是字符串长度:写 'U5' 却塞进 "Alexander",超出部分直接被砍掉,也不会警告。
实操建议:
- 字符串字段优先用
'U20'或更大,别卡着预估长度写 - 金融/科学计算中浮点字段统一用
'f8',除非明确压内存且接受误差 - 整数字段按范围选:
'i2'(-32768~32767)够用就别用'i8',省一半空间 - 定义完立刻用
np.dtype(...).itemsize算单条记录字节数,心里有底
填充结构化数组不能直接传嵌套列表,得按字段逐个赋值
常见错误是把三列数据打包成 [[name0, age0, h0], [name1, age1, h1]] 丢给 np.array(..., dtype=my_dtype),结果所有字段全变成字符串或全转成 object 类型——结构崩了。
正确做法是分开喂:
- 先创建空数组:
data = np.empty(4, dtype=my_dtype) - 再分字段填:
data['name'] = ['Alice', 'Bob', 'Cathy', 'Doug'],data['age'] = [25, 45, 37, 19] - 如果原始数据是字典列表,用
np.array(list_of_dicts, dtype=my_dtype)可以直接转换,但要求每个字典 key 必须完全匹配字段名
注意:字段赋值顺序无关,但字段名大小写、下划线必须和 dtype 定义严格一致。
让 macOS 自动化像说话一样简单 —— 用代码控制你的 Mac,无需学习 AppleScript 系统要求 macOS 14+ (Sonoma) Python 3.9+ 需要开启:辅助功能 + 屏幕录制权限
用布尔索引过滤结构化数组时,条件得写在方括号里而不是字段后
想筛出年龄大于 30 的人,别写 data['age'] > 30 然后试图用这个结果当索引——它返回一维布尔数组,形状和 data 不匹配,直接报 IndexError: boolean index did not match indexed array。
正确写法是把条件整个放进最外层索引位置:
-
data[data['age'] > 30]✅ -
data[(data['age'] > 30) & (data['height'] > 170)]✅(注意用&不是and) - 避免链式操作:
data[data['age'] > 30]['name']会触发 copy,大数组时慢且占内存;应写成data[data['age'] > 30]['name']一次取完
结构化数组排序比普通数组多一个 order 参数
对普通数组用 arr.sort() 就行,但结构化数组排序必须指明按哪个字段排,否则报 TypeError: sort() missing 1 required positional argument: 'axis'(即使你没动 axis)。
- 升序:
data.sort(order='age') - 多字段排序:
data.sort(order=['age', 'height']),先按 age,相同再按 height - 降序要额外加
-:data.sort(order='-age')(仅支持数值字段) - 字符串字段不支持负号,需用
data[::-1]配合布尔索引绕开
排序是原地操作,不返回新数组;如果需要保留原序,记得先 data.copy()。
结构化数组的字段访问看似简单,但 dtype 定义、填充方式、索引逻辑、排序参数这四点一旦错位,轻则结果错乱,重则内存暴涨或静默截断——尤其当字段含字符串和浮点混合时,问题往往在批量处理后期才暴露。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!










