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 の配列に別の次元を追加します (この場合、2 つのテストがあったように見えるため、2x3 配列になります)。

itertoolsこれが解決策ですが、ご覧のとおり、非常に複雑で非効率的です。他の 2 つの方法のいずれかをお勧めします。

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

itertoolsview() を使用せずに、 に基づく少し高速でシンプルなソリューションは次のとおりです。

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

これは ecatmur と同じ考え方ですが、ソートの代わりに argsort() を使用するインデックスに関して機能します。

于 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 に答える