【发布时间】:2021-10-13 15:21:53
【问题描述】:
上下文
从numpy 1.16 版开始,如果您访问结构化数组的多个字段,则结果数组的dtype 将具有与原始数组相同的项大小,从而导致额外的“填充”:
与 1.15 相比,Numpy 1.16 的新行为导致在未索引字段的位置有额外的“填充”字节。您将需要更新任何依赖于具有“打包”布局的数据的代码。
这可能会导致问题,例如如果您想稍后将字段添加到相关数组中:
import numpy as np
import numpy.lib.recfunctions
a = np.array(
[
(10.0, 13.5, 1248, -2),
(20.0, 0.0, 0, 0),
(30.0, 0.0, 0, 0),
(40.0, 0.0, 0, 0),
(50.0, 0.0, 0, 999)
], dtype=[('x', '<f8'), ('y', '<f8'), ('i', '<i8'), ('j', '<i8')]
) # some array stolen from here: https://stackoverflow.com/a/37081693/5472354
print(a.shape, a.dtype, a.dtype.names, a.dtype.descr)
# all good so far
b = a[['x', 'i']] # for further processing I only need certain fields
print(b.shape, b.dtype, b.dtype.names, b.dtype.descr)
# you will only notice the extra padding in the descr
# b = np.lib.recfunctions.repack_fields(b)
# workaround
# now when I add fields, this becomes an issue
c = np.empty(b.shape, dtype=b.dtype.descr + [('c', 'i4')])
c[list(b.dtype.names)] = b
c['c'] = 1
print(c.dtype.names)
print(c['f1'])
# the void fields are filled with raw data and were given proper names
# that can be accessed
现在一种解决方法是使用numpy.lib.recfunctions.repack_fields,它会删除填充,我将来会使用它,但对于我之前的代码,我需要修复。 (虽然可以有issues 和recfunctions,因为可能找不到模块;对我来说就是这种情况,因此附加了import numpy.lib.recfunctions 语句。)
问题
这部分代码是我用来给数组添加字段的(基于this):
c = np.empty(b.shape, dtype=b.dtype.descr + [('c', 'i4')])
c[list(b.dtype.names)] = b
c['c'] = 1
虽然(现在我知道了)使用numpy.lib.recfunctions.require_fields 可能更适合添加字段。但是,我仍然需要一种方法来删除 b.dtype.descr 中的空字段:
[('x', '<f8'), ('', '|V8'), ('i', '<i8'), ('', '|V8')]
这只是tuples 的list,所以我想我可以构建一个或多或少尴尬的方式(沿着descr.remove(('', '|V8')))来处理这个问题,但我想知道是否有更好的方式,特别是因为空隙的大小取决于遗漏字段的数量,例如如果连续有两个,则从 V8 到 V16,依此类推(而不是每个遗漏字段都有一个新的 void)。所以代码会很快变得非常笨重。
【问题讨论】:
-
这个
padding不是免费的。具有字段子集的真正view仍然必须访问原始数据,因此它必须“知道”原始 dtype 布局repack使用自己的数据副本创建一个新数组。导入recfunctions是正常的 - 请参阅我最近的 SO 答案,stackoverflow.com/questions/69546473/… -
在制作新数组时,许多
recfunctions会编辑dtype、组合字段、选择字段等。因此使用descr中的元组是正常的。跨度> -
除了
repack和structured_to_unstructured等最近添加了1.16 更改需求的功能外,大部分recfunctions已经存在很长时间了。recarray可能继承自numpy的前身,尽管它在很大程度上被当前的dtype和structured array版本所取代。 -
您的第一条评论很有道理。虽然如果访问多个字段会创建一个
view,这是否意味着建议的便利功能here 已经过时了? -
你能详细说明为什么单独导入
recfunctions是正常的吗?我想我不明白。
标签: python numpy structured-array