ndarray имена полей для строки и столбца? - PullRequest
7 голосов
/ 12 октября 2010

Я учитель информатики, пытаюсь создать для себя небольшой дневник с помощью NumPy.Но я думаю, что было бы проще написать мой код, если бы я мог создать ndarray, который использует имена полей как для строк, так и для столбцов.Вот что у меня получилось:

import numpy as np
num_stud = 23
num_assign = 2
grades = np.zeros(num_stud, dtype=[('assign 1','i2'), ('assign 2','i2')]) #etc
gv = grades.view(dtype='i2').reshape(num_stud,num_assign)

Итак, если мой первый ученик получил 97 на «задании 1», я могу написать либо:

grades[0]['assign 1'] = 97
gv[0][0] = 97

Также,Я могу сделать следующее:

np.mean( grades['assign 1'] ) # class average for assignment 1
np.sum( gv[0] ) # total points for student 1

Это все работает.Но то, что я не могу выяснить, как это сделать, это использовать идентификационный номер студента для ссылки на конкретного студента (предположим, что у двух моих студентов есть идентификаторы студентов, как показано):

grades['123456']['assign 2'] = 95
grades['314159']['assign 2'] = 83

... или, может быть, создать второе представление с разными именами полей?

np.sum( gview2['314159'] ) # total points for the student with the given id

Я знаю, что мог бы создать тождественное отображение идентификаторов учеников на индексы, но это кажется хрупким и грубым, и я 'Я надеюсь, что есть лучший способ, чем:

id2i = { '123456': 0, '314159': 1 }
np.sum( gv[ id2i['314159'] ] )

Я также готов перестроить вещи, если есть более чистый дизайн.Я новичок в NumPy, и я еще не написал много кода, так что начинать сначала не исключено, если я делаю это неправильно.

I am собираетсянеобходимость суммировать все баллы заданий для более ста учеников один раз в день, а также выполнять стандартные отклонения и другие статистические данные.Кроме того, я буду ждать результатов, поэтому я хотел бы, чтобы он запустился всего за пару секунд.

Заранее благодарен за любые предложения.

Ответы [ 3 ]

11 голосов
/ 12 октября 2010

По вашему описанию, вам лучше использовать другую структуру данных, чем стандартный массив numpy. ndarray не очень подходят для этого ... Они не электронные таблицы.

Однако в последнее время была проведена обширная работа над типом массива numpy, который является , хорошо подходящим для этого использования. Вот описание недавней работы над DataArrays. Хотя пройдет какое-то время, прежде чем это полностью войдет в состав NumPy ...

Один из проектов, на которых будет основан (вроде) предстоящий numpy DataArrays, - "larry" (Сокращение от "Labeled Array"). Этот проект звучит как то, что вы хотите сделать ... (Именуйте строки и столбцы, но в остальном действуйте прозрачно, как пустой массив.) Он должен быть достаточно стабильным для использования (и из-за моей ограниченной игры с ним, это довольно гладко!) но имейте в виду, что он, вероятно, будет в конечном итоге заменен встроенным классом numpy.

Тем не менее, вы можете использовать тот факт, что (простая) индексация пустого массива возвращает представление в этот массив и создает класс, который обеспечивает оба интерфейса ...

В качестве альтернативы, предложение @ unutbu выше - это другой (более простой и прямой) способ справиться с ним, если вы решите бросить свой собственный.

7 голосов
/ 12 октября 2010

Для ввода и хранения данных я бы использовал реляционную базу данных (например, sqlite, MySQL или Postgresql).Если вы делаете это таким образом, вы можете легко написать несколько программ, которые анализируют данные по-разному.Доступ к самой базе данных sqlite возможен из различных языков программирования, интерфейсов GUI / CLI.Ваши данные останутся независимыми от языка (в отличие от хранения пустых массивов).

Python имеет встроенную поддержку sqlite .

SQL предоставляет удобный, читаемый язык для нарезки и нарезания кубиков ваших данных (например, «Каковы все оценки за назначение 1 из класса 1? Дайте список из 10 самых высоких оценок. У кого были эти оценки?выше среднего, чем для class2?) Таблицы базы данных могут вместить несколько классов, несколько семестров.

Для ввода данных может быть наиболее удобным графический интерфейс. Для sqlite есть sqlitebrowser (у меня не так многоХотя здесь есть опыт; могут быть даже лучшие варианты.). Для MySQL мне нравится phpmyadmin, а для Postgresql - phppgadmin.

После ввода данных вы можете использовать модуль Python (например, sqlite3, MySQLdb,pyscopg2) для доступа к базе данных и выдачи SQL-запросов. Затем данные могут быть переданы в список или массив numpy. Затем можно использовать numpy для вычисления статистики.

PS. Для небольших наборов данных действительно нет проблемотносительно скорости или объема памяти. Вам не нужно хранить данные в массиве Numpy только для вызова NUMPСтатистические функции y / scipy.

Вы можете, например, вытянуть данные из базы данных в список Python и передать список Python в функцию numpy:

sql='SELECT * FROM grades WHERE assignment=%s'
args=['assign1']
data=cursor.fetchall(sql,args)
scores=zip(*data)[0]   
ave_score=np.mean(scores)

Если оценки - это простой структурный массив, вы никогда не сможете получить доступ к значениям следующим образом:

grades['123456']['assign 2']

, поскольку столбцы доступны по имени, а строки - целые числа.

Я не думаю, что это создает большие препятствия.И вот почему: все, что вы хотите сделать для одного студента (например, найти сумму всех баллов назначения), вы, вероятно, захотите сделать для каждого студента.

Так что трюк с numpy- способ использовать его мощность - это писать векторизованные уравнения или использовать простые функции, которые применяются ко всем строкам одновременно, вместо того, чтобы циклически проходить по строкам по отдельности.Вместо того, чтобы думать в индивидуальном масштабе (например, отдельные студенты, индивидуальные задания), NumPy побуждает вас думать в более широком масштабе (например, все студенты, все задания) и выполнять вычисления, которыепримените ко всем из них одновременно.

Как вы уже видели, когда вы спорили с представлениями, на самом деле вам лучше не использовать структурированный массив, а вместо этого выбрать простой 2-осевой массив Numpy:

Давайте представим, что столбцы представляют (2) задания, а строки представляют (4) учащихся.

In [36]: grades=np.random.random((4,2))

In [37]: grades
Out[37]: 
array([[ 0.42951657,  0.81696305],
       [ 0.2298493 ,  0.05389136],
       [ 0.12036423,  0.78142328],
       [ 0.5029192 ,  0.75186565]])

Вот некоторые статистические данные:

In [38]: sum_of_all_assignments = grades.sum(axis=1)

In [39]: sum_of_all_assignments
Out[39]: array([ 1.24647962,  0.28374066,  0.90178752,  1.25478485])

In [40]: average_of_all_assignments = grades.mean(axis=1)

In [41]: average_of_all_assignments
Out[41]: array([ 0.62323981,  0.14187033,  0.45089376,  0.62739242])

In [42]: average_assignment_score = grades.mean(axis=0)

In [43]: average_assignment_score 
Out[43]: array([ 0.32066233,  0.60103583])

Теперь предположим, что это именаучеников:

In [44]: student_names=['harold','harry','herb','humphrey']

Чтобы сопоставить имена учеников с их средним баллом, вы можете создать dict

In [45]: dict(zip(student_names,average_of_all_assignments))
Out[45]: 
{'harold': 0.62323981076528523,
 'harry': 0.14187032892653173,
 'herb': 0.45089375919011698,
 'humphrey': 0.62739242488169067}

И аналогично для заданий:

In [46]: assignment_names=['assign 1','assign 2']

In [47]: dict(zip(assignment_names,average_assignment_score))
Out[47]: {'assign 1': 0.32066232713749887, 'assign 2': 0.60103583474431344}
4 голосов
/ 16 сентября 2013

Вы должны посмотреть на модуль панд, который делает именно то, что вам нужно.http://pandas.pydata.org

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...