Linux合并巨大的gzip文件并保持只有交集

时间:2014-01-14 10:11:02

标签: linux merge gzip

我有一个名为“main.txt”的制表符分隔文件,我正在尝试从许多名为“chr1.info.gz”,“chr2.info.gz”,“chr3”的多个gz文件向此文件添加信息.info.gz“等等,包含比主文件多很多的行。请注意这些文件是使用gzip压缩的,我不能先解压缩它们并保存它们,因为它们是巨大的文件(我没有空间来执行此操作)。

我想将主文件中名为“name_id”(第6个字段)的列与多个不同文件(第3个字段)中名为“rs_id”的匹配列进行匹配,并仅添加来自这些文件的附加信息将行保存在主文件中:

main.txt文件如下所示:

number maf effect se pval name_id
34 0.7844 0.2197 0.0848  0.009585 snp1
78 0.6655 -0.1577 0.0796  0.04772 snp2

chr1.info.gz是这样的:

use pos rs_id a1 a2 a3 a4
f 10584 snp34 0 0 0 0
g 10687 snp35 0 0 0 0
t 13303 snp1 0 0 0 0

chr2.info.gz是这样的:

use pos rs_id a1 a2 a3 a4
s 13328 snp67 0 0 0 0    
g 10612 snp2 0 0 0 0
t 13303 snp10 0 0 0 0

......等等

我想从其他文件中获取添加信息的文件main.all.gz:

number maf effect se pval name_id use pos rs_id a1 a2 a3 a4
34 0.7844 0.2197 0.0848  0.009585 snp1 t 13303 snp1 0 0 0 0
78 0.6655 -0.1577 0.0796  0.04772 snp2 g 10612 snp2 0 0 0 0

我尝试过“加入”但看起来它需要解压缩文件,对它们进行排序并保存它们,我得到的消息是我没有足够的空间设备(我不认为我还有正确的代码):

join -1 6 -2 3 <(zcat main.txt | sort -k6,6) <(zcat chr1.info.gz | sort -k3,3 ) > try.txt

我尝试过使用awk,但我肯定做了几件事,因为它给了我一个空文件,而且在使用多个文件时我遇到了问题。

我一直在这上花一天时间,找不到一个好的解决方案, 你能帮我解决一下吗?

非常感谢! -f

1 个答案:

答案 0 :(得分:1)

我是用Python做的。

将主文件读入内存并输出一个字典(使用name_id作为键)。然后流式传输每个info.gzip文件,并根据您找到的内容扩展dict中的信息。 (如果您多次查找某行的信息,请考虑该怎么做。)

然后以您需要的格式写出dict。

这种方法有帮助吗?

#!/usr/bin/env python

import gzip
from collections import OrderedDict

mainData = OrderedDict()  # or just {} if order is not important
with open('main.txt') as mainFile:
  pos = None
  for line in mainFile:
    elements = line.split()
    if pos is None:
      pos = elements.index('name_id')
      mainHeaders = elements
    else:
      mainData[elements[pos]] = elements

infoHeaders = None
for infoFileName in [ 'chr1.info.gz', 'chr2.info.gz' ]:
  with gzip.open(infoFileName) as infoFile:
    pos = None
    for line in infoFile:
      elements = line.split()
      if pos is None:
        pos = elements.index('rs_id')
        if infoHeaders is None:
          infoHeaders = elements
        else:
          if infoHeaders != elements:
            print "headers in", infoFileName, "mismatch"  # maybe abort?
      else:
        key = elements[pos]
        try:
          mainData[key] += elements
        except KeyError:
          pass  # this key does not exist in main

with gzip.open('main.all.gz', 'w') as outFile:
  outFile.write(' '.join(mainHeaders + infoHeaders) + '\n')
  for key, value in mainData.iteritems():
    outFile.write(' '.join(value) + '\n')

我的结果是:

number maf effect se pval name_id use pos rs_id a1 a2 a3 a4
34 0.7844 0.2197 0.0848 0.009585 snp1 t 13303 snp1 0 0 0 0
78 0.6655 -0.1577 0.0796 0.04772 snp2 g 10612 snp2 0 0 0 0

它不期望或生成制表符分隔的文件(但为所有内容使用空格)。您的示例数据看起来就像是分隔符;-)但是您可以将输出代码中的' '(空格)(最后一行)更改为'\t'以使用选项卡作为分隔符。