Python数据科学手册:NumPy结构化数组详解
什么是结构化数组
在数据分析中,我们经常需要处理包含多种数据类型的数据集。NumPy的结构化数组(Structured Arrays)提供了一种高效存储和处理复合异构数据的方式。与常规的NumPy数组不同,结构化数组允许每个元素包含多个字段,每个字段可以有不同的数据类型。
为什么需要结构化数组
假设我们需要存储一组人员信息,包括姓名、年龄和体重:
name = ['Alice', 'Bob', 'Cathy', 'Doug']
age = [25, 45, 37, 19]
weight = [55.0, 85.5, 68.0, 61.5]
使用三个独立数组存储虽然可行,但缺乏关联性。结构化数组将这些数据整合到一个数组中,保持了数据的内在联系。
创建结构化数组
创建结构化数组的关键是定义合适的数据类型(dtype)。以下是几种定义方式:
- 字典方式:最直观的方法,明确指定字段名和类型
dtype = {'names':('name', 'age', 'weight'),
'formats':('U10', 'i4', 'f8')}
- 元组列表方式:简洁明了
dtype = [('name', 'S10'), ('age', 'i4'), ('weight', 'f8')]
- 字符串简写:适合快速原型开发
dtype = 'S10,i4,f8'
类型代码说明:
- 'U10':最大长度10的Unicode字符串
- 'i4':4字节(32位)整数
- 'f8':8字节(64位)浮点数
结构化数组操作
创建并填充结构化数组:
data = np.zeros(4, dtype=dtype)
data['name'] = name
data['age'] = age
data['weight'] = weight
访问数据非常灵活:
# 获取所有姓名
data['name']
# 获取第一行所有数据
data[0]
# 获取最后一行的姓名
data[-1]['name']
# 条件筛选:年龄小于30的姓名
data[data['age'] < 30]['name']
高级数据类型
结构化数组支持更复杂的数据类型,如数组或矩阵字段:
# 定义包含ID和3x3矩阵的类型
tp = np.dtype([('id', 'i8'), ('mat', 'f8', (3, 3))])
X = np.zeros(1, dtype=tp)
这种结构直接映射到C语言的结构体,非常适合与C/Fortran程序交互。
记录数组(Record Arrays)
记录数组是结构化数组的变体,允许通过属性访问字段:
data_rec = data.view(np.recarray)
data_rec.age # 等价于data['age']
虽然语法更简洁,但性能略有下降,适合交互式分析。
结构化数组的局限性
尽管结构化数组功能强大,但对于复杂的数据操作,Pandas的DataFrame通常是更好的选择。DataFrame提供了更丰富的数据处理功能,包括:
- 更灵活的数据索引
- 强大的数据清洗工具
- 便捷的聚合统计功能
- 优秀的时间序列处理能力
何时使用结构化数组
结构化数组最适合以下场景:
- 需要与C/Fortran代码交互
- 处理二进制数据格式
- 内存效率是关键因素
- 只需要基本的字段访问和筛选
对于大多数数据分析任务,建议直接使用Pandas,它底层也使用NumPy数组,但提供了更高级的接口。
总结
NumPy的结构化数组是处理复合异构数据的有力工具,特别适合底层数据操作和与其他语言的交互。理解结构化数组的工作原理有助于深入理解Python数据科学生态系统的基础。当项目复杂度增加时,可以平滑过渡到Pandas,获得更强大的数据处理能力。
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考