Python 解析大型文本文件并捕获多层数据

2 投票
3 回答
1341 浏览
提问于 2025-04-16 19:04

首先,如果我描述得很糟糕,我要道歉,我还在边学边做。

我有几个很大的文本文件(.txt),大约有60万行,里面是一些医院的基本信息,我正在用Python来解析这些数据。我一直在使用默认字典(python2.7)来统计病人的诊断情况,统计一层的数量。比如说,如果我想抓取心脏病发作的情况,然后根据类型进行区分(伪代码):

if 'heart attack' in line[65:69]: 
    defaultdict['heart attack'] +=1
    if [65:69] == 'worst kind':
        defaultdict['worst'] += 1
    else: 
        defaultdict['not worst'] +=1

这样我就能抓到心脏病发作的情况,以及它们是否是我关注的特定类型。这一切都运作得很好。不过,现在我还想从同一行中收集病人的年龄(以编码范围表示)、性别(男、女、未知)和种族等信息。我意识到我现在的方法不太适合这个需求——看起来复杂度在迅速增加。所以,在我陷得太深之前,有没有其他方法可以处理这个问题呢?

最终,我打算把这些文件放到一个真正的数据库里,但这基本上是我当前项目中最后一块需要的信息,所以我现在可以先把它们放到Excel里,做个图表。

非常感谢任何建议!

补充说明:示例行是这样的 -

02032011JuniorHospital       932220320M09A228393
03092011MassGeneralHospitals 923392818F09B228182

所有行的长度都是固定的,比如line[0:8]总是日期,等等。还有一个单独的文件(字典?)来解释这些数字的含义——比如诊断代码可能是410.22,年龄会在一个范围内,比如0代表0-1岁,1代表2-3岁,等等……

目标:对于我想要的每个诊断,我还想知道这个特定的诊断是否是我关注的子类型(用上面的代码可以轻松做到),以及与该诊断相关的各种年龄(也就是说,每个年龄范围内有多少人)。我现在是把这些输出到一个Excel文件(csv),所以我想要多个不同的列,以便我可以根据需要进行绘图。

再说一次,我可以通过创建几个额外的默认字典来解决这个问题——但我觉得应该有更简单的方法把它们都归到一个主要对象里!

呼~

3 个回答

0

听起来你遇到的情况和我当初一样,我当时也在努力处理文本并从中提取数据,但不知道有正则表达式这个东西(可以看看re模块)。

请具体说明你想要做什么,我们会帮助你实现你的目标。对我来说,这将会用到正则表达式的强大功能。

2

如果你把每一行数据放进一个元组里,就可以根据元组里的任何字段或者字段组合来排序。你需要提供一个自定义的比较函数,用来比较这些元素。比如说,你的比较函数可以先根据第一个字段排序,然后再根据第三个字段排序。如果第一个字段是“疾病”,第三个字段是“年龄”,那么就会先按年龄排序,在每个年龄段内再按疾病排序。这个方法很容易调整,比如可以先按疾病排序,然后按年龄排序,并在每种疾病后面分开列表。

http://wiki.python.org/moin/HowTo/Sorting/

不过,如果没有SQL或者电子表格,你可能需要使用多个字典来处理这些数据。

5

你可以把层级计数的概念进行一些概括,这样可以让代码更清晰,也更容易修改。下面是一个层级计数器类的基本示例:

class HierarchicCounter(object):
    def __init__(self, key, hierarchy):
        self.key = key
        self.hierarchy = hierarchy
        self.counts = defaultdict(int)
        self.subcounters = defaultdict(self._create_subcounters)

    def _create_subcounters(self):
        return {key: HierarchicCounter(key, hierarchy)
                for key, hierarchy in self.hierarchy.iteritems()}

    def count(self, line):
        key = self.key(line)
        if key is None:
            return
        self.counts[key] += 1
        for subcounter in self.subcounters[key].itervalues():
            subcounter.count(line)

这个类的构造函数接受两个参数。key 参数是“键函数”,它告诉计数器应该计数什么。如果你给计数器输入一行数据,它会把这个键函数应用到这行数据上,然后增加对应键的计数。hierarchy 参数是一个字典,它把你想要的子计数器的键函数和它们各自的层级对应起来。

使用示例:

def diagnosis_major(line):
    return line[0:3]

def diagnosis_minor(line):
    return line[3:5]

def age(line):
    return int(line[5:7])

def sex(line):
    return line[7]

counter = HierarchicCounter(
    diagnosis_major, {diagnosis_minor: {sex: {}}, age: {}})

这段代码创建了一些简单的键函数,从一行数据中提取不同的字段。在你的应用中,键函数可能会变得更复杂。你也可以在这里过滤掉一些键——如果一个键函数返回 None,计数器就会忽略这一行数据。最后两行代码创建了一个 HierarchicCounter 实例,并定义了以下的计数层级:

diagnosis_major
|-- diagnosis_minor
|   \-- sex
\-- age

所以这个计数器会统计每种主要诊断的案例数量。对于每种主要诊断,它还会统计与之对应的次要诊断和年龄。每种主要诊断下的每个次要诊断也会统计性别。

当然,这个例子并不完整。你还需要添加一些代码,才能以某种格式输出在计数器层级中收集到的计数——这只是为了让你了解如何以更一般的方式进行抽象。

撰写回答