使用Python逐行比较大型文本文件

0 投票
3 回答
782 浏览
提问于 2025-04-16 14:36

我正在处理一些大型的生物信息学数据集,这些数据集的格式大致如下:

chromosomeNumber locusStart locusStop sequence moreData

我还有其他文件也是这种格式:

chromosomeNumber locusStart locusStop moreData

我需要做的是把每种类型的文件都读入内存。如果上面文件中某一行的locusStart值在下面文件中某一行的起始值和结束值之间,就把这一行打印到输出文件1。如果这个locusStart值不在下面文件的任何行的起始值和结束值之间,就把它打印到输出文件2。

目前,我正在读取这些文件,并把它们转换成以染色体为键的字典,字典的值是对应的行。然后我把每一行的值拆分成字符串,再用这些字符串进行比较。这花费的时间非常长,我想知道有没有更高效的方法来完成这个任务。

谢谢。

3 个回答

0

看起来对于下面的文件(我假设它是第二种格式),你最关心的字段就是'locusStart'。因为从你的描述来看,你并不一定在意其他的数据,所以你可以把所有的locusStart放到一个集合里:

locusStart_list = set()
with open(upper_file, 'r') as f:
  for line in f:
    tmp_list = line.strip().split()
    locusStart_list.add(tmp_list[1])

这样就省去了你对下面文件进行的那些繁琐的行处理。接着,你可以很方便地把某个字段的locusStart和从下方文件构建的集合进行比较。这个集合还会自动去掉重复的值,比用列表要快一些。

0

用一个字典来存储染色体编号是个不错的主意,只要你能把两个文件都放进内存里。

接下来,你需要根据locusStart来排序这两个列表(把字符串分开,把locusStart转换成数字——如果你不确定怎么单独根据locusStart排序,可以参考这个排序的说明)。

现在你可以开始遍历你的列表:如果较小的locusStart小于第一个较大的locusStart,就把这一行放到文件2,然后继续下一个。如果较小的locusStart大于第一个较大的locusStart,那么

  • 只要它也大于locusEnd,就把较大的列表的开头部分丢掉
  • 如果你发现某个情况是大于locusStart但小于locusEnd,就把它放到文件1
  • 否则,就把它放到文件2

这样应该可以把现在可能是O(n^2)的算法替换成O(n log n)的算法。

0

听起来你需要进行很多大于和小于的比较,所以我觉得把数据放进字典里并不会提高代码的速度——根据你说的,似乎你还是在遍历每个文件中的每个元素。

你需要的是一种不同的数据结构来加载你的数据,并进行比较操作。可以看看Python的bisect模块,我觉得它可能提供了你需要的数据结构,让你的比较操作变得高效。


如果你能更准确地描述一下你想要实现的目标,我们就能帮助你开始写代码。

撰写回答