将二维数组(字段)添加到 numpy recarray
Add a 2d array(field) to a numpy recarray
我想使用 numpy.lib.recfunctions.append_fields
将 2D 字段添加到现有的重新排列。
假设我做了一个重新排列。
> arr = np.recarray(10, [("afield", "<f8"), ('pos', '<f8', (3,))])
> arr.dtype
dtype((numpy.record, [('afield', '<f8'), ('pos', '<f8', (3,))]))
我想添加一个字段,使 arr 看起来像:
> arr.dtype
dtype((numpy.record, [('afield', '<f8'), ('pos', '<f8', (3,)), ('vel', '<f8', (3,))]))
我不确定要传递给 dtypes= 参数的内容。
我尝试了 dtypes =np.dtype("f8",(3,)) 但没有成功。
> from numpy.lib.recfunctions import append_fields
> data = arr["pos"][:]
> new_arr = append_fields(arr, 'vel', data, dtypes =np.dtype("f8",(3,)),usemask=False)
ValueError: could not broadcast input array from shape (10,3) into shape (10)
或者,如果我传递一个单元素列表,我会得到另一个错误。
> new_arr = append_fields(arr, 'vel', data, dtypes =[("f8",(3,))],usemask=False)
ValueError: could not broadcast input array from shape (10,3) into shape (10,3,3)
我想要(10,3)
的形状,但我只能得到(10,)
或(10,3,3)
。
这是朝着正确方向迈出的一步:
data = arr['pos']
data = np.ascontiguousarray(data) # next line fails otherwise - bug?
data = data.view([('vel', (np.float, 3))])
data = data.reshape(data.shape[:-1]) # view doesn't ever remove a dimension
assert data.shape == (10,)
不幸的是,当您现在这样做时:
new_arr = append_fields(arr, 'vel', data,usemask=False)
你最终得到 new_arr['vel']['vel']
append_fields
和大多数其他 recarray
函数创建一个新的 dtype
和一个 empty
数组,然后按名称从结果的原件。
我将用结构化数组来说明
原始数据类型和数组:
In [102]: dt=np.dtype([('afield','f'),('pos','f',(3,))])
In [103]: dt
Out[103]: dtype([('afield', '<f4'), ('pos', '<f4', (3,))])
In [104]: arr = np.ones((3,),dtype=dt)
In [105]: arr
Out[105]:
array([(1.0, [1.0, 1.0, 1.0]), (1.0, [1.0, 1.0, 1.0]),
(1.0, [1.0, 1.0, 1.0])],
dtype=[('afield', '<f4'), ('pos', '<f4', (3,))])
修改后的数据类型:
In [106]: dt1=np.dtype([('afield','f'),('pos','f',(3,)),('vel','f',(2,))])
In [107]: arr1 = np.empty((3,),dtype=dt1)
In [108]: arr1
Out[108]:
array([(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])],
dtype=[('afield', '<f4'), ('pos', '<f4', (3,)), ('vel', '<f4', (2,))])
In [109]: for name in dt.names:
.....: arr1[name] = arr[name]
In [110]: arr1
Out[110]:
array([(1.0, [1.0, 1.0, 1.0], [0.0, 0.0]),
(1.0, [1.0, 1.0, 1.0], [0.0, 0.0]),
(1.0, [1.0, 1.0, 1.0], [0.0, 0.0])],
dtype=[('afield', '<f4'), ('pos', '<f4', (3,)), ('vel', '<f4', (2,))])
recarray
是同一件事,但能够将字段作为属性访问 (arr.pos
)。
添加一个简单的整数字段:
In [118]: rf.append_fields(arr, 'vel', np.arange(3),usemask=False)
Out[118]:
array([(1.0, [1.0, 1.0, 1.0], 0), (1.0, [1.0, 1.0, 1.0], 1),
(1.0, [1.0, 1.0, 1.0], 2)],
dtype=[('afield', '<f4'), ('pos', '<f4', (3,)), ('vel', '<i4')])
对于 (2,) 字段,我在 recursive_fill
步骤中遇到错误。通过适当的输入,我可以用它来填充我的 dt1
数组:
In [206]: arr = np.ones((3,),dtype=dt)
In [207]: arr1 = np.zeros((3,),dtype=dt1)
In [208]: rf.recursive_fill_fields(arr,arr1)
Out[208]:
array([(1.0, [1.0, 1.0, 1.0], [0.0, 0.0]),
(1.0, [1.0, 1.0, 1.0], [0.0, 0.0]),
(1.0, [1.0, 1.0, 1.0], [0.0, 0.0])],
dtype=[('afield', '<f4'), ('pos', '<f4', (3,)), ('vel', '<f4', (2,))])
In [210]: x = np.ones((3,),dtype=[('vel','f',(2,))])
In [211]: x['vel'] *= 2
In [212]: rf.recursive_fill_fields(x,arr1)
Out[212]:
array([(1.0, [1.0, 1.0, 1.0], [2.0, 2.0]),
(1.0, [1.0, 1.0, 1.0], [2.0, 2.0]),
(1.0, [1.0, 1.0, 1.0], [2.0, 2.0])],
dtype=[('afield', '<f4'), ('pos', '<f4', (3,)), ('vel', '<f4', (2,))])
现在在 append_fields
中尝试 x
:
In [213]: rf.append_fields(arr, 'vel', x, usemask=False)
Out[213]:
array([(1.0, [1.0, 1.0, 1.0], ([2.0, 2.0],)),
(1.0, [1.0, 1.0, 1.0], ([2.0, 2.0],)),
(1.0, [1.0, 1.0, 1.0], ([2.0, 2.0],))],
dtype=[('afield', '<f4'), ('pos', '<f4', (3,)), ('vel', [('vel', '<f4', (2,))])])
糟糕 - 我正在获取一个嵌套字段。回到我原来的例子——创建目标并按名称填充它。
merge_arrays
效果更好 - 使用 flatten
In [247]: rf.merge_arrays((arr,x),flatten=True)
Out[247]:
array([(1.0, [1.0, 1.0, 1.0], [2.0, 2.0]),
(1.0, [1.0, 1.0, 1.0], [2.0, 2.0]),
(1.0, [1.0, 1.0, 1.0], [2.0, 2.0])],
dtype=[('afield', '<f4'), ('pos', '<f4', (3,)), ('vel', '<f4', (2,))])
为该新字段创建适当数组的另一种方法
In [248]: dx = [('f0','f',(2,))]
In [250]: y=np.zeros((3,), dtype=dx)
In [251]: y['f0'] = np.arange(6.).reshape(3,2)
创建和填充通常似乎是制作这些复杂结构化数组的最佳方式。
我想使用 numpy.lib.recfunctions.append_fields
将 2D 字段添加到现有的重新排列。
假设我做了一个重新排列。
> arr = np.recarray(10, [("afield", "<f8"), ('pos', '<f8', (3,))])
> arr.dtype
dtype((numpy.record, [('afield', '<f8'), ('pos', '<f8', (3,))]))
我想添加一个字段,使 arr 看起来像:
> arr.dtype
dtype((numpy.record, [('afield', '<f8'), ('pos', '<f8', (3,)), ('vel', '<f8', (3,))]))
我不确定要传递给 dtypes= 参数的内容。 我尝试了 dtypes =np.dtype("f8",(3,)) 但没有成功。
> from numpy.lib.recfunctions import append_fields
> data = arr["pos"][:]
> new_arr = append_fields(arr, 'vel', data, dtypes =np.dtype("f8",(3,)),usemask=False)
ValueError: could not broadcast input array from shape (10,3) into shape (10)
或者,如果我传递一个单元素列表,我会得到另一个错误。
> new_arr = append_fields(arr, 'vel', data, dtypes =[("f8",(3,))],usemask=False)
ValueError: could not broadcast input array from shape (10,3) into shape (10,3,3)
我想要(10,3)
的形状,但我只能得到(10,)
或(10,3,3)
。
这是朝着正确方向迈出的一步:
data = arr['pos']
data = np.ascontiguousarray(data) # next line fails otherwise - bug?
data = data.view([('vel', (np.float, 3))])
data = data.reshape(data.shape[:-1]) # view doesn't ever remove a dimension
assert data.shape == (10,)
不幸的是,当您现在这样做时:
new_arr = append_fields(arr, 'vel', data,usemask=False)
你最终得到 new_arr['vel']['vel']
append_fields
和大多数其他 recarray
函数创建一个新的 dtype
和一个 empty
数组,然后按名称从结果的原件。
我将用结构化数组来说明
原始数据类型和数组:
In [102]: dt=np.dtype([('afield','f'),('pos','f',(3,))])
In [103]: dt
Out[103]: dtype([('afield', '<f4'), ('pos', '<f4', (3,))])
In [104]: arr = np.ones((3,),dtype=dt)
In [105]: arr
Out[105]:
array([(1.0, [1.0, 1.0, 1.0]), (1.0, [1.0, 1.0, 1.0]),
(1.0, [1.0, 1.0, 1.0])],
dtype=[('afield', '<f4'), ('pos', '<f4', (3,))])
修改后的数据类型:
In [106]: dt1=np.dtype([('afield','f'),('pos','f',(3,)),('vel','f',(2,))])
In [107]: arr1 = np.empty((3,),dtype=dt1)
In [108]: arr1
Out[108]:
array([(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])],
dtype=[('afield', '<f4'), ('pos', '<f4', (3,)), ('vel', '<f4', (2,))])
In [109]: for name in dt.names:
.....: arr1[name] = arr[name]
In [110]: arr1
Out[110]:
array([(1.0, [1.0, 1.0, 1.0], [0.0, 0.0]),
(1.0, [1.0, 1.0, 1.0], [0.0, 0.0]),
(1.0, [1.0, 1.0, 1.0], [0.0, 0.0])],
dtype=[('afield', '<f4'), ('pos', '<f4', (3,)), ('vel', '<f4', (2,))])
recarray
是同一件事,但能够将字段作为属性访问 (arr.pos
)。
添加一个简单的整数字段:
In [118]: rf.append_fields(arr, 'vel', np.arange(3),usemask=False)
Out[118]:
array([(1.0, [1.0, 1.0, 1.0], 0), (1.0, [1.0, 1.0, 1.0], 1),
(1.0, [1.0, 1.0, 1.0], 2)],
dtype=[('afield', '<f4'), ('pos', '<f4', (3,)), ('vel', '<i4')])
对于 (2,) 字段,我在 recursive_fill
步骤中遇到错误。通过适当的输入,我可以用它来填充我的 dt1
数组:
In [206]: arr = np.ones((3,),dtype=dt)
In [207]: arr1 = np.zeros((3,),dtype=dt1)
In [208]: rf.recursive_fill_fields(arr,arr1)
Out[208]:
array([(1.0, [1.0, 1.0, 1.0], [0.0, 0.0]),
(1.0, [1.0, 1.0, 1.0], [0.0, 0.0]),
(1.0, [1.0, 1.0, 1.0], [0.0, 0.0])],
dtype=[('afield', '<f4'), ('pos', '<f4', (3,)), ('vel', '<f4', (2,))])
In [210]: x = np.ones((3,),dtype=[('vel','f',(2,))])
In [211]: x['vel'] *= 2
In [212]: rf.recursive_fill_fields(x,arr1)
Out[212]:
array([(1.0, [1.0, 1.0, 1.0], [2.0, 2.0]),
(1.0, [1.0, 1.0, 1.0], [2.0, 2.0]),
(1.0, [1.0, 1.0, 1.0], [2.0, 2.0])],
dtype=[('afield', '<f4'), ('pos', '<f4', (3,)), ('vel', '<f4', (2,))])
现在在 append_fields
中尝试 x
:
In [213]: rf.append_fields(arr, 'vel', x, usemask=False)
Out[213]:
array([(1.0, [1.0, 1.0, 1.0], ([2.0, 2.0],)),
(1.0, [1.0, 1.0, 1.0], ([2.0, 2.0],)),
(1.0, [1.0, 1.0, 1.0], ([2.0, 2.0],))],
dtype=[('afield', '<f4'), ('pos', '<f4', (3,)), ('vel', [('vel', '<f4', (2,))])])
糟糕 - 我正在获取一个嵌套字段。回到我原来的例子——创建目标并按名称填充它。
merge_arrays
效果更好 - 使用 flatten
In [247]: rf.merge_arrays((arr,x),flatten=True)
Out[247]:
array([(1.0, [1.0, 1.0, 1.0], [2.0, 2.0]),
(1.0, [1.0, 1.0, 1.0], [2.0, 2.0]),
(1.0, [1.0, 1.0, 1.0], [2.0, 2.0])],
dtype=[('afield', '<f4'), ('pos', '<f4', (3,)), ('vel', '<f4', (2,))])
为该新字段创建适当数组的另一种方法
In [248]: dx = [('f0','f',(2,))]
In [250]: y=np.zeros((3,), dtype=dx)
In [251]: y['f0'] = np.arange(6.).reshape(3,2)
创建和填充通常似乎是制作这些复杂结构化数组的最佳方式。