Kon*_*ert 4 python arrays numpy
给定一个结构化的numpy数组,我想按名称删除某些列而不复制数组.我知道我可以这样做:
names = list(a.dtype.names)
if name_to_remove in names:
names.remove(name_to_remove)
a = a[names]
Run Code Online (Sandbox Code Playgroud)
但是这会创建一个我想避免的数组的临时副本,因为我正在处理的数组可能非常大.
有没有办法做到这一点?
您可以创建一个仅包含所需字段的新数据类型,具有相同的字段偏移量和与原始数组的数据类型相同的itemsize,然后使用此新数据类型创建原始数组的视图.该dtype函数处理多种格式的参数; 在"指定和构造数据类型"的文档部分中描述了相关的一个.向下滚动到以.开头的小节
{'names': ..., 'formats': ..., 'offsets': ..., 'titles': ..., 'itemsize': ...}
Run Code Online (Sandbox Code Playgroud)
这里有一些使用这个想法的便利功能.
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)
Run Code Online (Sandbox Code Playgroud)
例如,
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})
Run Code Online (Sandbox Code Playgroud)
通过更改来验证这b是一个视图(而不是副本)...ab[0]['x']
In [300]: b[0]['x'] = 3.14
Run Code Online (Sandbox Code Playgroud)
并看到它a也改变了:
In [301]: a[0]
Out[301]: (3.14, 13.5, 1248, -2)
Run Code Online (Sandbox Code Playgroud)