所以我有几个看起来像的文件:
snpID Gene
rs1 ABC1
rs2 ABC1
rs3 ABC25
rs4 PT4
rs5 MTND24
在不同的文件中会有其他snpID和Gene对,但是对于给定的snpID可能有重复,但相关的“Gene”关联可能不同。例如:
snpID Gene
rs100 URX1
rs95 KL4
rs1 ABC1
rs2 ABC1-MHT5
rs3 ABC25
rs4 PT4-FIL42
我想要做的是附加文件的所有内容,如果它们具有相同的snpID和Gene对,则删除重复项。然而,如果snpID的相应Gene不同,则它必须进入同一行 对于上面的示例,它应该如下所示:
snpID Gene
rs1 ABC1
rs2 ABC1, ABC1-MHT5
rs3 ABC25
rs4 PT4, PT4-FIL42
rs5 MTND2
rs100 URX1
rs95 KL4
我认为我可以通过创建词典来实现这一目标。
import glob
file_list = glob.glob('annotations.*')
dict_snps_genes = {}
for filename in file_list:
with open(filename) as fileA:
for line in fileA:
col0 = line.split()[0]
col1 = line.split()[1]
dict_snps_genes[col0] = col1
unique_dict_snps = {}
for key,value in dict_snps_genes:
if key not in unique_dict_snps.keys():
unique_dict_snps_genes[key] = value
我在进一步移动之前对此进行了测试,这给了我一个错误:
ValueError: too many values to unpack
PS:每个文件大约有8000个snpId-Gene对,并且有超过5个文件
如何超越这个想法!!
答案 0 :(得分:6)
您正在循环键,但尝试将它们分配给键和值变量:
for key,value in dict_snps_genes:
将其更改为循环.items()
:
for key,value in dict_snps_genes.items():
或者更好的是,如果在Python 2.x上,使用`.iteritems():
for key,value in dict_snps_genes.iteritems():
请注意,您阅读文件的方式,您只存储任何给定snpID的最后读取基因;如果找到该ID的另一个条目,则覆盖前一个。
就个人而言,我使用collections.defaultdict()
set
默认值:
import glob
import collections
file_list = glob.glob('annotations.*')
snps_genes = collections.defaultdict(set)
for filename in file_list:
with open(filename) as fileA:
for line in fileA:
snpid, gene = line.strip().split(None, 1)
snps_genes[snpid].add(gene)
现在snps_genes
中的值是基因组,每个基因都是唯一的。请注意,我将您的行分成两个空格(.split(None, 1)
),这样如果基因值中有任何空格,它将被存储为:
>>> 'id gene with whitespace'.split(None, 1)
['id', 'gene with whitespace']
使用`snpid,gene'作为左手赋值表达式Python获取分割的结果并将每个片段分配给一个单独的变量;这里有一个方便的技巧来保存一行代码。
要将其输出到新文件,只需循环生成snps_genes
结构。这是一个对所有事情进行分类的人:
for id in sorted(snps_genes):
print id, ', '.join(sorted(snps_genes[id]))
答案 1 :(得分:2)
我会把它写成如下:
from glob import glob
import fileinput
infiles = glob('annotations.*')
lines = fileinput.input(infiles)
rows = (line.split() for line in lines)
from collections import defaultdict
dd = defaultdict(list)
for row in rows:
dd[row[0]].append(row[1])
如果值是唯一的,则:
dd = defaultdict(set)
for row in rows:
dd[row[0]].add(row[1])
然后从那里开始......
答案 2 :(得分:1)
您可以将col1 = line.split()[1]
之后的行替换为:
if col0 in dict_snps_genes:
dict_snps_genes[col0].add(col1)
else:
dict_snps_genes[col0] = set([col1])
您可以阅读有关集here的更多信息。
答案 3 :(得分:1)
为什么不这样做:
import glob
files = glob.glob('annotations.*')
d = {}
for f in files:
with open(f) as f:
for line in f:
col0, col1 = line.split()
if col0 not in d:
d[col0] = [col1]
elif col1 not in d[col0]:
d[col0].append(col1)
将导致:
d = {
"rs95": ['KL4'],
"snpID": ['Gene'],
"rs1": ['ABC1'],
"rs2": ['ABC1', 'ABC1-MHT5'],
"rs3": ['ABC25'],
"rs4": ['PT4', 'PT4-FIL42'],
"rs5": ['MTND24'],
"rs100": ['URX1']
}