Skip to main content
 首页 » 编程设计

python之按多列对数据进行排序

2025年05月04日10mfrbuaa

我有一个关于按多列对数据进行排序的问题。我绝对是这方面的初学者,想知道如何在不丢失第一列顺序的情况下按一列然后按另一列排序。我有一个包含三列的制表符分隔数据文件。大多数数据不成对(一个 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 

所需格式:

PITG_00129  606 1436 
 
PITG_00130  1   987 
 
PITG_00132  2   1321 
 
PITG_00133 1 2946 
PITG_00133 4081 4515 
PITG_00133 4464 11708 

请您参考如下方法:

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

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

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

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) 

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

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)) 

这使用 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