【问题标题】:from text file to csv using Python使用 Python 从文本文件到 csv
【发布时间】:2011-12-30 07:33:07
【问题描述】:

我需要帮助来解析一个很长的文本文件,如下所示:

NAME         IMP4   
DESCRIPTION  small nucleolar ribonucleoprotein 
CLASS        Genetic Information Processing
             Translation
             Ribosome biogenesis in eukaryotes
DBLINKS      NCBI-GI: 15529982
             NCBI-GeneID: 92856
             OMIM: 612981
///
NAME         COMMD9
DESCRIPTION  COMM domain containing 9
ORGANISM     H.sapiens
DBLINKS      NCBI-GI: 156416007
             NCBI-GeneID: 29099
             OMIM: 612299
///
.....

我想获得一个结构化的 csv 文件,每行中的列数相同,以便轻松提取我需要的信息。

首先我是这样尝试的:

for line in a:
    if '///' not in line:
        b.write(''.join(line.replace('\n', '\t')))
    else:
    b.write('\n')

获取这样的 csv:

NAME         IMP4\tDESCRIPTION  small nucleolar ribonucleoprotein\tCLASS        Genetic Information Processing\t             Translation\t             Ribosome biogenesis in eukaryotes\tDBLINKS      NCBI-GI: 15529982\t            NCBI-GeneID: 92856\t
         OMIM: 612981
NAME         COMMD9\tDESCRIPTION  COMM domain containing 9\tORGANISM     H.sapiens\tDBLINKS      NCBI-GI: 156416007\t             NCBI-GeneID: 29099t\             OMIM: 612299

主要问题是像 DBLINKS 这样的字段,在原始文件中是多行的,这样会导致结果拆分为多个字段,而我需要将它们全部放在一个字段中。 此外,并非所有字段都存在于每一行中,例如示例中的字段“CLASS”和“ORGANISM”。

我想获取的文件应该是这样的:

NAME         IMP4\tDESCRIPTION  small nucleolar ribonucleoprotein\tNA\tCLASS        Genetic Information Processing; Translation; Ribosome biogenesis in eukaryotes\tDBLINKS      NCBI-GI: 15529982; NCBI-GeneID: 92856; OMIM: 612981
NAME         COMMD9\tDESCRIPTION  COMM domain containing 9\tORGANISM     H.sapiens\tNA\tDBLINKS      NCBI-GI: 156416007; NCBI-GeneID: 29099; OMIM: 612299

你能帮帮我吗?

【问题讨论】:

    标签: python parsing text csv


    【解决方案1】:

    您可以使用itertools.groupby,一次将行收集到记录中,第二次将多行字段收集到迭代器中:

    import csv
    import itertools
    
    def is_end_of_record(line):
        return line.startswith('///')
    
    class FieldClassifier(object):
        def __init__(self):
            self.field=''
        def __call__(self,row):
            if not row[0].isspace():
                self.field=row.split(' ',1)[0]
            return self.field
    
    fields='NAME DESCRIPTION ORGANISM CLASS DBLINKS'.split()
    with open('data','r') as f:
        for end_of_record, lines in itertools.groupby(f,is_end_of_record):
            if not end_of_record:
                classifier=FieldClassifier()
                record={}
                for fieldname, row in itertools.groupby(lines,classifier):
                    record[fieldname]='; '.join(r.strip() for r in row)
                print('\t'.join(record.get(fieldname,'NA') for fieldname in fields))
    

    产量

    NAME         IMP4   DESCRIPTION  small nucleolar ribonucleoprotein  NA  CLASS        Genetic Information Processing; Translation; Ribosome biogenesis in eukaryotes DBLINKS      NCBI-GI: 15529982; NCBI-GeneID: 92856; OMIM: 612981
    NAME         COMMD9 DESCRIPTION  COMM domain containing 9   ORGANISM     H.sapiens  NA  DBLINKS      NCBI-GI: 156416007; NCBI-GeneID: 29099; OMIM: 612299
    

    上面是你看到的输出。它与您发布的所需输出相匹配,假设您显示的是该输出的 repr


    所用工具的参考:

    【讨论】:

    • 我想和你私聊,有什么办法吗?
    • 对不起,没有。我可以帮你吗?
    • 我将在我的研究中使用这个脚本,我想在我的论文中正式感谢你
    • 谢谢,但您不必这样做。我在这里发布的所有内容都是免费的。如果您想引用来源,只需引用此页面即可。
    【解决方案2】:

    此脚本会将您的文本文件转换为有效的 CSV 文件(例如,可以使用 Excel 读取):

    import sys
    from sets import Set
    
    if len(sys.argv) < 2:
        print 'Usage: %s <input-file> <output-file>' % sys.argv[0]
        sys.exit(1)
    
    entries = []
    entry = {}
    
    # Read the input file
    with open(sys.argv[1]) as input:
        lines = input.readlines()
    
    for line in lines:
        # Check for beginning of new entry
        if line.strip() == '///':
            if len(entry) > 0:
                entries.append(entry)
            entry = {}
            continue
    
        # Check for presense of key
        possible_key = line[:13].strip()
        if possible_key != '':
            key = possible_key
            entry[key] = []
    
        # Assemble the value
        if key:
            entry[key].append(line[13:].strip())
    
    # Append the last entry
    if len(entry) > 0:
        entries.append(entry)
    
    # 'entries' now contains a list of a dict of a list
    
    # Find out all possible keys
    all_keys = Set()
    for entry in entries:
        all_keys.union_update(entry.keys())
    
    # Write all entries to the output file
    with open(sys.argv[2], 'w') as output:
        # The first line will contain the keys
        output.write(','.join(['"%s"' % key for key in sorted(all_keys)]))
        output.write('\r\n')
    
        # Write each entry
        for entry in entries:
           output.write(','.join(['"%s"' % ';'.join(entry[key]) if key in entry else '' for key in sorted(all_keys)]))
           output.write('\r\n')
    

    【讨论】:

    • 它只写用法:
    猜你喜欢
    • 2020-09-16
    • 2021-05-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-11-03
    • 2021-08-13
    • 1970-01-01
    • 2013-12-06
    相关资源
    最近更新 更多