「这是我参与2022首次更文挑战的第14天,活动详情查看:2022首次更文挑战」
前言
继上一节numpy 记录数组辅助方法,我们已经对 recarray 辅助方法学习了一些。我们都知道recarray 辅助方法是由 numpy.lib 中 recfunctions 模块提供一系列对创建和操作结构化的函数方法。
- apply_along_fields() 方法可以使用应用函数缩减结构化数组中字段
- append_fields() 方法将新字段添加到结构化数组
- drop_fields() 方法在结构化数组中删除指定字段,并返回新数组
- join_by() 方法通过key连接两个数组
- merge_arrays()方法将数组列表进行合并
在使用合并数组列表中,数组的长度不一致时,系统合并过程中,系统会对较短的数组将缺失的值进行自动填充,填充的内容取决与它对应的类型。
填充值 | 说明 |
---|---|
-1 | 整数类型 |
-1.0 | 浮点数类型 |
"-" | 字符 |
'-1' | 字符串 |
True | 布尔值 |
本期,我们将继续学习 recfunctions 模块对结构化数组操作的相关方法,Let's go~
1. 获取结构化数组字段名称相关操作
recfunctions 模块还提供对结构化数据类型字段名称获取。
1.1 以字典形式返回字段名称
recfunctions 模块提供 get_fieldstructure() 方法对结构化数据类型字段以字典形式返回。
get_fieldstructure()方法对嵌入的结构化数据类似可以简化。
get_fieldstructure(adtype, lastname=None, parents=None,)
参数说明:
参数 | 说明 |
---|---|
adtype | 结构化数据类似np.dtype() |
lastname | 最后处理字段名称,可选 |
parents | 父字段字典 |
>>> import numpy as np
>>> from numpy.lib import recfunctions as rfn
>>> arr_dtype = np.dtype([("A","i8"),("B","i8")])
>>> rfn.get_fieldstructure(arr_dtype)
{'A': [], 'B': []}
>>>
get_fieldstructure()方法对嵌入的结构化数据类似可以简化尤为明显。
>>> import numpy as np
>>> from numpy.lib import recfunctions as rfn
>>> stu_dtype = np.dtype([("school","S16"),("class",[("classA","S6"),("classB","S6")])])
>>> rfn.get_fieldstructure(stu_dtype)
{'school': [], 'class': [], 'classA': ['class'], 'classB': ['class']}
>>>
1.2 以元组形式返回字段名称
recfunctions 模块提供 get_names()方法,以元组形式返回结构化数据类型字段
get_names(adtype)
参数说明:
参数 | 说明 |
---|---|
adtype | 输入数据类型 |
>>> arr_dtype = np.dtype([("A","i8"),("B","i8"),("C",[("C1","i8"),("C2","i4")])])
>>> rfn.get_names(arr_dtype)
('A', 'B', ('C', ('C1', 'C2')))
>>>
1.3 以元组展平形式返回字段名称
recfunctions 模块提供 get_name_flat() 对于嵌入结构的结构化数据类型字段名称为元组返回.
get_names_flat(adtype)
参数说明:
参数 | 说明 |
---|---|
adtype | 结构化数据类型 |
对比 get_names() 方法,对于嵌入字段名称,get_names_flat()方法返回时会取消嵌入结构,返回单元组。
>>> arr_dtype = np.dtype([("A","i8"),("B","i8"),("C",[("C1","i8"),("C2","i4")])])
>>> rfn.get_names(arr_dtype)
('A', 'B', ('C', ('C1', 'C2')))
>>> rfn.get_names_flat(arr_dtype)
('A', 'B', 'C', 'C1', 'C2')
>>>
2. 查找结构化数组重复项
recfunctions 模块提供 find_duplicates() 可以根据特定key结构化数组的重复项
find_duplicates(a, key=None, ignoremask=True, return_index=False)
参数说明:
参数 | 说明 |
---|---|
a | 输入数组 |
key | 用于检查重复性的字段的名称。默认为None |
ignoremask | 是否舍弃数据 |
return_index | 是否返回重复值的索引 |
使用 find_duplicates() 方法时,数组需要使用np.ma.array()类型
>>> arr =np.ma.array([1,1,2,3,1,3,1],dtype = [("A","i8")])
>>> rfn.find_duplicates(arr)
masked_array(data=[(1,), (1,), (1,), (1,), (3,), (3,)],
mask=[(False,), (False,), (False,), (False,), (False,),
(False,)],
fill_value=(999999,),
dtype=[('A', '<i8')])
>>>
如果使用np.array()创建的数据,进行查找重复项式时,系统会报AttributeError
>>> arr =np.array([1,1,2,3,1,3,1],dtype = [("A","i8")])
>>> rfn.find_duplicates(arr)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<__array_function__ internals>", line 6, in find_duplicates
File "C:\Users\user\AppData\Roaming\Python\Python37\site-packages\numpy\lib\recfunctions.py", line 1388, in find_duplicates
sorteddata = sortedbase.filled()
AttributeError: 'numpy.ndarray' object has no attribute 'filled'
3. 字段名称赋值
recfunctions 模块还提供 assign_fields_by_name()方法,可以将数组A的字段值赋值给数组B。
- assign_fields_by_name()方法是按字段名复制的,从源数组中字段复制给目标字段分配。
- 该方法使用递归,非常适合嵌套结构的结构化数组
assign_fields_by_name(dst, src, zero_unassigned=True)
参数说明:
参数 | 说明 |
---|---|
dst | 源数组 |
src | 目标数组 |
zero_unassigned | 可选,如果为True。dst中src中没有匹配的字段将填充为0 |
>>> arr =np.array([1,1,2,3,1,3,1],dtype = [("A","i8")])
>>> arr2 =np.array([10,10,20,30,1,3,1],dtype = [("A","i8")])
>>> rfn.assign_fields_by_name(arr,arr2)
>>> arr
array([(10,), (10,), (20,), (30,), ( 1,), ( 3,), ( 1,)],
dtype=[('A', '<i8')])
>>>
注意 dst 和 src 数组必须要保持同shape的,否则系统会报ValueError
>>> arr =np.array([1,1,2,3,1,3,1],dtype = [("A","i8")])
>>> arr2 = np.array([(1,2),(3,3),(1,2)],dtype=[("A","i8"),("B","i8")])
>>> rfn.assign_fields_by_name(arr2,arr)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<__array_function__ internals>", line 6, in assign_fields_by_name
File "C:\Users\user\AppData\Roaming\Python\Python37\site-packages\numpy\lib\recfunctions.py", line 1200, in assign_fields_by_name
zero_unassigned)
File "<__array_function__ internals>", line 6, in assign_fields_by_name
File "C:\Users\user\AppData\Roaming\Python\Python37\site-packages\numpy\lib\recfunctions.py", line 1191, in assign_fields_by_name
dst[...] = src
ValueError: could not broadcast input array from shape (7) into shape (3)
>>>
4. 字段折叠
recfunctions 模块将数组列表字段进行叠加,返回一个新数组。
stack_arrays(arrays, defaults=None, usemask=True, asrecarray=False,
autoconvert=False)
参数说明:
参数 | 说明 |
---|---|
arrays | 数组或者数组序列 |
defaults | 字典类型,将字段名映射到相应的默认值 |
usemask | 是否返回掩码数组 |
asrecarray | 是否返回记录数组 |
autoconvert | 是否自动将字段的类型转换为最大值 |
>>> arr =np.array([1,1,2,3,1,3,1],dtype = [("A","i8")])
>>> arr2 = np.array([(1,2),(3,3),(1,2)],dtype=[("A","i8"),("B","i8")])
>>> new_arr = rfn.stack_arrays((arr,arr2))
>>> new_arr
masked_array(data=[(1, --), (1, --), (2, --), (3, --), (1, --), (3, --),
(1, --), (1, 2), (3, 3), (1, 2)],
mask=[(False, True), (False, True), (False, True),
(False, True), (False, True), (False, True),
(False, True), (False, False), (False, False),
(False, False)],
fill_value=(999999, 999999),
dtype=[('A', '<i8'), ('B', '<i8')])
>>>
注意:在数组序列字段叠加过程中,字段名称缺少的值,系统会默认填充"--"
5. 结构化与非结构化转换
recfunctions 模块中还支持对结构化数组与非结构化数组相互转换的方法。
5.1 结构化转换成非结构化
recfunctions 模块提供 structured_to_unstructured()方法将结构化数组转换成非结构化数组。
- structured_to_unstructured()方法将n结构化数组转换(n+1)D非结构化数组
- 新数组将一个新的最后一维,其大小等于输入数组的字段元素数
- 如果未提供输出数据类型,则系统会按照numpy 数据类型规则确定
structured_to_unstructured(arr, dtype=None, copy=False, casting='unsafe')
参数说明:
参数 | 说明 |
---|---|
arr | 结构化数组 |
dtype | 指定输出非结构化数组的dtype |
copy | 默认为false,如果为True,则会返回一个副本,否则返回视图 |
casting | 可选项,可选值有"no","equiv","safe","some_kind","unsafe",控制数据类型转换情况 |
>>> arr =np.array([1,1,2,3,1,3,1],dtype = [("A","i8")])
>>> arr
array([(1,), (1,), (2,), (3,), (1,), (3,), (1,)], dtype=[('A', '<i8')])
>>> rfn.structured_to_unstructured(arr)
array([[1],
[1],
[2],
[3],
[1],
[3],
[1]], dtype=int64)
>>> arr2 = np.array([(1,2),(3,3),(1,2)],dtype=[("A","i8"),("B","i8")])
>>> rfn.structured_to_unstructured(arr2)
array([[1, 2],
[3, 3],
[1, 2]], dtype=int64)
>>>
5.2 非结构化转换成结构化
recfunctions 模块也提供支持将非结构化数组转换成结构化数组的unstructured_to_structured()方法。
- 该方法将n维非结构化数组转换成(n-1)维结构化数组
- 输入的数组的最后一维被转换成一个结构,字段元素的数量等于输入数组最后一维的大小
- 默认情况,输出的字段都具有输入数组的dtype 。
- 可以提供输出结构化的dtype字段
unstructured_to_structured(arr, dtype=None, names=None, align=False,
copy=False, casting='unsafe')
参数说明:
参数 | 说明 |
---|---|
arr | 非结构化数组 |
dtype | 要输出的结构化数组dtype |
names | 字符串列表 |
align | 是否创建对齐内存布局 |
copy | 是否要返回一个副本 |
casting | 控制发生的数据类型转换 |
>>> arr = np.array([(1,2),(3,3),(1,2)])
>>> arr_dtype = np.dtype([("A","i8"),("B","i8")])
>>> rfn.unstructured_to_structured(arr)
array([(1, 2), (3, 3), (1, 2)], dtype=[('f0', '<i4'), ('f1', '<i4')])
>>> rfn.unstructured_to_structured(arr,arr_dtype)
array([(1, 2), (3, 3), (1, 2)], dtype=[('A', '<i8'), ('B', '<i8')])
>>>
总结
本期,我们已经对recfunctions 模块提供对结构化数组操作如可使用stack_arrays()方法将数组序列字段进行叠加,返回新数组。并且我们可以使用unstructured_to_structured()将非结构化数组转换成结构化数组,structured_to_unstructured将结构化数组转换成非结构化数组。
recarray 辅助方法可以帮助我们更好使用结构化数组,在实际工作中大家多多使用。
以上是本期内容,欢迎大佬们点赞评论,下期见~