Категоризация данных, вычисление среднего и стандартного отклонения для каждой категории

Я пишу код для классификации данных и получения среднего и стандартного отклонения. Вот пример моих данных.

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 столбцов. Я думаю о трехэтапном расчете здесь.

  1. Распределите эти числа по 6-му столбцу. 6-й столбец состоит из чисел с плавающей точкой от 0 до n. Я надеюсь сгенерировать n секций (или субматриц, или что-то еще), например, 0~1, 1~2, 2~3 .... n-1 ~ n. Последнее число должно быть округлено до числа последних данных, потому что я надеюсь сделать разделы. Например, если последнее число - 121.2513, последний раздел должен содержать 120~121, чтобы содержать эти данные.

  2. Перераспределите все остальные номера столбца 1~5 в соответствующие им подразделы на основе 6-го столбца. Если в определенных разделах нет номера, просто выведите его как 0. Количество подразделов будет n. Количество элементов в каждом подразделе будет случайным.

  3. Получите среднее и стандартное отклонение 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]))

Расширение этого до нескольких / различных столбцов и функций должно быть тривиальным.

Другие вопросы по тегам