给定一个结构化的numpy数组,我想按名称删除某些列而不复制数组。 我知道我可以这样做:
names = list(a.dtype.names)
if name_to_remove in names:
names.remove(name_to_remove)
a = a[names]
但是这会创建一个我想避免的数组的临时副本,因为我正在处理的数组可能非常大。
有没有好办法呢?
答案 0 :(得分:5)
您可以创建一个仅包含所需字段的新数据类型,使用相同的字段偏移量和与原始数组的数据类型相同的itemsize,然后使用此新数据类型创建原始数组的视图。 dtype
函数处理多种格式的参数;相关的一个在名为"Specifying and constructing data types"的文档部分中描述。向下滚动到以
{'names': ..., 'formats': ..., 'offsets': ..., 'titles': ..., 'itemsize': ...}
以下是一些使用这种想法的便利功能。
import numpy as np
def view_fields(a, names):
"""
`a` must be a numpy structured array.
`names` is the collection of field names to keep.
Returns a view of the array `a` (not a copy).
"""
dt = a.dtype
formats = [dt.fields[name][0] for name in names]
offsets = [dt.fields[name][1] for name in names]
itemsize = a.dtype.itemsize
newdt = np.dtype(dict(names=names,
formats=formats,
offsets=offsets,
itemsize=itemsize))
b = a.view(newdt)
return b
def remove_fields(a, names):
"""
`a` must be a numpy structured array.
`names` is the collection of field names to remove.
Returns a view of the array `a` (not a copy).
"""
dt = a.dtype
keep_names = [name for name in dt.names if name not in names]
return view_fields(a, keep_names)
例如,
In [297]: a
Out[297]:
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')])
In [298]: b = remove_fields(a, ['i', 'j'])
In [299]: b
Out[299]:
array([(10.0, 13.5), (20.0, 0.0), (30.0, 0.0), (40.0, 0.0), (50.0, 0.0)],
dtype={'names':['x','y'], 'formats':['<f8','<f8'], 'offsets':[0,8], 'itemsize':32})
通过更改b
...
a
是b[0]['x']
的视图(不是副本)
In [300]: b[0]['x'] = 3.14
并且看到a
也发生了变化:
In [301]: a[0]
Out[301]: (3.14, 13.5, 1248, -2)