我需要在其第一列上合并83个文件,并且第一列中的id在文件之间并不总是相同的。由于这些文件每个都包含几百万行,因此我需要一种有效的计算方法来将它们合并成宽格式。
因此,我对this question by Stephen Rauch中的python答案做了一些修改。它将以正确的模式在目录中一个接一个地读取每个文件,创建一个包含id-value匹配的sampleID的字典,然后从所有词典中将每个id作为行调用。
from os import listdir
import fnmatch
import re
vcfs= fnmatch.filter(listdir("."), "pivotted_vaf_out*")
columns = []
data = {}
ids = set()
for filename in vcfs:
with open(filename, 'rU') as f:
key=re.findall(r"[0-9]+",filename)[0]
columns.append(key)
data[key] = {}
for line in f:
if line.strip():
id, value = line.strip().split()
try:
data[key][(id)] = value
except ValueError as exc:
raise ValueError(
"Problem in line: '{}' '{}' '{}'".format(
id, value, line.rstrip()))
ids.add((id))
print('\t'.join(['ID'] + columns))
for id in sorted(ids):
line = []
for column in columns:
line.append(data[column].get(id, './.'))
print('\t'.join([str(id)] + line))
我的输入和输出如下所示。
File1.tsv
chr1_13868_A_G 0/1
chr1_13896_C_A 0/1
chr1_14464_A_T 1/1
chr1_14653_C_T 0/1
File2.tsv
chr1_13868_A_G 0/1
chr1_14464_A_T 1/1
chr1_14654_G_T 1/1
File3.tsv
chr1_13868_A_G 0/1
chr1_13896_C_A 0/1
chr1_14464_A_T 1/1
chr1_14653_C_T 0/1
Together.tsv
ID 1 2 3
chr1_13868_A_G 0/1 0/1 0/1
chr1_13896_C_A 0/1 ./. 0/1
chr1_14464_A_T 1/1 1/1 1/1
chr1_14653_C_T 0/1 0/1 0/1
chr1_14654_G_T 1/1 ./. ./.
如果我分配了足够的内存,此代码可以完美地工作。我想知道有什么替代和有效的解决方案来合并/合并大量行数很大的文件。
答案 0 :(得分:0)
使用POSIX中已经可用的工具:sort
和join
。 Python通常会浪费内存(对象开销),并且在POSIX工具中已经为您完成了所有工作之后,您可能需要编写代码。 (我不知道是否存在现成的东西。)
此外,POSIX join
不需要内存中的文件即可发挥作用(它每次只能从每个文件读取一行),并且可以按顺序进行排序(因此,您只需要一个文件即可)一次)。
分别排序每个文件:
sort -t$'\t' -k1,1 File1.tsv > File1.sorted.tsv
sort -t$'\t' -k1,1 File2.tsv > File2.sorted.tsv
sort -t$'\t' -k1,1 File3.tsv > File3.sorted.tsv
然后将他们一一加入:
join -t$'\t' -a1 -a2 -e./. -o0,1.2,2.2 File1.sorted.tsv File2.sorted.tsv > join_2.tsv
join -t$'\t' -a1 -a2 -e./. -o0,1.2,1.3,2.2 join_2.tsv File3.sorted.tsv > join_3.tsv
不幸的是,您将需要列出join
中的所有字段(我不知道如何解决);您要连接的第一个文件中的每个数据列都需要-o0,
,然后是1.x
,从2开始(即join_2.tsv
有两个数据列,因此您需要{{1 }})后接1.2,1.3
。到第83个文件时,2.2
列表将变得很胖。 :(
很明显,编写一个循环(在bash中完全可能,尽管有点混乱),或者编写一个程序来生成所需的全部165条命令真是太棒了。您不是想要手动执行此操作:D
无论如何,语法解释:-o
要求对文件进行排序,并且排序顺序必须与join
使用的文件相同。因此,join
选项(对于-t
和sort
)都将制表符作为定界符,而join
选项确保-k1,1
仅考虑联接列,并且不像默认情况下那样将列作为主要排序标准(与其他列的关联消除歧义)加入。 sort
正在产生完整的外部联接,并且-a1 -a2
指定-e./.
应该用于空值。最后,./.
不会输出任何空字段(即使我们指定了join
),除非您用-e
(sheesh)列出输出字段。