NumPy - 记录数组



NumPy中的记录数组

记录数组类似于结构化数组,但具有一个附加功能:它们允许您使用属性样式(点表示法)和索引样式(字典样式)访问来访问字段作为属性。

这可以使代码更易于阅读和编写,尤其是在处理复杂数据结构时。

创建记录数组

我们可以通过多种方式创建记录数组,它们是:

  • 通过转换现有结构化数组
  • 直接定义记录数组
  • 使用 np.recarray 构造函数

将结构化数组转换为记录数组

创建记录数组最简单的方法之一是使用 view 方法转换现有的结构化数组。这种方法允许您在获得属性访问便利性的同时保持数据的结构。

示例

在下面的示例中,我们将 NumPy 中的结构化数组转换为记录数组:

import numpy as np

# Create a structured array
structured_array = np.array([('Alice', 25, 5.5), ('Bob', 30, 6.0)], dtype=[('name', 'U10'), ('age', 'i4'), ('height', 'f4')])

# Convert the structured array to a record array
record_array = structured_array.view(np.recarray)

# Access fields as attributes
print(record_array.name)  
print(record_array.age)  

获得的输出如下:

['Alice' 'Bob']
[25 30]

直接创建记录数组

创建记录数组的另一种方法是使用 **np.rec.array()** 函数直接定义它。此方法允许您从头开始创建记录数组,同时指定数据和结构。

示例

在下面的示例中,我们直接在 NumPy 中创建记录数组,这允许我们使用点表示法访问字段作为属性:

import numpy as np 

# Directly create a record array
record_array_direct = np.rec.array([('Charlie', 35, 5.8), ('David', 40, 6.2)], dtype=[('name', 'U10'), ('age', 'i4'), ('height', 'f4')])

# Access fields as attributes
print(record_array_direct.name)   
print(record_array_direct.height) 

这将产生以下结果:

['Charlie' 'David']
[5.8 6.2]

使用 np.recarray 构造函数

您还可以使用 np.recarray 构造函数创建记录数组。此方法不太常见,但在特定用例中提供额外的灵活性。

示例

在这个例子中,我们使用 np.recarray 构造函数创建一个记录数组,为其分配数据,然后访问字段 **name** 和 **age** 作为属性:

import numpy as np

# Define a record array using np.recarray
record_array_custom = np.recarray((2,), dtype=[('name', 'U10'), ('age', 'i4'), ('height', 'f4')])

# Assign data to the record array
record_array_custom[0] = ('Eve', 28, 5.7)
record_array_custom[1] = ('Frank', 33, 6.1)

# Access fields as attributes
print(record_array_custom.name)   
print(record_array_custom.age)   

以上代码的输出如下:

['Eve' 'Frank']
[28 33]

访问记录数组的字段

创建记录数组后,您可以将其字段(即结构化数据的列)作为属性访问,这简化了数据操作和查询。

访问记录数组字段最常用的方法是使用 **点 (.)** 表示法。记录数组的每个字段都成为可以直接访问的属性,类似于您在 Python 中访问对象属性的方式。

示例:使用属性表示法访问字段

在下面的示例中,我们创建一个具有字段 **name**、**age** 和 **height** 的记录数组,然后将每个字段作为记录数组的属性访问:

import numpy as np

# Create a record array
record_array = np.rec.array([('Alice', 25, 5.5), ('Bob', 30, 6.0)], dtype=[('name', 'U10'), ('age', 'i4'), ('height', 'f4')])

# Accessing the 'name' field
print(record_array.name)  

# Accessing the 'age' field
print(record_array.age)   

# Accessing the 'height' field
print(record_array.height) 

获得的输出如下:

['Alice' 'Bob']
[25 30]
[5.5 6. ]

示例:同时访问多个字段

除了访问单个字段外,您还可以一次访问多个字段。但是,与结构化数组不同,记录数组不支持使用属性表示法直接同时访问字段。

如果您想一次检索多个字段,则需要像下面的示例中所示那样恢复到传统的索引方法:

import numpy as np

# Create a record array
record_array = np.rec.array([('Alice', 25, 5.5), ('Bob', 30, 6.0)], dtype=[('name', 'U10'), ('age', 'i4'), ('height', 'f4')])

# Access multiple fields using indexing
multiple_fields = record_array[['name', 'height']]
print(multiple_fields)

执行上述代码后,我们得到以下输出:

[('Alice', 5.5) ('Bob', 6. )]

修改记录数组的字段

修改 NumPy 记录数组中的字段允许您更新或更改结构化数据集中的特定列(字段)中的数据。记录数组提供了一种使用 **属性样式** 访问来访问和修改字段的方法。

例如,您可以通过点 (.) 表示法访问字段,然后应用所需的运算或赋值来修改记录数组中各个字段的值。

要向记录数组添加新字段,您可以结合使用 np.concatenat() 函数(或类似函数)来创建一个包含附加字段的新记录数组。

示例:更新字段

在下面的示例中,我们创建一个具有字段“name”、“age”和“height”的记录数组。然后我们更改特定记录的“age”和“height”:

import numpy as np

# Step 1: Define the initial record array with fields 'name', 'age', and 'height'
dtype = [('name', 'S20'), ('age', 'i1'), ('height', 'f4')]
data = [('Alice', 30, 5.5), ('Bob', 25, 6.0), ('Charlie', 35, 5.8)]
record_array = np.array(data, dtype=dtype)

print("Original Record Array:")
print(record_array)

# Step 2: Update the fields for specific records
# Update 'age' and 'height' for 'Bob'
record_array[record_array['name'] == b'Bob']['age'] = 26
record_array[record_array['name'] == b'Bob']['height'] = 6.1

# Update 'age' for 'Charlie'
record_array[record_array['name'] == b'Charlie']['age'] = 36

print("\nUpdated Record Array:")
print(record_array)

产生的结果如下:

Original Record Array:
[(b'Alice', 30, 5.5) (b'Bob', 25, 6. ) (b'Charlie', 35, 5.8)]

Updated Record Array:
[(b'Alice', 30, 5.5) (b'Bob', 25, 6. ) (b'Charlie', 35, 5.8)]

示例:添加新字段

在这个例子中,我们首先定义一个只包含“name”和“age”字段的记录数组。然后我们创建一个包含额外“height”字段的新记录数组:

import numpy as np

# Step 1: Define the initial record array with fields 'name' and 'age'
dtype = [('name', 'S20'), ('age', 'i1')]
data = [('Alice', 30), ('Bob', 25), ('Charlie', 35)]
record_array = np.array(data, dtype=dtype)

print("Original Record Array:")
print(record_array)

# Step 2: Define a new dtype that includes the new field 'height'
new_dtype = [('name', 'S20'), ('age', 'i1'), ('height', 'f4')]

# Step 3: Create a new record array with the new dtype, initialized with zeros or default values
new_record_array = np.zeros(record_array.shape, dtype=new_dtype)

# Step 4: Copy existing data into the new record array
for field in ['name', 'age']:
    new_record_array[field] = record_array[field]

# Optionally, set default values for the new field 'height'
new_record_array['height'] = 0.0

print("\nRecord Array with New Field:")
print(new_record_array)

我们得到如下所示的输出:

Original Record Array:
[(b'Alice', 30) (b'Bob', 25) (b'Charlie', 35)]

Record Array with New Field:
[(b'Alice', 30, 0.) (b'Bob', 25, 0.) (b'Charlie', 35, 0.)]

组合记录数组

在 NumPy 中组合记录数组是指将多个记录数组合并或连接成单个记录数组。当您需要组合数据集或使用其他行扩展现有数据集时,此过程非常有用。

以下是组合记录数组的方法:

  • **连接:**沿现有轴(通常沿行)组合记录数组。
  • **堆叠:**沿新轴堆叠记录数组,这对于添加新维度很有用。

示例:连接记录数组

在下面的示例中,我们创建两个记录数组,然后沿行将它们连接起来以形成一个组合的单个记录数组:

import numpy as np

# Define two record arrays with fields 'name', 'age', and 'height'
dtype = [('name', 'U10'), ('age', 'i4'), ('height', 'f4')]
data1 = [('Alice', 25, 5.5), ('Bob', 30, 6.0)]
data2 = [('Charlie', 35, 5.8), ('David', 40, 5.9)]

# Create record arrays
record_array1 = np.array(data1, dtype=dtype).view(np.recarray)
record_array2 = np.array(data2, dtype=dtype).view(np.recarray)

# Concatenate the record arrays along the rows (axis 0)
combined_record_array = np.concatenate((record_array1, record_array2))

print("Combined record array:")
print(combined_record_array)

获得的输出如下:

Combined record array:
[('Alice', 25, 5.5) ('Bob', 30, 6. ) ('Charlie', 35, 5.8)
 ('David', 40, 5.9)]

示例:堆叠记录数组

在下面的示例中,我们创建两个记录数组,然后沿新轴将它们堆叠起来以形成一个 3D 记录数组:

import numpy as np

# Define two record arrays with fields 'name', 'age', and 'height'
dtype = [('name', 'U10'), ('age', 'i4'), ('height', 'f4')]
data1 = [('Alice', 25, 5.5), ('Bob', 30, 6.0)]
data2 = [('Charlie', 35, 5.8), ('David', 40, 5.9)]

# Create record arrays
record_array1 = np.array(data1, dtype=dtype).view(np.recarray)
record_array2 = np.array(data2, dtype=dtype).view(np.recarray)

# Stack the record arrays along a new axis
stacked_record_array = np.stack((record_array1, record_array2), axis=0)

print("Stacked record array:")
print(stacked_record_array)

这将产生以下结果:

Stacked record array:
[[('Alice', 25, 5.5) ('Bob', 30, 6. )]
 [('Charlie', 35, 5.8) ('David', 40, 5.9)]]

过滤记录数组

过滤记录数组是指根据条件或条件集从记录数组中选择特定的行或元素。

此过程用于提取满足特定条件的数据子集,这有助于我们进行更集中的分析和操作。

示例

在这个例子中,我们创建一个布尔掩码来过滤记录数组中“age”大于“30”的记录:

import numpy as np

# Define a record array with fields 'name', 'age', and 'height'
dtype = [('name', 'U10'), ('age', 'i4'), ('height', 'f4')]
data = [('Alice', 25, 5.5), ('Bob', 30, 6.0), ('Charlie', 35, 5.8), ('David', 40, 5.9)]
record_array = np.array(data, dtype=dtype).view(np.recarray)

# Create a Boolean mask for ages greater than 30
mask = record_array.age > 30

# Apply the mask to filter the record array
filtered_record_array = record_array[mask]

print("Filtered record array (ages > 30):")
print(filtered_record_array)

以上代码的输出如下:

Filtered record array (ages > 30):
[('Charlie', 35, 5.8) ('David', 40, 5.9)]
广告