NumPy的复合数据类型(Structured Array)是一种强大的数据结构,允许在单个数组中存储异构数据(不同数据类型),类似于数据库表格或结构化记录。以下是其核心特性和使用方法的系统介绍:


🧱 一、核心概念

  1. 定义与特点

    • 异构数据存储:复合数据类型允许每个数组元素包含多个字段(字段名 + 数据类型),例如存储学生信息(姓名:字符串、年龄:整数、成绩:浮点数)。
    • 内存高效:基于NumPy的连续内存模型,访问速度快,适合大规模数据处理。
    • 字段访问:支持通过字段名直接访问数据(如 array['age']),无需额外转换。
  2. 适用场景

    • 表格数据处理(CSV、数据库导出)
    • 科学计算中的多参数记录(如物理实验中时间、位置、温度等)
    • 与Pandas DataFrame互操作(结构化数组可无缝转为DataFrame)

🔧 二、创建方法

1. 定义数据类型(dtype)

使用 np.dtype 指定字段结构,支持三种语法:

  • 元组列表(最常用):
    dtype = np.dtype([('name', 'U10'), ('age', 'i4'), ('height', 'f4')])
    
  • 字典形式
    dtype = np.dtype({'names': ['name', 'age', 'height'], 
                     'formats': ['U10', 'i4', 'f4']})
    
  • 字符串简写
    dtype = np.dtype('U10, i4, f4')  # 字段名自动分配为f0, f1, f2
    

注:U10 表示长度10的Unicode字符串,i4 为32位整数,f4 为32位浮点数。

2. 创建结构化数组

data = np.array([('Alice', 25, 1.65), ('Bob', 30, 1.80)], dtype=dtype)

输出:

[('Alice', 25, 1.65) ('Bob', 30, 1.80)]

3. 三种创建方式对比

方法语法示例优势限制
元组列表dtype=[('name','U10'), ('age','i4')]字段名和类型明确代码稍长
字典形式dtype={'names':['name','age'], 'formats':['U10','i4']}字段名集中管理不支持嵌套字段
字符串简写dtype='U10, i4, f4'简洁字段名默认为f0,f1,...

🛠️ 三、数据操作

  1. 字段访问与修改

    • 按字段提取列
      names = data['name']  # 输出:['Alice' 'Bob']
      
    • 按行访问
      first_row = data[0]  # 输出:('Alice', 25, 1.65)
      
    • 修改值
      data['age'] += 1  # 所有年龄+1
      data[0]['height'] = 1.70  # 修改Alice身高
      
  2. 切片与条件筛选

    # 筛选年龄>25的记录
    filtered = data[data['age'] > 25]
    # 输出:[('Bob', 31, 1.80)]
    
  3. 排序

    # 按年龄升序排序
    sorted_data = np.sort(data, order='age')
    # 多字段排序:先按年龄,再按身高
    sorted_data = np.sort(data, order=['age', 'height'])
    

四、高级特性

  1. 嵌套字段
    支持字段内嵌套复合类型,适合存储树状结构:

    dtype_nested = np.dtype([
        ('info', [('name', 'U10'), ('age', 'i4')]),  # 嵌套字段
        ('height', 'f4')
    ])
    data_nested = np.array([(('Alice', 25), 1.65)], dtype=dtype_nested)
    
  2. 多维字段
    字段可以是多维数组,用于存储矩阵或张量:

    dtype_matrix = np.dtype([
        ('id', 'i4'), 
        ('matrix', 'f8', (3, 3))  # 每个元素包含3x3矩阵
    ])
    arr_matrix = np.zeros(2, dtype=dtype_matrix)
    
  3. 字段增删(需重建数组)

    # 添加体重字段
    new_dtype = np.dtype(dtype.descr + [('weight', 'f4')])
    new_data = np.zeros(data.shape, dtype=new_dtype)
    for field in data.dtype.names:
        new_data[field] = data[field]
    new_data['weight'] = [55, 70]  # 填充新字段
    

💡 五、实际应用案例

学生成绩管理系统

# 定义数据类型
dtype = np.dtype([
    ('name', 'U10'), 
    ('math', 'f4'), 
    ('english', 'f4'),
    ('physics', 'f4')
])

# 创建数组
students = np.array([
    ('Alice', 85, 90, 88),
    ('Bob', 92, 85, 90)
], dtype=dtype)

# 计算平均分并添加新字段
avg_scores = np.mean([students['math'], students['english'], students['physics']], axis=0)
students = np.lib.recfunctions.append_fields(students, 'average', avg_scores, dtypes='f4')

输出:

[('Alice', 85., 90., 88., 87.67) ('Bob', 92., 85., 90., 89.0)]

⚠️ 六、注意事项

  1. 内存对齐
    使用 np.dtype(..., align=True) 可强制内存对齐(类似C结构体),提升CPU访问效率
  2. 性能局限
    复杂查询(如多条件筛选)效率低于Pandas,建议在数据清洗后转为结构化数组进行计算。
  3. 类型映射
    复合类型可直接映射到C结构体,适合与C/Fortran库交互(如物理仿真、信号处理)。

💎 总结

NumPy复合数据类型通过结构化数组实现异构数据的高效存储,核心价值在于:

  • 灵活建模:用单一数组管理多类型数据,避免多数组同步问题。
  • 高性能计算:保留NumPy向量化操作优势,支持排序、筛选等复杂操作。
  • 跨平台兼容:内存布局兼容C语言,无缝对接底层科学计算库。