Категоризация данных, вычисление среднего и стандартного отклонения для каждой категории
Я пишу код для классификации данных и получения среднего и стандартного отклонения. Вот пример моих данных.
3917 1 -0.662261 25.148 22.9354 68.8076
3918 1 12.7649 18.7451 7.68473 69.0063
3919 1 -9.56836 -23.3265 -61.953 68.8357
3920 1 11.6292 31.6525 -29.3697 69.1372
3921 2 26.4837 -66.7897 12.0257 69.2282
3922 1 -9.81652 14.3788 9.38343 69.1217
3923 2 39.931 -88.1879 109.498 69.1604
3924 1 4.5502 3.53887 -6.59604 69.486
3925 2 13.6801 -24.6628 -5.7568 69.9398
3926 1 -10.5635 7.05517 -8.82785 70.2263
Как видите, есть 6 столбцов. Я думаю о трехэтапном расчете здесь.
Распределите эти числа по 6-му столбцу. 6-й столбец состоит из чисел с плавающей точкой от 0 до n. Я надеюсь сгенерировать n секций (или субматриц, или что-то еще), например, 0~1, 1~2, 2~3 .... n-1 ~ n. Последнее число должно быть округлено до числа последних данных, потому что я надеюсь сделать разделы. Например, если последнее число - 121.2513, последний раздел должен содержать 120~121, чтобы содержать эти данные.
Перераспределите все остальные номера столбца 1~5 в соответствующие им подразделы на основе 6-го столбца. Если в определенных разделах нет номера, просто выведите его как 0. Количество подразделов будет n. Количество элементов в каждом подразделе будет случайным.
Получите среднее и стандартное отклонение 3-го, 4-го и 5-го столбца для каждого подраздела и запишите в выходной файл "количество элементов в подразделе, начальный номер подраздела, а также среднее и стандартное отклонение 3-го, 4-го и 5-го" столбец"
Я пытался это с несколькими циклами for, но это стало слишком сложным, и делает ошибку. Есть ли другой простой способ классифицировать данные, поиграть с каждым подразделом и распечатать их на Python? Кроме того, мои циклы for не работают вообще. Какой-нибудь простой пример предложения с использованием этих данных?
3 ответа
Эта задача поддается библиотеке панд. ( http://pandas.pydata.org/) Из того, что я понял из вашего поста, вы хотели вычислить среднее значение по столбцам и стандартные отклонения. Чтобы вычислить статистику по строкам, добавьте параметр, axis=1
к среднему и стандартным функциям. В приведенном ниже коде пример был сохранен в "tmp.txt". Первый шаг загружает его, затем просто вычислить статистику по фрейму данных.
import pandas as pd
df =pd.read_csv('tmp.txt',sep=' ',header=None)
means = df.mean()
stds = df.std()
Для получения дополнительной информации о пандах, посмотрите на краткое введение: http://pandas.pydata.org/pandas-docs/stable/10min.html
Я предполагаю, что у вас есть матрица в списке списков, и покажу вам, как начать. (Однако, как я уже упоминал в комментарии, если у вас была матрица в клочке array
или же matrix
было бы намного проще - и быстрее тоже.)
Если у вас просто есть это значение в виде большой многострочной строки, вы можете преобразовать его в список списков с плавающей точкой, например:
m = [[float(col) for col in line.split()] for line in s.splitlines()]
Теперь, "категоризовав эти числа на основе 6-го столбца", вы услышите, что вы хотите сгруппировать их по целому значению этого столбца.
Python поставляется с groupby
функция, которая делает большую часть того, что вы хотите здесь, но вы должны сначала отсортировать данные.
В Python сортировка, группировка и связанные функции всегда позволяют передавать ключевую функцию. Вам не нужно сортировать и группировать 6-й столбец, вы можете сортировать и группировать всю строку, используя 6-й столбец в качестве ключа.
Но на самом деле вы не хотите использовать значение 6-го столбца в качестве ключа, вы хотите использовать целочисленное значение 6-го столбца. Для первого вы бы использовали itemgetter
функция, которая входит в stdlib, но чтобы сделать что-то более сложное, лучше написать для нее функцию:
def keyfunc(row):
return int(row[5])
groups = groupby(sorted(data, key=keyfunc), key=keyfunc)
(Если вы делаете это неоднократно, вы, вероятно, захотите написать функцию-обертку, которая сортирует, а затем группирует с одним и тем же ключом, поэтому вам не нужно повторяться и ошибаться.)
Это дает вам итератор с итераторами внутри, который немного сложно распечатать:
[(k, list(g)) for k, g in groups]
... но то, что вы получаете:
[(68,
[[3917.0, 1.0, -0.662261, 25.148, 22.9354, 68.8076],
[3919.0, 1.0, -9.56836, -23.3265, -61.953, 68.8357]]),
(69,
[[3918.0, 1.0, 12.7649, 18.7451, 7.68473, 69.0063],
[3920.0, 1.0, 11.6292, 31.6525, -29.3697, 69.1372],
[3921.0, 2.0, 26.4837, -66.7897, 12.0257, 69.2282],
[3922.0, 1.0, -9.81652, 14.3788, 9.38343, 69.1217],
[3923.0, 2.0, 39.931, -88.1879, 109.498, 69.1604],
[3924.0, 1.0, 4.5502, 3.53887, -6.59604, 69.486],
[3925.0, 2.0, 13.6801, -24.6628, -5.7568, 69.9398]]),
(70, [[3926.0, 1.0, -10.5635, 7.05517, -8.82785, 70.2263]])]
Итак, каждый k
целое число, по которому сгруппирована категория, и каждый g
это все строки в этой категории (в отсортированном порядке).
(Обратите внимание, что, потому что groups
является итератором, если вы print
этот, groups
теперь будет пусто.)
И это заботится о вашей первой проблеме, и я думаю, что большинство вашей второй (я не уверен, что именно вы хотели там).
Для третьего, сначала вам нужно перебрать группы:
for k, g in groups:
Если вы собираетесь зацикливаться на группе несколько раз, вы хотите сразу составить список, а затем зациклить этот список.
Для каждой группы вы хотите сделать некоторые статистические вещи для нескольких столбцов. Самый простой способ сделать это - использовать модуль, который позаботится обо всей математике за вас. stats
Модуль на PyPI - хорошая ставка, особенно теперь, когда (с небольшими изменениями) он, вероятно, попадет в стандартную библиотеку для будущей версии Python.
Но я просто покажу среднее, потому что это тривиально.
Так:
def mean(sequence):
return sum(sequence) / len(sequence)
for k, g in groups:
rows = list(g)
print(k)
for column_index in 2, 3, 4:
column = [row[column_index] for row in rows]
print(mean(column))
Вероятно, многое из того, что этот код не делает того, что вам нужно, но, надеюсь, этого достаточно, чтобы начать работу и задавать более конкретные вопросы, когда вы застряли.
Как уже говорили другие, вы можете захотеть взглянуть на numpy или pandas, особенно если ваш набор данных огромен. Но эту задачу легко достичь и на чистом питоне, используя правильные структуры данных. В этом случае я бы просто использовал defaultdict для разделов, ключом которого является 6-й столбец, округленный в меньшую сторону, который сопоставляется с кортежем списков (или более сложной структурой данных), в которой вы можете затем собрать значения столбцов:
from collections import defaultdict
sections = defaultdict(lambda: ([], [], [], [], []))
with open("mydata.txt") as f:
#parse all non-empty lines into a list of lists of floats
lines = [x.strip() for x in f.read().split("\n")]
data = [map(float, x.split(" ")) for x in lines if x]
for row in data:
#get the corresponding section (and create it if it doesn't exist)
section = sections[int(row[5])]
for x in range(5):
#append the column values to the respective lists
section[x].append(row[x])
Сейчас sections
содержит данные в удобном для использования формате; просто переберите его и вычислите среднее и стандартное отклонение интересующих вас строк:
for s, columns in sections.items():
#assuming "mean" is a function that calculates the average of a list
print "mean of section [%i,%i) column 3 is %f" % (s, s+1, mean(columns[2]))
Расширение этого до нескольких / различных столбцов и функций должно быть тривиальным.