有效地在数千兆字节的数据集中查找行

时间:2015-10-02 12:07:41

标签: python

我有两个数据集格式如下:

infile1:

1       742429  SNP_A-1909444   T       C       .       .       PR      GT      0/0     0/0     0/0     
1       767376  SNP_A-2237149   G       A       .       .       PR      GT      0/0     0/0     0/0 
1       769185  SNP_A-4303947   A       G       .       .       PR      GT      0/0     ./.     0/0

infile2:

1   742428  742430  rs3094315   SNP_A-1909444   C   T   +
1   769184  769186  rs4040617   SNP_A-4303947   A   G   -

如果来自inifle1的第3列中的数据和来自infile 2的第5列中的数据一致,并且infile2中的最后一列= =" - "那么,我想把infile1中2,4,5列的值从infile2切换到2,6,7列。

我可以用一些if语句来做,但文件很大(几次演出),所以它绝对不可行,因此,python执行它的最佳方法是什么?

编辑:

for line in infile1:
    line = line.split()
    for row in infile2:
        row = row.split()
        if line[4] == row[6]:
            if row[-1] == "-":
                line[3] == row[3]
                line[5] == row[7]
                line[6] == row[8]

我可以将一个文件作为元组列表读取,但不会加快速度,因为每次迭代时它都会从文件的开头到结尾。

2 个答案:

答案 0 :(得分:1)

要在python中执行此操作,您需要使用SNP编号索引file2的行;你可以用字典做到这一点:

rows2 = [ line.split() for line in infile2 ]
data2 = dict( (row[4], row) for row in rows2 )

for line in infile1:
    r = line.split()
    row2 = data2.get(r[2])
    if row2 and row2[-1] == "-":
        <make the replacement>

这假设文件2中的SNP ID当然是唯一的。

但是如果文件真的太大而无法容纳在内存中,或者你有很多这样做,那么正确的方法是将它们存储为两个数据库表。您描述的转换可以使用单个SQL查询来执行。从python中,您可以简单地将它们写入sqlite3数据库 - 无需安装外部服务器或软件。

答案 1 :(得分:0)

首先,您最好指定更好的数据格式。从示例数据看,数据显示为固定宽度列,但您的代码使用split(),这意味着可以将其视为以空格分隔的“CSV”(如果您的数据实际上没有空格)在每个单元格中。)

然后,您最好将数据转换为数据库。数据库具有特制的算法,可以处理您想要的,这是一个连接和选择方法,然后是更新操作。数据库优化适用,例如SNP列的索引,这可能会加速连接。

但是,如果您不想转换数据,或者如果您想要转换,则可以检查其他一些选项。我看的第一个是Blaze ecosystemBlaze library本身可以帮助您进行核外处理(如果您的文件与您说的一样大,则需要这些处理)。您还应该检查Pandas类似数据库的操作是否适合您,例如join()和索引。在这种情况下,您可以尝试类似

的内容
dataset3 = dataset1.join(dataset2, "SNP")
dataset3 = dataset3[dataset3.plus_minus_column=='-']
len1 = len(dataset1.columns)-1  # maybe -2?
dataset1[3,5,6,dataset3.index] = dataset3[:,(3+len1,7+len1,8+len1)]
之后

你已经完成了正确的索引。

您也可以尝试使用update()

dataset1.update(dataset2[dataset2.plus_minus_column=='-',(2,6,7)])

小心这些代码片段未经过测试(只是内存不足)而且我真的不知道它是否会在任何性能提升下给你带来任何性能提升。