Python中基于标识符的文件并行解析

Python中基于标识符的文件并行解析,python,parsing,Python,Parsing,我有一些以下格式的并行文件。标识符总是相同的,标识符之间的数字长度也是相同的。文件之间的更改是实际数字。最后,并行文件的数量可以从2到50不等 >Identifier1 0 1 3 2 0 >Identifier2 0 4 1 >Identifier3 ... 由于这些文件很大,(每个大约3.5gb),我不想将它们加载到内存中,而是基于标识符并行解析它们。因此,对于所有文件,选择第一个标识符及其对应的值,并在所有可能的组合之间调用函数。然后选择第二个标识符并执行相同的操作

我有一些以下格式的并行文件。标识符总是相同的,标识符之间的数字长度也是相同的。文件之间的更改是实际数字。最后,并行文件的数量可以从2到50不等

>Identifier1  
0
1
3
2
0
>Identifier2
0
4
1
>Identifier3
...
由于这些文件很大,(每个大约3.5gb),我不想将它们加载到内存中,而是基于标识符并行解析它们。因此,对于所有文件,选择第一个标识符及其对应的值,并在所有可能的组合之间调用函数。然后选择第二个标识符并执行相同的操作

为了解析文件,我尝试的第一件事是:

import fileinput
from glob import glob
fnames = glob('tmp/test*')
for line in fileinput.input(fnames):
   print(line)
问题是它一个接一个地解析文件,而不是一次解析所有文件

第二件事(这是一件正在工作的事情)是使用“with open”手动添加文件。但这不是一个好的选择,因为文件的数量不是固定的。以下代码用于组合两个文件

from itertools import izip_longest
with open('tmp/test1', 'r') as a, open('tmp/test2', 'r') as b:
   flag = true
   for x, y in izip_longest(a,b):
           first = x.strip()
           second = y.strip()
           if(first[0]=='>' and second[0]=='>' and first==second):
                   if(flag is true):
                           flag = false
                           identifier = first
                           d1 = []
                           d2 = []
                   else:
                           print(cor(list(d1),list(d2)))
                           identifier = first
                           d1 = []
                           d2 = []
           else:
                   d1.append(first)
                   d2.append(second)
如何改进这一点以适用于多个文件

更新: 我在网上找到了以下迭代器:

def isheader(line):
    return line[0] == '>'

def aspairs(file):
        for header,group in itertools.groupby(f, isheader):
                if header:
                        line = group.next()
                        ensembl_id = line[1:].split()[0]
                else:
                        sequence = ''.join(line.strip() for line in group)
                        yield ensembl_id, sequence
当我用一个文件测试它时,它正在工作:

with open("tmp/test1") as f:
    for l in aspairs(f):
            print(l)

我不明白的是如何将它与Tom建议的解决方案结合起来。

这就是如何为多个文件名实现izip方法:

files = #create a list of filenames
open_files = [open(i, "r") for i in files]
for rows in izip(*open_files):
# rows is now a tuple containing one row from each file
# now you can compare each row with its identifiers
#Don't forget to close the files!
for file in open_files:
    file.close()
更新: 好的,我读了你的其他评论,我想我理解你想做什么,所以这里是我修改的代码。这里的要点是,我将创建一个列表列表,称为numbers\u list,它从每个文件中获取一个数字(对于每个标识符),并将该数字放入与文件“索引”对应的列表中-第一个文件中的第一个数字(第一行)将进入第一个列表中的第一个单元格,第二个文件中的第一个数字将进入第二个列表中的第一个单元格,以此类推。。(如果不清楚,请通知我)


在不牺牲运行时间或磁盘空间的情况下,似乎没有办法解决这个问题。以牺牲一些磁盘为代价更有效地解决这个问题的一个简单方法是创建索引

因此,例如,您可以实现一个两遍算法,在第一遍遍历文件时创建索引。将所有文件读入内存,但不要将实际数据保留在内存中,只保留每个标识符的偏移量。然后创建类似于

Identifier1|file1:0:253|file2:1234:1279|file7:151617:151702
Identifier2|file1:254:307|file3:2345:2399|file6:65537:65613
Identifier3|file2:0:125|file6:120:199
:
然后在第二遍中,一次读入一个标识符,
open()
每个文件,
seek()
到指定的偏移量,
read()
指定的字节范围,并解析它们。当您拥有该标识符的所有信息时,您可以写出该标识符的记录,并继续进行下一次迭代,以及索引文件中的下一个输入行

索引文件的大小可能会成为一个问题,但听起来它会比您的任何单个输入文件都要小一些;反复
open()
ing和
seek()
ing输入文件显然也会比直接读取文件慢。另一方面,如果您无法将所有数据保存在内存中,这将向您展示如何解决这一问题。此外,这甚至可以扩展到非常大的输入——但随后您可能需要移动到更多的过程(在每个顶级过程中,仅将标识符的子集提取到索引中,并重复,直到涵盖了所有过程)


当然,这只是将数据放入数据库并利用其功能执行合并的一个简单替代方法。

您可以列出同一文件夹中的所有文件,并对其进行迭代(一次比较两个文件)。这可能不是很有效,但编码很简单。更好的解决方案是使用多个线程-每个线程从不同的文件读取一行,一个线程将比较所有标识符-这将更加复杂,如果只扫描这些文件一次,或者如果不需要高性能脚本,则可能不值得实现。如果这些文件很大(你说是),那么尝试从磁盘“并行读取”很可能不起作用。磁盘头是串行争用点,只能“有效地”一次读取一个文件。在这种情况下,您唯一的希望是为每个标识符进行的计算非常昂贵,因此大部分时间都花在计算上,允许操作系统在计算的同时获取下一个文件片段关于当前的一个。这很有趣。我计算的是list.numpy.corrcoef(list1,list2)之间的相关系数。我不知道这是否“昂贵”够了。此外,由于文件很大,我使用的是最长的izip_。我会试一试,然后让你知道。文件格式表面上看起来像FASTA,但你有数字而不是序列。文件大小听起来也像你在处理FASTA。如果是这样,你可能想添加标签,以专门达到Pytion生物信息学程序员;标签很忙,所以很少有人查看所有帖子。我更新了问题,因为我不太清楚如何实际使用上面的行。使用上面描述的迭代器方法没有意义,因为izip已经创建了迭代器对象-它不会将整个文件加载到内存中,而是一次只读取一行从每个文件中输入ime。如果您能更详细地解释您希望在所有行上使用哪种比较或函数,我将能够进一步帮助您。1.是否要逐行比较(从每个文件中提取一个数字,并与所有其他数字进行比较?)2.或者,是否要比较完整的文件(一个文件中的所有数字与另一个文件中的所有数字)?
Identifier1|file1:0:253|file2:1234:1279|file7:151617:151702
Identifier2|file1:254:307|file3:2345:2399|file6:65537:65613
Identifier3|file2:0:125|file6:120:199
: