根据一列的值分割numpy recarray

0 投票
1 回答
1146 浏览
提问于 2025-04-18 08:06

我的真实数据有一万多个项目。我有一个复杂的numpy记录数组,格式大致如下:

a = (((1., 2., 3.), 4., 'metadata1'), 
     ((1., 3., 5.), 5., 'metadata1'), 
     ((1., 2., 4.), 5., 'metadata2'),
     ((1., 2., 5.), 5., 'metadata2'),  
     ((1., 3., 8.), 5., 'metadata3'))

我的列是通过 dtype = [('coords', '3f4'), ('values', 'f4'), ('meta', 'S10')] 定义的。我通过执行 set(a['meta']) 来获取所有可能的meta值的列表。

我想根据'meta'列将数据分成更小的列表。理想情况下,我希望得到这样的结果:

a['metadata1'] == (((1., 2., 3.), 4.), ((1., 3., 5.), 5.))
a['metadata2'] == (((1., 2., 4.), 5.), ((1., 2., 5.), 5.))
a['metadata3'] == (((1., 3., 8.), 5.))

或者

a[0] = (((1., 2., 3.), 4., 'metadata1'), ((1., 3., 5.), 5., 'metadata1'))
a[1] = (((1., 2., 4.), 5., 'metadata2'), ((1., 2., 5.), 5., 'metadata2'))
a[2] = (((1., 3., 8.), 5., 'metadata3'))

或者任何其他方便拆分的格式。

不过,对于大数据集来说,前一种方式在内存使用上更好。有没有什么想法可以实现这种拆分?我看到这里有一些其他问题,但它们都是在测试数值。

1 个回答

2

你可以通过一种叫做“花式索引”的方法轻松访问那些行:

In [34]: a[a['meta']=='metadata2']
Out[34]: 
rec.array([(array([ 1.,  2.,  4.], dtype=float32), 5.0, 'metadata2'),
           (array([ 1.,  2.,  5.], dtype=float32), 5.0, 'metadata2')], 
          dtype=[('coords', '<f4', (3,)), ('values', '<f4'), ('meta', 'S10')])

你可以用这种方法为不同的元类型创建一个查找字典:

meta_dict = {}
for meta_type in np.unique(a['meta']):
    meta_dict[meta_type] = a[a['meta']==meta_type]

如果元类型很多,这种方法会非常低效。

一个更有效的解决方案是考虑使用Pandas的数据框。它们有一个分组功能,正好可以完成你所描述的任务。

撰写回答