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