2011-11-14 43 views
4

这是我试图解析解析制表符分隔文件与丢失的字段

ENTRY map0010\tNAME Glycolysis\tDESCRIPTION Glycolysis is the process of converting glucose into pyruvate\tCLASS Metabolism\tDISEASE H00071 Hereditary fructose intolerance\tH00072 Pyruvate dehydrogenase complex deficiency\tDBLINKS  GO: 0006096 0006094 
ENTRY map00020\tNAME Citrate cycle (TCA cycle)\tCLASS Metabolism; Carbohydrate Metabolism\tDISEASE H00073 Pyruvate carboxylase deficiency\tDBLINKS  GO: 0006099\tREL_PATHWAY map00010 Glycolysis/Gluconeogenesis\tmap00053 Ascorbate and aldarate metabolism 

我试图获得仅含有一些领域,如输出的复杂制表符分隔的文件的一个例子:

ENTRY map0010\tNAME Glycolysis\tCLASS Metabolism\tDISEASE H00071 Hereditary fructose intolerance H00072 Pyruvate dehydrogenase complex deficiency\tDBLINKS  GO: 0006096 0006094\tNA 
ENTRY map00020\tNAME Citrate cycle (TCA cycle)\tCLASS Metabolism; Carbohydrate Metabolism\tDISEASE H00073 Pyruvate carboxylase deficiency\tDBLINKS  GO: 0006099\tREL_PATHWAY map00010 Glycolysis/Gluconeogenesis\tmap00053 Ascorbate and aldarate metabolism 

的主要问题是,并不是所有的行包含相同数量的字段,所以我需要删除,例如,包含字符串“描述”字段,并且在各行,其中添加一个空场“CLASS”字段不存在。

此外,对于某些领域的数据被分割成多个(f.i,第1行,疾病包含疾病数据!),我需要加入他们。

我已经试过:

input = open('file', 'r') 

dict = ["ENTRY", "NAME", "CLASS", "DISEASE", "DBLINKS", "REL_PATHWAY"] 

split_tab = [] 
output = [] 

for line in input: 
    split_tab.append(line.split('\t')) 

for item in dict: 
    for element in split_tab: 
     if item in element: 
      output.append(element) 
     else: 
      output.append('\tNA\t') 

但它使一切,不仅在字典中指定的元素。 你能帮我吗?

+0

那么,什么是实际的格式/文法? –

+0

@Stuart,这是一个制表符分隔的文件(也许我不明白你的问题)。 – Sonny

+0

看起来,每行显式命名字段,用空格分隔,然后是由tab分隔的值: –

回答

6

使用内置的csv库。你的工作会容易得多。

对于一些示例代码:

import csv 
reader = csv.reader(open('myfile.csv', 'rb'), dialect='excel-tab') 
fieldnames = ['Name','Class'] 
writer = csv.DictWriter(open('myfile.csv', 'rb'), fieldnames, restval='', extrasaction='ignore', dialect='excel-tab') 

for row in reader: 
    newrow = {} 
    for field in row: 
     key = field.split(' ', 1)[0] 
     newrow[key] = field 
    writer.writerow(newrow) 

要特别注意DictWriter是如何设置的。如果您包含restvalextrasaction字段,则更容易使用。它们允许你传递一个比作者期望值更多或更少的字典。

只需设置适当的字段名称,并设置阅读器使用正确的方言。这可能包括添加自己的,但csv链接有关于如何做到这一点的说明。

编辑

罗布的评论贴在下面,我已经修订此考虑到一个事实,即CSV方言并不像我想象的那样强大。

+0

这将无法正常工作。 DictReader类需要给出字段名称或作为第一行数据。索尼的数据在每一行的字段中都嵌入了字段名称,并且可以丢失任意字段(不仅仅是空的)。例如,第3列可能是“描述”,或者可能是“CLASS”;你必须查看每一行的字段内容以知道它是什么字段。如果一个方言可以处理这个,文档当然不解释如何。 –

+0

@robmayoff我随意设置字段名,包含变量。剩下的就是按照[这里]的解释设置一个新的方言(http://docs.python.org/library/csv.html#csv-fmt-params)。请注意,如果方括号变量中嵌入了字段名的混合字段,他可能需要继承该方言变量。 –

+0

“我正在任意设置字段名称” - 在DictWriter上。您不在DictReader上设置任何字段名称。 “......正如[这里]解释的一样(http://docs.python.org/library/csv.html#csv-fmt-params)。”该文档没有解释如何使用方言来确定字段名称。事实上,方言*不能确定字段名称。检查源代码([csv.py](http://hg.python.org/cpython/file/555871844962/Lib/csv.py)[_csv.c](http://hg.python.org/cpython/)文件/ 555871844962 /模块/ _csv.c))。 –

2

你的线

split_tab.append(line.split( '\ T'))

是搞乱这个向上。你在列表中列出一个列表。试试这个来代替:

split_tab = line.split( '\ t')

+1

有人可以解释为什么我的回答得到如此少的赞赏吗?我发现代码存在问题 - 其他两个答案虽然很好,但给出了不同的方法。没有爱指出一个简单的错误?这是一个寒冷的世界 – Rookie

+0

你的回答是正确的,这就是为什么没有人下调它。但是,他正在复制已经存在于python中的功能,所以他最终得到的功能更少且更容易出错。 –

+1

谢谢你,这让人很有道理! (编辑:这可能会被解释为讽刺,但这不是我的意图!) – Rookie

3
requiredKeys = 'ENTRY NAME CLASS DISEASE DBLINKS REL_PATHWAY'.split(' ') 

for line in open('file', 'r'): 
    fields = line.split('\t') 
    fieldMap = {} 
    for field in fields: 
     key = field.split(' ', 1)[0] 
     fieldMap[key] = field 
    print '\t'.join([fieldMap.get(key, 'NA') for key in requiredKeys])