4

假设我有一个结构化的学生数组(字符串)和测试分数(整数),其中每个条目是特定学生在特定测试中获得的分数。自然,每个学生在这个数组中都有多个条目。

例子

import numpy
grades = numpy.array([('Mary', 96), ('John', 94), ('Mary', 88), ('Edgar', 89), ('John', 84)],
                     dtype=[('student', 'a50'), ('score', 'i')])

print grades
#[('Mary', 96) ('John', 94) ('Mary', 88) ('Edgar', 89) ('John', 84)]

如何轻松计算每个学生的平均分数?换句话说,我如何在“分数”维度中取数组的平均值?我想做

grades.mean('score')

并让 Numpy 返回

[('Mary', 92), ('John', 89), ('Edgar', 89)]

但 Numpy 抱怨

TypeError: an integer is required

有没有一种 Numpy 式的方法可以轻松做到这一点?我认为这可能涉及查看具有不同 dtype 的结构化数组。任何帮助,将不胜感激。谢谢。

编辑

>>> grades = numpy.zeros(5, dtype=[('student', 'a50'), ('score', 'i'), ('testid', 'i'])
>>> grades[0] = ('Mary', 96, 1)
>>> grades[1] = ('John', 94, 1)
>>> grades[2] = ('Mary', 88, 2)
>>> grades[3] = ('Edgar', 89, 1)
>>> grades[4] = ('John', 84, 2)
>>> np.mean(grades, 'testid')
TypeError: an integer is required
4

4 回答 4

4

NumPy 并非旨在将行分组在一起并将聚合函数应用于这些组。你可以:

  • 使用itertools.groupby和重建数组;
  • 使用Pandas,它基于 NumPy,擅长分组;或者
  • 为测试 id 的数组添加另一个维度(因此本例将是一个 2x3 数组,因为看起来有两个测试)。

这是itertools解决方案,但正如您所见,它非常复杂且效率低下。我会推荐其他两种方法中的一种。

np.array([(k, np.array(list(g), dtype=grades.dtype).view(np.recarray)['score'].mean())
          for k, g in groupby(np.sort(grades, order='student').view(np.recarray),
                              itemgetter('student'))], dtype=grades.dtype)
于 2012-08-16T14:30:23.867 回答
1

matplotlib.mlab.rec_groupby 正是我想要的。

于 2012-08-20T21:05:21.537 回答
0

itertools不使用 view()的基于 的更快和更简单的解决方案是

[(k,e['score'][list(g)].mean()) for k, g in groupby(argsort(e),e['student'].__getitem__ )]

这与 ecatmur 的想法相同,但在使用 argsort() 而不是 sort 的索引方面起作用。

于 2012-08-16T17:55:01.163 回答
0

collapseByField(grades,'student') 给出你想要的,之后:

def collapseByField(e,collapsefield,keepFields=None,agg=None):
   import numpy as np
   assert isinstance(e,np.ndarray) # Structured array
   if agg is None:
       agg=np.mean
   if keepFields is None:
       newf=[(n,agg,n) for n in e.dtype.names if n not in (collapsefield)]
   import matplotlib as mpl
   return(mpl.mlab.rec_groupby(e,[collapsefield],newf))
于 2012-10-20T19:20:32.013 回答