Numpy库:结构化数组

来自和鲸社区
假定现在有关于一些人的分类数据(如姓名,年龄和体重),我们需要存储这些数据用于Python项目,一种可行的方法是将它们存在三个单独的数组中

name = ['Alice', 'Bob', 'Cathy', 'Doug']
age = [25, 45, 37, 19]
weight = [55.0, 85.5, 68, 61.5]

但这种方法有点笨,因为并没有任何信息能说明这三个数组之间是相关联的,可以用结构化数组来存储所有数据

# 生成一个简单的数组
x = np.zeros(4, dtype = int)
print('x: ', x)

# 通过指定复合数据结构,构造一个结构化数组,dtype参数是一个字典,‘name’指定字段名称每个元素包含三个字段:name, age, weight
data = np.zeros(4, dtype = {'names':('name', 'age', 'weight'),
                            'formats':('U10', 'i4', 'f8')})
# u10:表示长度不超过10的Unicode字符串,i4表示4字节整型,f8表示8字节浮点型
print('data.dtype:', data.dtype)
print('空数组data:', data)

# 将列表数据放入生成的空数组中
data['name'] = name
data['age'] = age
data['weight'] = weight
print('data: ', data)

# 通过索引或名称查看相应的值
print('获取所有名称:', data['name'])
print('获取数据第一行:', data[0])
print('获取最后一行的名字:', data[-1]['name'])

# 利用布尔掩码复杂操作,例如按照年龄进行筛选
print('获取年龄小于30岁的人信息', data[data['age'] < 30])
print('获取年龄小于30岁的人的名字', data[data['age'] < 30]['name'])

x: [0 0 0 0]
data.dtype: [(‘name’, ‘<U10’), (‘age’, ‘<i4’), (‘weight’, ‘<f8’)]
空数组data: [(‘’, 0, 0.) (‘’, 0, 0.) (‘’, 0, 0.) (‘’, 0, 0.)]
data: [(‘Alice’, 25, 55. ) (‘Bob’, 45, 85.5) (‘Cathy’, 37, 68. )
(‘Doug’, 19, 61.5)]
获取所有名称: [‘Alice’ ‘Bob’ ‘Cathy’ ‘Doug’]
获取数据第一行: (‘Alice’, 25, 55.)
获取最后一行的名字: Doug
获取年龄小于30岁的人信息 [(‘Alice’, 25, 55. ) (‘Doug’, 19, 61.5)]
获取年龄小于30岁的人的名字 [‘Alice’ ‘Doug’]

1 生成结构式数组

采用字典方式,制定结构化数组的数据类型

np.dtype({'names':('name', 'age', 'weight'),
                   'formats':('U10', 'i4', 'f8')})

dtype([(‘name’, ‘<U10’), (‘age’, ‘<i4’), (‘weight’, ‘<f8’)])

数值数据类型可以用Python类型或NumPy的dtype类型指定

np.dtype([('name', 'S10'), ('age', 'i4'), ('weight', 'f8')])

dtype([(‘name’, ‘S10’), (‘age’, ‘<i4’), (‘weight’, ‘<f8’)])

如果类型名称并不重要可以省略,仅仅指定数据类型

np.dtype('S10, i4, f8')

dtype([(‘f0’, ‘S10’), (‘f1’, ‘<i4’), (‘f2’, ‘<f8’)])
在这里插入图片描述

2 更高级的复合类型

之前创建的每个元素例如name, age都是一个列表,也可以创建更高级的复合类型比如每个元素是一个数组或矩阵

# 创建一个只包含1个元素的结构化数组,其中该元素的数据类型是一个 mat组件包含一个3x3的浮点矩阵
user_id = [1, 2, 3, 4]
X = np.zeros(4, dtype = ([('user_id', 'i8'), ('mat', 'f8', (3, 3))]))
X['user_id'] = user_id
print('X: ', X)
print('获取第一行:', X[0])
print('mat:', X['mat'])
print('mat第一层:', X['mat'][0])

X: [(1, [[0., 0., 0.], [0., 0., 0.], [0., 0., 0.]])
(2, [[0., 0., 0.], [0., 0., 0.], [0., 0., 0.]])
(3, [[0., 0., 0.], [0., 0., 0.], [0., 0., 0.]])
(4, [[0., 0., 0.], [0., 0., 0.], [0., 0., 0.]])]
获取第一行: (1, [[0., 0., 0.], [0., 0., 0.], [0., 0., 0.]])
mat: [[[0. 0. 0.]
[0. 0. 0.]
[0. 0. 0.]]

[[0. 0. 0.]
[0. 0. 0.]
[0. 0. 0.]]

[[0. 0. 0.]
[0. 0. 0.]
[0. 0. 0.]]

[[0. 0. 0.]
[0. 0. 0.]
[0. 0. 0.]]]
mat第一层: [[0. 0. 0.]
[0. 0. 0.]
[0. 0. 0.]]

3 记录数组:结构化数组的扭转

Numpy提供了np.recarray类,与结构化数组几乎相同,但有一个独特特征:域可以像属性一样获取,而不是像字典的键那样获取

# 类似字典的键获取方式
data['age']

array([25, 45, 37, 19], dtype=int32)

如果将这些数据当作一个记录数组,可以用很少的键来获取这个结果, 可以使用点操作符访问字段,每个字段代表一列

# data.view 允许你创建一个与原始结构化数组共享数据存储的视图,从而可以以不同的方式查看和操作相同的数据。这在某些情况下可以提高效率,因为不需要复制数据。
# 但要注意,修改视图可能会影响原始数组,因此需要小心操作。
data_rec = data.view(np.recarray)
data_rec.age

array([25, 45, 37, 19], dtype=int32)

这里np.recarray的使用实际上是增添了一种检索结构化数组的方法,纯粹看习惯,和效率?
因此,需要说明的是,data_rec和data是同一个存储地址,这意味着,改变data_rec也会改变data.
以上内容由于原文总结得很好,因此基本上直接照搬,仅当作记笔记方便自己看和给大家看.


OK 来点新东西,刚学会的
rfn.append_fields可用于结构化数组的添列
以下是代码

# 可以用以下代码进行列数据添加
import numpy.lib.recfunctions as rfn

new_data = rfn.append_fields(new_data, 'points_eff', points_eff, usemask=False)  

模块与函数

  • rfn:这是 NumPy 库中的一个子模块,它提供了用于处理结构化数组的各种函数。
  • append_fields:这是 rfn 模块中的一个函数,用于向现有的结构化数组中添加新的字段。
    这里仅用到函数append_fields,如若还需要

参数解释

  • new_data:这是原始的结构化数组,具有多个字段(列)。结构化数组允许每个元素有不同的数据类型和字段名。
  • ‘points_eff’:这是要添加的新字段的名称。它将作为新列的标题。
  • points_eff:这是一个包含要插入到新字段中的数据的数组。这个数组的长度应该与 new_data 中的元素数量一致,以确保每个元素都有相应的 points_eff 值。
  • usemask=False:这个参数指示是否使用掩码。如果设置为 True,则会考虑掩码数据,即只有未被掩码的数据会被添加。如果为
    False,则所有数据都将被添加

返回值

  • new_data = …:通过调用 append_fields 函数,将返回的新的结构化数组赋值给 new_data变量。这个新数组包含了原始数据以及新增的 points_eff 字段。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值