使用Python按第一(或第二,或其他)列对文件进行排序

9

这似乎是一个非常基础的问题,但我对Python还不熟悉,在花费很长时间尝试自己解决后,我认为现在是时候向更高级的人询问了!

那么,我有一个文件(示例):

ENSMUSG00000098737  95734911    95734973    3   miRNA
ENSMUSG00000077677  101186764   101186867   4   snRNA
ENSMUSG00000092727  68990574    68990678    11  miRNA
ENSMUSG00000088009  83405631    83405764    14  snoRNA
ENSMUSG00000028255  145003817   145032776   3   protein_coding
ENSMUSG00000028255  145003817   145032776   3   processed_transcript
ENSMUSG00000028255  145003817   145032776   3   processed_transcript
ENSMUSG00000098481  38086202    38086317    13  miRNA
ENSMUSG00000097075  126971720   126976098   7   lincRNA
ENSMUSG00000097075  126971720   126976098   7   lincRNA

我需要写一个新文件,包含和原文件相同的信息,但按第一列排序。

目前我使用的是:

lines = open(my_file, 'r').readlines()
output = open("intermediate_alphabetical_order.txt", 'w')

for line in sorted(lines, key=itemgetter(0)):
    output.write(line)

output.close()

我的代码没有返回任何错误,但输出文件与输入文件完全相同。

我知道这肯定是一个非常基本的错误,但如果有人能告诉我我错在哪里,那就太棒了!

非常感谢!

编辑

我遇到了文件打开方式的问题,所以关于已经打开数组的答案并不能帮助我。


你尝试过逐行读取并压缩吗? - m_callens
1
嗨,我认为这个问题可能已经在以下链接中得到回答:https://dev59.com/u2Ij5IYBdhLWcg3wmWC1,https://dev59.com/XGIj5IYBdhLWcg3whFUI,... - bufh
@bufh 不完全是,这些解释了如何做OP已经尝试过的事情。 - SuperBiasedMan
@bufh 是的,我看到了这些答案,但我遇到困难的部分与读取文件的方式有关,因此已经谈论数组的答案对我没有帮助。 无论如何,谢谢 :) - Tiana
6个回答

8
你遇到的问题是没有将每一行转换为列表。当你读取文件时,只是将整行作为字符串读入。然后按照每行的第一个字符进行排序,而在你的输入中这个字符总是相同的,即'E'
如果只想按照第一列排序,需要将第一块分离出来并仅读取该部分。因此,你的关键字应该是这样的:
for line in sorted(lines, key=lambda line: line.split()[0]):
< p > split将把您的行转换为列表,然后从该列表中取出第一列。


7
如果您的输入文件是以制表符分隔的,您也可以使用csv模块。
import csv
from operator import itemgetter
reader = csv.reader(open("t.txt"), delimiter="\t")

for line in sorted(reader, key=itemgetter(0)):
    print(line)

按第一列排序。

更改中的数字

key=itemgetter(0)

按不同列进行排序。

你还需要在开头加入 from operator import itemgetter - domi
@domi:谢谢你提醒,我已经更新了我的答案。 - Revan

2
与SuperBiasedMan的想法相同,但我更喜欢这种方法:如果您想要另一种排序方式(例如:如果第一列匹配,则按第二列,然后是第三列等进行排序),则更容易实现。
with open(my_file) as f:
    lines = [line.split(' ') for line in f]
output = open("result.txt", 'w')

for line in sorted(lines):
    output.write(' '.join(line), key=itemgetter(0))

output.close()

1
你可以编写一个函数,该函数使用csv.reader解析文件,并按列排序,函数需要输入文件名、分隔符和排序列作为参数。
from operator import itemgetter

import  csv

def sort_by(fle,col,delim):
    with open(fle) as f:
        r = csv.reader(f, delim=delim)
        for row in sorted(r, key=itemgetter(col)):
            yield row

for row in sort_by("your_file",2, "\t"):
     print(row)

1

您可以使用pandas快速完成此操作,步骤如下,数据文件设置完全与您展示的相同(即,使用变量空格作为分隔符):

import pandas as pd
df = pd.read_csv('csvdata.csv', sep=' ', skipinitialspace=True, header=None)
df.sort(columns=[0], inplace=True)
df.to_csv('sorted_csvdata.csv', header=None, index=None)

只是为了检查结果:

with open('sorted_csvdata.csv', 'r') as f:
    print(f.read())

ENSMUSG00000028255,145003817,145032776,3,protein_coding
ENSMUSG00000028255,145003817,145032776,3,processed_transcript
ENSMUSG00000028255,145003817,145032776,3,processed_transcript
ENSMUSG00000077677,101186764,101186867,4,snRNA
ENSMUSG00000088009,83405631,83405764,14,snoRNA
ENSMUSG00000092727,68990574,68990678,11,miRNA
ENSMUSG00000097075,126971720,126976098,7,lincRNA
ENSMUSG00000097075,126971720,126976098,7,lincRNA
ENSMUSG00000098481,38086202,38086317,13,miRNA
ENSMUSG00000098737,95734911,95734973,3,miRNA

您可以通过在列 colmuns=[...] 关键字参数中添加额外的列来进行多列排序。

0

这里还有另一个选项。与上面的一些想法类似。基本上,mysort是一个函数,它将为您执行自定义排序,这里的排序是基于

def mysort(line):
    return line.split()[0]

with open("records.txt", "r") as f:
    text = f.readlines()

for line in sorted(text, key=mysort):
    print line

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接