复合数据类型
结构化数组
前面介绍过,在创建数组时使用 dtype
参数可以指定数组元素的类型:
numpy 提供了许多数据类型,可以满足各种场景的使用。但是这种方式创建的数组只能容纳同种类型的元素。
通过在列表内安排多个数据类型,可以指定复合数据类型,构造一个结构化数组:
这种复合数据类型可以通过字段名来区分各个数据成员,就像命名元组一样。
当检查该数组的类型时,可以看到复合数据类型由多个简单数据类型组合而成。这里基本数据类型以简写形式表达,U16
表示“长度不超过 16 的 Unicode 字符串”,i2
表示“ 2 字节(16 位)整型”,f8 表示“ 8 字节(64 位)浮点型”。最前方的小于号 <
表示以低字节序(little endian)存储。
更多字符对应的 numpy 的数据类型如下表所示:
数据类型符号 | 描述 | 数据类型符号 | 描述 |
---|---|---|---|
'b' | 字节型 | 'c' | 浮点型复数 |
'i' | 有符号整型 | 'S', 'a' | 字符串 |
'u' | 无符号整型 | 'U' | Unicode 字符串 |
'f' | 浮点型 | 'V' | 原生数据 |
除了元组列表外,还可以通过字典的形式表达复合数据类型:
还可以忽略字段名称,仅用一个逗号分隔的字符串来指定复合类型:
这种通过 dtype
类构造的类型也可以直接用作传参。
现在生成了一个空的数组容器,可以将列表数据放入数组中:
结构化数组所有的数据被安排在一个内存块中,因此它的存储和运算效率都优于元组列表。
可以通过索引或名称查看相应的值。例如,以下获取结构数组所有 name
字段的内容:
以下获取数据的第一个结构:
以下获取最后一个结构的 name
字段:
利用布尔数组数据,还可以做一些更复杂的操作,如按照分数筛选结构,再提取结构字段:
更高级的复合类型
numpy 中也可以定义更高级的复合数据类型,其中每个字段又是一个复合数据类型。
例如,可以创建一种结构,其中每个元素都包含一个数组或矩阵:
使用第三个参数可以确定数组的形状。
使用这种规则还可以创建嵌套结构类型,例如:
它的使用方法和普通的数组并没有太大差异。
numpy 还提供了 recarray
类。它和前面介绍的结构化数组几乎相同,但是它有一个独特的特征:字段可以像属性一样获取,而不是像字典的键那样获取。
例如,以下使用 .view()
方法,将一个数组通过视图表现为 recarray
类。这种类型的转换不修改底层数据,只改变数据的处理方式:
NumPy与I/O
在处理大量数据时,将结果暂时保存到磁盘上是有必要的。numpy 提供了一系列 I/O 操作,可以与磁盘交互。
最基本的 save(file, arr, allow_pickle=True, fix_imports=True)
函数将数组保存到扩展名为 .npy
的文件中。allow_pickle
参数使用序列化形式保存数组对象。fix_imports
参数则是为了处理 Python2 与 Python3 的版本差异:
然后同级目录下就会得到一个 grade7.npy
的文件。由于对其做了序列化操作,因此该文件是二进制形式的,不能通过一般的文本编辑器打开。
读取则使用 load()
函数。如果不想使用二进制的形式保存数据,可以调用 savetxt()
以简单的文本形式存储数据,对应的使用 loadtxt()
函数读取文本数据。不过文本形式无法保存复杂的结构化数组数据,因此不建议使用。