当前位置: 首页 > news >正文

NumPy 2.x 完全指南【二十五】记录数组

文章目录

  • 1. 概述
  • 2. 创建记录数组
    • 2.1 numpy.rec.array
    • 2.2 numpy.rec.fromXX
  • 3. 访问数据
  • 4. Recarray 辅助函数
    • 4.1 添加新字段
    • 4.2 删除字段

1. 概述

在上一篇中,我们学习了结构化数组,需要通过索引访问字段对应的数据:

# 创建结构化数组
struct_arr = np.array([('Alice', 25, 1.65),('Bob', 30, 1.75)],dtype=[('name', 'U10'),('age', 'i4'),('height', 'f4')]
)
print("索引访问 name:", struct_arr['name'])  # 输出:['Alice' 'Bob']

基于便利性考虑,NumPy 提供了 numpy.recarray 记录数组,它也是 ndarray 的子类,是一种特殊的结构化数组,允许通过属性访问结构化数组的字段,而不仅仅是通过索引。

提示: 和结构化数组一样,pandasDataFrame 也有类似功能,而且更强大,这里主要是入门介绍有个了解即可。

2. 创建记录数组

numpy.rec 模块提供了从各种对象创建记录数组的函数。

2.1 numpy.rec.array

numpy.rec.array():从多种对象创建记录数组。

函数定义:

def array(obj, dtype=None, shape=None, offset=0, strides=None, formats=None,names=None, titles=None, aligned=False, byteorder=None, copy=True)

参数说明:

  • obj:输入对象(必选)
  • dtype:指定字段类型(如 [('name','U10'), ('age','i4')])。
  • shape:数组形状。
  • offset:数据读取起始位置(字节单位)。
  • strides:内存步幅(控制数据在内存中的布局)。
  • formats:字段类型简写(替代 dtype)。
  • names:字段名称列表(如 ['name','age'])。
  • titles:字段别名(用于多名称映射)。
  • aligned:是否内存对齐(提升 CPU 访问效率)。
  • byteorder:字节序('<‘小端,’>'大端)。
  • copy:是否创建数据副本。

示例 1 ,使用 namesformats 指定字段名称和类型:

scores = [('张三', 2023001, 85.5, 90.0),('李四', 2023002, 78.0, 92.5),('王五', 2023003, 95.0, 88.0)
]
rec = np.rec.array(scores,formats=['U10', 'i4', 'f4', 'f4'],  # 字段类型names=('name', 'student_id', 'math_score', 'physics_score')  # 字段命名
)
print(rec)
# [('张三', 2023001, 85.5, 90. )
# ('李四', 2023002, 78. , 92.5)
#  ('王五', 2023003, 95. , 88. )]

示例 2 ,将结构化数组转换为记录数组:

arr = np.array([(1, 2., 'Hello'), (2, 3., "World")],dtype=[('foo', 'i4'), ('bar', 'f4'), ('baz', 'S10')])
record_arr = np.rec.array(arr)
print(record_arr)
# [(1, 2., b'Hello') (2, 3., b'World')]

2.2 numpy.rec.fromXX

numpy.rec 模块还提供了许多 fromXX 函数用于创建记录数组:

  • fromarrays():将多个同长度的数组按列组合为记录数组,每列对应一个字段。
  • fromrecords():将元组或列表的序列(每行一个记录)转换为记录数组。
  • fromstring():解析二进制字符串生成只读记录数组。
  • fromfile():直接从二进制文件读取数据生成记录数组。

示例 1 ,从数组列表构建记录数组:

# 创建三个独立数组
names = np.array(['Alice', 'Bob'])
ages = np.array([25, 30])
heights = np.array([1.65, 1.75])# 合并为记录数组
rec_arr = np.rec.fromarrays([names, ages, heights],names='name,age,height')
print(rec_arr.name)  # 输出:['Alice' 'Bob']

示例 2 ,从记录列表构建记录数组:

data = [('Alice', 25, 1.65), ('Bob', 30, 1.75)]
rec_arr = np.rec.fromrecords(data,names=['name','age','height'])
print(rec_arr.age)  # 输出:[25 30]

示例 3 ,从二进制字符串创建记录数组:

binary_data = b'\x41\x00\x00\x00\x42\x00\x00\x00'  # 示例二进制数据
dtype = [('id', 'i4')]  # 32位整数
rec_arr = np.rec.fromstring(binary_data, dtype=dtype)
print(rec_arr.id)  # 输出:[65 66] (十六进制 0x41=65, 0x42=66)

3. 访问数据

当通过索引或属性访问记录数组的字段时:

  • 如果该字段本身具有结构化类型(即嵌套结构),那么访问该字段会返回一个记录数组。
  • 如果该字段是非结构化的(简单类型),则返回普通的 ndarray

示例 1 ,简单类型:

# 创建记录数组
rec_arr = np.rec.array([('Alice', 25, 1.65), ('Bob', 30, 1.75)],dtype=[('name', 'U10'), ('age', 'i4'), ('height', 'f4')]
)# 索引访问
print("索引访问 name:", rec_arr['name'])  # 输出: ['Alice' 'Bob'] (类型: ndarray)# 属性访问
print("属性访问 age:", rec_arr.age)       # 输出: [25 30] (类型: ndarray)

示例 2 ,当字段为嵌套结构时:

# 创建含嵌套字段的记录数组
nested_arr = np.rec.array([('Alice', (25, 55.5)), ('Bob', (30, 70.2))],dtype=[('name', 'U10'), ('info', [('age', 'i4'), ('weight', 'f4')])]
)# 访问嵌套字段
info_field = nested_arr.info
print(type(info_field))          # 输出: <class 'numpy.rec.recarray'>
print("嵌套字段 age:", info_field.age)  # 输出: [25 30] (通过属性递归访问)

4. Recarray 辅助函数

NumPy 提供了结构化数组(包括记录数组)的一个操作工具集合,这些函数大多数最初由 John Huntermatplotlib 实现,后来被重写并扩展以提高便利性。

numpy.lib.recfunctions 公开接口列表:

__all__ = ['append_fields',  # 添加字段'apply_along_fields',  # 沿字段应用函数'assign_fields_by_name',  # 按名称分配字段'drop_fields',  # 删除字段'find_duplicates',  # 查找重复记录'flatten_descr',  # 展平字段描述'get_fieldstructure',  # 获取字段结构'get_names',  # 获取字段名称(嵌套结构)'get_names_flat',  # 获取平铺字段名称'join_by',  # 按键连接数组'merge_arrays',  # 合并数组'rec_append_fields',  # 记录数组版添加字段'rec_drop_fields',  # 记录数组版删除字段'rec_join',  # 记录数组版连接'recursive_fill_fields',  # 递归填充字段'rename_fields',  # 重命名字段'repack_fields',  # 重新打包字段'require_fields',  # 必需字段检查'stack_arrays',  # 堆叠数组'structured_to_unstructured',  # 结构化转非结构化'unstructured_to_structured',  # 非结构化转结构化]

4.1 添加新字段

numpy.lib.recfunctions.append_fields:向现有结构化数组(记录数组)动态添加新字段,返回一个新数组(原始数组不被修改)。

函数定义:

def append_fields(base, names, data, dtypes=None,fill_value=-1, usemask=True, asrecarray=False)

参数说明:

  • base: 输入数组。
  • names: 字符串或字符串序列,对应新字段的名称。
  • data: 数组或数组序列,存储要添加到基础数组的字段。
  • dtypes: 可选,数据类型或数据类型序列。
  • fill_value: 可选,填充值,用于填充较短数组中的缺失数据。
  • usemask: 可选,是否返回一个被掩码的数组。
  • asrecarray: 可选,是否返回记录数组。

示例 1 ,基本字段添加:

# 基础数组
base = np.array([(1, 2.3), (2, 5.7)],dtype=[('id', 'i4'), ('value', 'f4')])# 添加单字段:'score'
new_arr = rfn.append_fields(base, 'score', [80, 90])
print(new_arr)
# 输出: [(1, 2.3, 80) (2, 5.7, 90)]# 添加多字段:'status'和'comment'
multi_arr = rfn.append_fields(base,['status', 'comment'],[[1, 0], ['OK', 'Error']],  # 字段数据dtypes=['i1', 'U10']         # 指定数据类型
)
print(multi_arr)
# 输出: [(1, 2.3, 1, 'OK') (2, 5.7, 0, 'Error')]

示例 2 ,自动填充:

# 新数据行数 > 基础数组(2行 → 3行)
expanded = rfn.append_fields(base,'score',[80, 90, 95],                # 3行数据fill_value=0                 # 基础数组扩展行填充0
)
print(expanded)
# 输出: [(1, 2.3, 80) (2, 5.7, 90) (0, 0., 95)]

示例 3 ,返回类型控制:

# 返回掩码数组(支持缺失值)
masked_arr = rfn.append_fields(base,'score',[80, 90],usemask=True
)
print(type(masked_arr))  # <class 'numpy.ma.MaskedArray'># 返回记录数组(支持属性访问)
rec_arr = rfn.append_fields(base,'score',[80, 90],asrecarray=True
)
print(rec_arr.score)  # 输出: [80 90]

4.2 删除字段

numpy.lib.recfunctions.drop_fields:从结构化数组中移除指定字段,返回一个不包含被移除字段的新数组。

函数定义:

drop_fields(base, drop_names, usemask=True, asrecarray=False):

参数说明:

  • base: 输入数组。
  • drop_names: 要删除的字段名称(单个字段名或列表)。
  • usemask: 是否返回掩码数组(支持缺失值处理)。
  • asrecarray: 是否返回记录数组。

示例 1 ,基本字段删除:

# 原始结构化数组
arr = np.array([(1, 2.3, 'A'), (4, 5.6, 'B')],dtype=[('id','i4'), ('value','f4'), ('code','U1')])# 删除单个字段
new_arr = rfn.drop_fields(arr, 'value')
print(new_arr)
# 输出: [(1, 'A') (4, 'B')]# 批量删除多字段
new_arr = rfn.drop_fields(arr, ['id', 'code'])
print(new_arr)
# 输出: [(2.3,) (5.6,)]

相关文章:

  • 建站新手:我与SiteServerCMS的爱恨情仇(三)
  • 【c++八股文】Day2:虚函数表和虚函数表指针
  • RPC启动机制及注解实现
  • day 50
  • 0:0 error Parsing error: Cannot read properties of undefined (reading ‘map‘)
  • Rust 学习笔记:通过异步实现并发
  • C语言学习20250611
  • 亮数据抓取浏览器,亚马逊数据采集实战
  • Flask 报错修复实战:send_file() got an unexpected keyword argument ‘etag‘
  • vite原理
  • MFC 第1章:适配 WIndows 编程的软件界面调整
  • 创建和运行线程
  • 训练过程中的 Loss ?
  • 红队手法:从web漏洞到ssh横向移动 实战方案
  • 达梦数据库dsc集群+异步主备
  • Android11三网共存
  • el-table-v2修改表头、单元格、表格整体的宽度、高度样式
  • 用 IRify 深入探索 WebShell 中的 Source/Sink 挖掘
  • C# ConcurrentDictionary 中获取指定范围的元素
  • 解密Spring Boot:深入理解条件装配与条件注解
  • 传奇私服发布网网站建设/简单制作html静态网页
  • 做网站如何添加表单/网页设计模板图片
  • 西安网站建设ipv6/东莞营销网站建设直播
  • 成都网站开发公司排名/外链代发公司
  • 网站设计的重要性/网络视频营销
  • 郑州市建设劳务服务网站/2023免费推广入口