Numpy对结构化数组中的组应用函数

2024-04-27 05:00:36 发布

您现在位置:Python中文网/ 问答频道 /正文

从一个有4个字段的结构化numpy数组开始,我试图返回一个包含相同4个字段的最新日期的数组。我找到了一个使用itertools.groupby的解决方案,它几乎可以在这里工作: Numpy Mean Structured Array

问题是当你有4个字段而不是2个字段时,我不知道如何调整它。我想取回整个“行”,但只获取每个ID的最新日期的行。我知道使用pandas进行这种操作比较简单,但这只是一个更大过程的一小部分,我不能将pandas添加为依赖项。在

data = np.array([('2005-02-01', 1, 3, 8),
             ('2005-02-02', 1, 4, 9),
             ('2005-02-01', 2, 5, 10),
             ('2005-02-02', 2, 6, 11),
             ('2005-02-03', 2, 7, 12)], 
             dtype=[('dt', 'datetime64[D]'), ('ID', '<i4'), ('f3', '<i4'),    
             ('f4', '<i4')])

对于这个示例数组,我想要的输出是:

^{pr2}$

这就是我尝试过的:

latest = np.array([(k, np.array(list(g), dtype=data.dtype).view(np.recarray)
              ['dt'].argmax()) for k, g in 
              groupby(np.sort(data, order='ID').view(np.recarray),
              itemgetter('ID'))], dtype=data.dtype)

我得到这个错误:

ValueError: size of tuple must match number of fields.

我想这是因为元组有2个字段,而数组有4个字段。当我从数组中删除'f3''f4'时,它可以正常工作。在

如何让它返回所有4个字段?在


Tags: ofviewidpandasdatanpdt数组
1条回答
网友
1楼 · 发布于 2024-04-27 05:00:36

让我们来找出你的错误在哪里,从一个层次:

In [38]: from operator import itemgetter
In [39]: from itertools import groupby
In [41]: [(k, np.array(list(g), dtype=data.dtype).view(np.recarray)
          ['dt'].argmax()) for k, g in 
          groupby(np.sort(data, order='ID').view(np.recarray),
          itemgetter('ID'))]
Out[41]: [(1, 1), (2, 2)]

这个元组列表应该代表什么?它显然不是data中的行。由于每个元组只有2个项,所以不能映射到data.dtype数组上。因此出现了数值误差。在


在考虑了一下这个问题之后,我想:[(1, 1), (2, 2)]意味着,对于ID==1,使用组中的[1]项;对于ID==2,使用组中的[2]项。在

^{pr2}$

您已经找到了最大日期,但是您必须将其转换为data中的索引,或者从组中选择这些项目。在

In [91]: groups=groupby(np.sort(data, order='ID').itemgetter('ID'))
# don't need recarray

In [92]: G = [(k,list(g)) for k,g in groups]

In [93]: G
Out[93]: 
[(1,
  [(datetime.date(2005, 2, 1), 1, 3, 8),
   (datetime.date(2005, 2, 2), 1, 4, 9)]),
 (2,
  [(datetime.date(2005, 2, 1), 2, 5, 10),
   (datetime.date(2005, 2, 2), 2, 6, 11),
   (datetime.date(2005, 2, 3), 2, 7, 12)])]
In [107]: I=[(1,1), (2,2)]

In [108]: [g[1][i[1]] for g,i in zip(G,I)]
Out[108]: [(datetime.date(2005, 2, 2), 1, 4, 9), (datetime.date(2005, 2, 3), 2, 7, 12)]

好吧,从G中选择的内容很笨拙,但这只是一个开始。在


如果我定义一个简单的函数从一个组中提取具有最新日期的记录,则处理过程要简单得多。在

def maxdate_record(agroup):
    an_array = np.array(list(agroup))
    i = np.argmax(an_array['dt'])
    return an_array[i]

groups = groupby(np.sort(data, order='ID'),itemgetter('ID'))
np.array([maxdate_record(g) for k,g in groups])

制作:

array([(datetime.date(2005, 2, 2), 1, 4, 9),
       (datetime.date(2005, 2, 3), 2, 7, 12)], 
      dtype=[('dt', '<M8[D]'), ('ID', '<i4'), ('f3', '<i4'), ('f4', '<i4')])

当我将记录列表转换为数组时,不需要指定dtype,因为这些记录有自己的数据类型。在

相关问题 更多 >