在Python中动态解析研究数据

0 投票
4 回答
1706 浏览
提问于 2025-04-16 18:08

长话短说: 我正在用Python收集研究数据。最开始的代码虽然不太好看,但能正常工作,它能给我一些基本信息,把原始数据转成适合用SPSS进行深入统计分析的格式。不过,每次我修改实验的时候,就得重新去调整分析的代码。

对于一个典型的实验,我会有30个文件,每个文件对应一个独特的用户。每个实验的字段数量是固定的(但不同实验之间可能会有10到20个字段的差异)。这些文件通常有700到1000条记录,并且有一个表头。记录的格式是用制表符分隔的(比如样本数据包含4个整数、3个字符串和10个浮点数)。

我需要把我的数据列表分类。在一个1000行的文件中,我可能会有4到256个类别。与其提前确定每个文件有多少个类别,我使用下面的代码来统计它们。每行开头的整数决定了这一行的浮点值属于哪个类别。整数的组合可以通过字符串值进行修改,从而产生非常不同的结果,有时多个组合也可以归为一类。

一旦数据被分类,就开始进行数据处理。我会得到每个文件每个类别的统计信息(比如均值、标准差等)。

要点: 我需要把下面的样本数据解析成类别。类别是每条记录中非浮点数的组合。我还想找一种动态(图形化)的方式来将列组合与类别关联起来。 这部分我会另开一个帖子讨论。

我在寻找关于如何同时完成这两件事的建议。

    # 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 个回答

0

第一步: 使用类似 csv.DictReader 的工具,把文本文件转换成可以逐行读取的格式。

第二步: 把这些行转换成一个字典,字典的结构是第一个条目作为键,后面的条目作为值。

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

第三步: 遍历这个数据的 items(),对每一行进行一些操作。

for category, line in categories.items():
    do_stats_to_line(line)
0

关于你问题的某个部分,可以看看命名元组这个内容。

2

我不太确定我是否理解你的问题,不过我有一些想法可以分享:

在处理数据文件时,通常会用到 Python的csv模块

如果你想对数据进行分类,可以使用 defaultdict,把那些不是浮点数的字段组合起来作为字典的键。举个例子:

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)

这样一来,你就不需要先计算出分类,可以一次性处理数据。

至于“以动态(图形化)方式将列组合与类别关联”那部分,我就不太明白了。

撰写回答