You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何简单移除numpy.dtype.descr中的padding填充字段

Numpy 1.16+结构化数组多字段访问padding问题及解决方案

从numpy 1.16版本起,访问结构化数组的多个字段时,返回数组的dtype会保留与原数组相同的项大小,产生额外padding填充:

与1.15版本相比,Numpy 1.16起的新特性会在未索引字段位置产生额外的padding字节,依赖紧凑布局数据的代码需要更新。

该特性会引发问题,例如后续给数组新增字段时会出错,示例代码如下:

import numpy as np
import numpy.lib.recfunctions


a = np.array(
    [
        (10.0, 13.5, 1248, -2),
        (20.0, 0.0, 0, 0),
        (30.0, 0.0, 0, 0),
        (40.0, 0.0, 0, 0),
        (50.0, 0.0, 0, 999)
    ], dtype=[('x', '<f8'), ('y', '<f8'), ('i', '<i8'), ('j', '<i8')]
)
print(a.shape, a.dtype, a.dtype.names, a.dtype.descr)
# 到这里运行正常

b = a[['x', 'i']]  # 后续处理仅需部分字段
print(b.shape, b.dtype, b.dtype.names, b.dtype.descr)
# 仅能在descr中看到额外的padding填充

# b = np.lib.recfunctions.repack_fields(b)
# 已知解决方案

# 新增字段时就会出现问题
c = np.empty(b.shape, dtype=b.dtype.descr + [('c', 'i4')])
c[list(b.dtype.names)] = b
c['c'] = 1

print(c.dtype.names)
print(c['f1'])
# void填充字段会被填充原始数据,且被分配可访问的正式名称

现有解决方案可使用numpy.lib.recfunctions.repack_fields移除padding,但部分场景下无法引入recfunctions模块,需手动处理b.dtype.descr中的空字段,例如[('x', '<f8'), ('', '|V8'), ('i', '<i8'), ('', '|V8')]这类空名称的void类型填充项。直接使用remove方法处理不够灵活,连续多个未选字段会合并为更大的void类型(如V16),会导致代码冗余繁琐。

精简无依赖解决方案

仅需一行代码过滤descr中的空名称项即可,无需关注填充字段的长度和数量:

# 过滤所有空名称的padding填充项,得到仅含有效字段的紧凑dtype描述
clean_dtype_descr = [field for field in b.dtype.descr if field[0] != '']

# 后续新增字段就不会产生多余的f1、f2这类自动命名的void字段
c = np.empty(b.shape, dtype=clean_dtype_descr + [('c', 'i4')])
c[list(b.dtype.names)] = b
c['c'] = 1

原理说明

numpy自动生成的padding填充字段在dtype.descr中统一使用空字符串作为字段名,无论连续未选中字段合并成多大的void类型,只要过滤掉所有名称为空的字段,就能得到完全紧凑的有效字段描述,不会影响原有数据的读取和写入。

内容的提问来源于stack exchange,提问作者mapf

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.30 06:06:05