介绍
在本实验中,你将学习 NumPy 中的结构化数组(structured arrays)。结构化数组是处理异构数据(heterogeneous data)的强大功能,类似于数据库中的表或电子表格。结构化数组的每个元素都可以被看作是一行,其中包含称为“字段”(fields)的命名列。这使得它们非常适合直接在 Python 中组织和操作表格数据。
在本实验中,你将在 WebIDE 中提供的 structured_arrays.py 文件中编写和执行 Python 代码。
在本实验中,你将学习 NumPy 中的结构化数组(structured arrays)。结构化数组是处理异构数据(heterogeneous data)的强大功能,类似于数据库中的表或电子表格。结构化数组的每个元素都可以被看作是一行,其中包含称为“字段”(fields)的命名列。这使得它们非常适合直接在 Python 中组织和操作表格数据。
在本实验中,你将在 WebIDE 中提供的 structured_arrays.py 文件中编写和执行 Python 代码。
首先,让我们创建一个简单的结构化数组。结构化数组的数据类型(dtype)被定义为一个元组列表(list of tuples)。每个元组指定一个字段及其 (name, data_type)。这允许我们在同一个数组中存储不同类型的数据,如字符串和整数。
从左侧面板的文件浏览器中打开 structured_arrays.py 文件。添加以下代码来创建一个结构化数组,该数组表示一个包含姓名和年龄的列表。
## Create a structured array
data = np.array([('Alice', 25, 55.5), ('Bob', 30, 68.0)],
dtype=[('name', 'U10'), ('age', 'i4'), ('weight', 'f4')])
print("Original Array:")
print(data)
## Access a specific field by its name
names = data['name']
print("\nNames field:")
print(names)
代码解释:
import numpy as np: 这行代码导入 NumPy 库。np.array([...], dtype=[...]): 我们创建一个数组。第一个参数是一个元组列表,其中每个元组 ('Alice', 25, 55.5) 代表一行数据。dtype=[('name', 'U10'), ('age', 'i4'), ('weight', 'f4')]: 这是关键部分。我们定义了三个字段:
'name': 一个最大长度为 10 个字符的 Unicode 字符串(U10)。'age': 一个 4 字节(32 位)的整数(i4)。'weight': 一个 4 字节(32 位)的浮点数(f4)。data['name']: 我们可以通过使用字段名作为索引来访问特定字段(列)的所有值,这将返回一个新的 NumPy 数组。现在,保存文件并从终端运行它以查看输出。
python structured_arrays.py
你应该会看到以下输出,它显示了完整的结构化数组以及仅包含姓名的数组。
Original Array:
[('Alice', 25, 55.5) ('Bob', 30, 68. )]
Names field:
['Alice' 'Bob']
结构化数组是可变的(mutable),这意味着你可以更改它们的值。你可以一次性修改整个字段,或者通过索引访问特定元素然后修改其字段。你还可以创建一个包含原始字段子集的新数组。
将以下代码添加到你的 structured_arrays.py 脚本末尾。
## Modify the 'age' field
data['age'] = [26, 31]
print("\nArray after modifying age:")
print(data)
## Access a single element (the first row)
first_person = data[0]
print("\nFirst person's data:")
print(first_person)
## Create a new array with a subset of fields
subset = data[['name', 'weight']]
print("\nSubset of array (name and weight):")
print(subset)
代码解释:
data['age'] = [26, 31]: 这将一个新值列表赋给 age 字段,从而更新了整个列。data[0]: 这会访问数组的第一个元素(行)。结果是一个 NumPy void scalar,它包含了该单行的所有数据。data[['name', 'weight']]: 通过传递一个字段名列表,你可以选择多个列,这将创建一个只包含这些字段的新结构化数组。保存文件并再次从终端运行它。
python structured_arrays.py
你的输出现在将包含新的部分,显示修改后的数组和子集。
... (previous output) ...
Array after modifying age:
[('Alice', 26, 55.5) ('Bob', 31, 68. )]
First person's data:
('Alice', 26, 55.5)
Subset of array (name and weight):
[('Alice', 55.5) ('Bob', 68. )]
虽然按名称索引(例如 data['name'])非常强大,但可能会显得冗长。NumPy 提供了一个 ndarray 的特殊子类,称为记录数组(record array,np.recarray)。记录数组允许你像访问属性一样访问字段,使用点表示法(例如 record_array.name),这可以使你的代码更简洁、更易读。
你可以直接创建记录数组,或者转换现有的结构化数组。让我们看看如何做到这两点。将以下代码添加到 structured_arrays.py 的末尾。
## Convert the structured array to a record array using view()
record_array = data.view(np.recarray)
print("\nType of the new view:")
print(type(record_array))
## Access fields using attribute (dot) notation
print("\nAccessing names via attribute:")
print(record_array.name)
print("\nAccessing ages via attribute:")
print(record_array.age)
代码解释:
data.view(np.recarray): .view() 方法会创建一个查看相同数据的新数组对象。通过指定 np.recarray,我们获得了结构化数组数据的记录数组视图。没有数据被复制;这只是与数据交互的一种不同方式。record_array.name: 这是记录数组的关键特性。你可以像访问对象的属性一样访问 name 字段。这等同于 record_array['name']。保存文件并执行它。
python structured_arrays.py
输出现在将显示新数组视图的类型,并演示属性访问。
... (previous output) ...
Type of the new view:
<class 'numpy.recarray'>
Accessing names via attribute:
['Alice' 'Bob']
Accessing ages via attribute:
[26 31]
在本实验中,你学习了 NumPy 中结构化数组(structured arrays)的基础知识。你首先创建了一个具有命名字段和多种数据类型的结构化数组。然后,你练习了使用字典风格的键索引来访问特定字段(列)并修改它们的值。最后,你探索了记录数组(record arrays),这是一种方便的替代方法,允许你像访问属性一样访问字段,并学习了如何使用 .view() 方法在标准的结构化数组和记录数组之间进行转换。
结构化数组是处理 Python 中科学计算和数据分析中复杂、表格化数据集的重要工具。