Среднее количество структурированных массивов

Предположим, что у меня есть структурированный массив студентов (строк) и тестов (ints), где каждая запись – это оценка, которую конкретный ученик получил по конкретному тесту. Естественно, каждый студент имеет несколько записей в этом массиве.

пример

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-esque сделать это легко? Я думаю, что это может быть связано с представлением структурированного массива с другим 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 

  • Выбирайте самые дальние k точек из заданных n точек
  • numpy max vs amax против максимума
  • Могу ли я сохранить массив numpy в виде 16-битного изображения, используя «обычный» (Enthought) python?
  • Как получить прогноз теста из 2D-параметров регрессии WLS в статистических моделях
  • Почему numpy массивы не могут конвертировать из datetime в np.datetime64 неявно?
  • Что делает matplotlib `imshow (интерполяция = 'ближайший')` делать?
  • Cython: Должен ли я использовать np.float_t вместо двойного для типизированных видов памяти
  • Назначить массив, добавив несколько копий индекса
  • 4 Solutions collect form web for “Среднее количество структурированных массивов”

    NumPy не предназначен для группировки строк и применения агрегатных функций к этим группам. Ты мог:

    • используйте itertools.groupby и восстановите массив;
    • используйте Pandas , который основан на NumPy и отлично подходит для группировки; или
    • добавьте другое измерение в массив для идентификатора теста (так что этот случай будет массивом 2×3, потому что похоже, что было два теста).

    Вот решение 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) 

    matplotlib.mlab.rec_groupby был именно тем, что я искал.

    Несколько быстрее и проще решение на основе itertools , без использования view (), является

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

    Это та же идея ecatmur, но работает с точки зрения индексов, использующих argsort () вместо сортировки.

    collapseByField (оценки, «ученик») дает то, что вы хотите, после:

     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)) 
    Python - лучший язык программирования в мире.