Python 解析大型文本文件并捕获多层数据
首先,如果我描述得很糟糕,我要道歉,我还在边学边做。
我有几个很大的文本文件(.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 个回答
听起来你遇到的情况和我当初一样,我当时也在努力处理文本并从中提取数据,但不知道有正则表达式这个东西(可以看看re模块)。
请具体说明你想要做什么,我们会帮助你实现你的目标。对我来说,这将会用到正则表达式的强大功能。
如果你把每一行数据放进一个元组里,就可以根据元组里的任何字段或者字段组合来排序。你需要提供一个自定义的比较函数,用来比较这些元素。比如说,你的比较函数可以先根据第一个字段排序,然后再根据第三个字段排序。如果第一个字段是“疾病”,第三个字段是“年龄”,那么就会先按年龄排序,在每个年龄段内再按疾病排序。这个方法很容易调整,比如可以先按疾病排序,然后按年龄排序,并在每种疾病后面分开列表。
http://wiki.python.org/moin/HowTo/Sorting/
不过,如果没有SQL或者电子表格,你可能需要使用多个字典来处理这些数据。
你可以把层级计数的概念进行一些概括,这样可以让代码更清晰,也更容易修改。下面是一个层级计数器类的基本示例:
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
所以这个计数器会统计每种主要诊断的案例数量。对于每种主要诊断,它还会统计与之对应的次要诊断和年龄。每种主要诊断下的每个次要诊断也会统计性别。
当然,这个例子并不完整。你还需要添加一些代码,才能以某种格式输出在计数器层级中收集到的计数——这只是为了让你了解如何以更一般的方式进行抽象。