按多列排序数据

use*_*467 1 python perl

我有一个关于按多列排序数据的问题.我绝对是这方面的初学者,我想知道如何按一列排序,然后另一列排序而不会丢失第一列的排序.我有一个由三列组成的制表符分隔数据文件.大多数数据未配对(一个id,第一列,以及位置开始和结束,第二和第三列).但是,有时候,同一ID(第一列)有多个条目.这些需要保持组合在一起(没有空格将它们与下一个条目分开,除非它具有不同的ID).数据实际上已经按照第一列进行了排序,但我需要根据起始位置(第二列)对数据进行排序,同时保留原始排序.像这样:

目前的格式:

PITG_00129  606 1436

PITG_00130  1   987

PITG_00132  2   1321

PITG_00133 4464 11708
PITG_00133 1 2946
PITG_00133 4081 4515
Run Code Online (Sandbox Code Playgroud)

所需格式:

PITG_00129  606 1436

PITG_00130  1   987

PITG_00132  2   1321

PITG_00133 1 2946
PITG_00133 4081 4515
PITG_00133 4464 11708
Run Code Online (Sandbox Code Playgroud)

mgi*_*son 5

你可以在python中很容易地做到这一点.首先,您需要以适当的格式读取数据:

def line_to_tuple(line):
    data = line.split()
    return (data[0],int(data[1]),int(data[2]))
Run Code Online (Sandbox Code Playgroud)

这会将每一行转换为一个按字典顺序排序的元组.由于您的字符串(第一列)以易于排序的方式设置,因此我们无需担心它们.第二列和第三列只需要转换为整数以使它们正确排序.

with open(inputfile) as fin, open(outputfile,'w') as fout:
    non_blank_lines = (line for line in fin if line.strip())
    sorted_lines = sorted(non_blank_lines,key=line_to_tuple)
    fout.writelines(sorted_lines)
Run Code Online (Sandbox Code Playgroud)

这是另一个在字段之间保留空行的实现:

import itertools
def field1(line):
    data = line.split()
    try:
        return data[0]
    except IndexError:
        return None

def fields(line):
    data = line.split()
    return data[0],int(data[1]),int(data[2])

with open('test.dat') as fin, open('output.dat','w') as fout:
    for k,v in itertools.groupby(fin,key=field1):
        if k is None:
            fout.write('\n')
        else:
            fout.writelines(sorted(v,key=fields))
Run Code Online (Sandbox Code Playgroud)

这使用itertools根据空行对文件进行分块,并在将它们写回之前单独对这些组进行排序.

这是输出:

temp $ cat output.dat 
PITG_00129  606 1436

PITG_00130  1   987

PITG_00132  2   1321

PITG_00133 1 2946
PITG_00133 4081 4515
PITG_00133 4464 11708
Run Code Online (Sandbox Code Playgroud)