Динамический анализ данных исследований в Python - PullRequest
0 голосов
/ 22 мая 2011

Длинная (сложная) версия: Я собираю данные исследований с использованием Python.Мой первоначальный анализ - это некрасивый (но функциональный) код, который дает мне некоторую базовую информацию и превращает мои необработанные данные в формат, подходящий для статистического анализа в тяжелых условиях с использованием SPSS.Однако каждый раз, когда я изменяю эксперимент, мне приходится погружаться в код анализа.

Для типичного эксперимента у меня будет 30 файлов, каждый для уникального пользователя.Количество полей фиксировано для каждого эксперимента (но может варьироваться от одного к другому 10-20).Файлы обычно имеют длину 700-1000 записей со строкой заголовка.Формат записи разделен табуляцией (см. Пример, который состоит из 4 целых чисел, 3 строк и 10 чисел с плавающей запятой).

Мне нужно отсортировать мой список по категориям.В файле из 1000 строк у меня могло быть 4-256 категорий.Вместо того, чтобы пытаться заранее определить, сколько категорий содержит каждый файл, я использую приведенный ниже код для их подсчета.Целые числа в начале каждой строки определяют, какой категории соответствуют значения с плавающей точкой в ​​строке.Целочисленные комбинации могут быть изменены строковыми значениями для получения совершенно разных результатов, и несколько комбинаций могут иногда смешиваться вместе.

Как только они попадают в категории, начинается сокращение чисел.Я получаю статистическую информацию (среднее, SD и т. Д. Для каждой категории для каждого файла).

Основы: Мне нужно разбить данные, как в примере ниже, на категории.Категории - это комбинации не-поплавков в каждой записи. Я также пытаюсь придумать динамический (графический) способ связать комбинации столбцов с категориями. Создаю новый пост для этого.

I 'я ищу предложения о том, как сделать оба.

    # data is a list of tab separated records
    # fields is a list of my field names

    # get a list of fieldtypes via gettype on our first row
    # gettype is a function to get type from string without changing data
    fieldtype = [gettype(n) for n in data[1].split('\t')]

    # get the indexes for fields that aren't floats
    mask =  [i for i, field in enumerate(fieldtype) if field!="float"]

    # for each row of data[skipping first and last empty lists] we split(on tabs)
    # and take the ith element of that split where i is taken from the list mask
    # which tells us which fields are not floats
    records = [[row.split('\t')[i] for i in mask] for row in data[1:-1]]

    # we now get a unique set of combos
    # since set doesn't happily take a list of lists, we join each row of values
    # together in a comma seperated string. So we end up with a list of strings.
    uniquerecs = set([",".join(row) for row in records])


    print len(uniquerecs)
    quit()

def gettype(s):
    try:
        int(s)
        return "int"
    except ValueError:
        pass
    try:
        float(s)
        return "float"
    except ValueError:
        return "string"

Пример данных:

field0  field1  field2  field3  field4  field5  field6  field7  field8  field9  field10 field11 field12 field13 field14 field15
10  0   2   1   Right   Right   Right   5.76765674196   0.0310912272139 0.0573603238282 0.0582901376612 0.0648936500524 0.0655294305058 0.0720571099855 0.0748289246137 0.446033755751
3   1   3   0   Left    Left    Right   8.00982745764   0.0313840132052 0.0576521406854 0.0585844966069 0.0644905497442 0.0653386429438 0.0712603578765 0.0740345755708 0.2641076191
5   19  1   0   Right   Left    Left    4.69440026591   0.0313852052224 0.0583165354345 0.0592403274967 0.0659404609478 0.0666070804916 0.0715314027001 0.0743022054775 0.465994962101
3   1   4   2   Left    Right   Left    9.58648184552   0.0303649003017 0.0571579895338 0.0580911765412 0.0634304670863 0.0640132919609 0.0702920967445 0.0730697946335 0.556525293
9   0   0   7   Left    Left    Left    7.65374257547   0.030318719717  0.0568551744109 0.0577785415066 0.0640577002605 0.0647226582655 0.0711459854908 0.0739256050784 1.23421547397

Ответы [ 4 ]

2 голосов
/ 22 мая 2011

Не уверен, что понимаю ваш вопрос, но вот несколько соображений:

Для анализа файлов данных вы обычно используете Python CSV-модуль .

Для классификации данных вы можете использовать defaultdict с полями, не являющимися числами с плавающей точкой, соединенными в качестве ключа для dict.Пример:

from collections import defaultdict
import csv

reader = csv.reader(open('data.file', 'rb'), delimiter='\t')
data_of_category = defaultdict(list)
lines = [line for line in reader]
mask =  [i for i, n in enumerate(lines[1]) if gettype(n)!="float"]
for line in lines[1:]:
    category = ','.join([line[i] for i in mask])
    data_of_category[category].append(line)

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

И я не понял части о «динамическом (графическом) способе связать комбинации столбцов с категориями».

0 голосов
/ 23 мая 2011

Некоторые полезные ответы уже есть, но я тоже добавлю свои. Ключевые моменты:

  1. Используйте модуль csv
  2. Используйте collections.namedtuple для каждой строки
  3. Сгруппируйте строки, используя кортеж из int значений полей в качестве ключа

Если исходные строки отсортированы по ключам (целочисленные значения столбцов), вы можете использовать itertools.groupby. Это, вероятно, уменьшит потребление памяти. Учитывая данные вашего примера и тот факт, что ваши файлы содержат> = 1000 строк, это, вероятно, не является проблемой для беспокойства.

def coerce_to_type(value):
    _types = (int, float)
    for _type in _types:
        try:
            return _type(value)
        except ValueError:
            continue
    return value

def parse_row(row):
    return [coerce_to_type(field) for field in row]

with open(datafile) as srcfile:
    data    = csv.reader(srcfile, delimiter='\t')

    ## Read headers, create namedtuple
    headers = srcfile.next().strip().split('\t')
    datarow = namedtuple('datarow', headers)

    ## Wrap with parser and namedtuple
    data = (parse_row(row) for row in data)
    data = (datarow(*row) for row in data)

    ## Group by the leading integer columns
    grouped_rows = defaultdict(list)
    for row in data:
        integer_fields = [field for field in row if isinstance(field, int)]
        grouped_rows[tuple(integer_fields)].append(row)

    ## DO SOMETHING INTERESTING WITH THE GROUPS
    import pprint
    pprint.pprint(dict(grouped_rows))

РЕДАКТИРОВАТЬ Вы можете найти код в https://gist.github.com/985882 полезным.

0 голосов
/ 22 мая 2011

Шаг 1 : Используйте что-то вроде csv.DictReader, чтобы превратить текстовый файл в повторяющиеся строки.

Шаг 2 : Превратить это в диктовку первой записи: остальные записи.

with open("...", "rb") as data_file:
    lines = csv.Reader(data_file, some_custom_dialect)
    categories = {line[0]: line[1:] for line in lines}

Шаг 3 : переберите items() данных и сделайте что-нибудь с каждой строкой.

for category, line in categories.items():
    do_stats_to_line(line)
0 голосов
/ 22 мая 2011

По крайней мере, часть вашего вопроса, посмотрите на Именованные кортежи

...