2

所以我有一些看起来像这样的文件:

snpID  Gene
rs1  ABC1
rs2  ABC1
rs3  ABC25
rs4  PT4
rs5  MTND24

在不同的文件中会有其他的 snpID 和基因对,但给定的 snpID 可能有重复,但相关的相应“基因”可能不同。例如:

snpID  Gene
rs100  URX1
rs95  KL4
rs1  ABC1
rs2  ABC1-MHT5
rs3  ABC25
rs4  PT4-FIL42

我想要做的是附加文件的所有内容,如果它们具有相同的 snpID 和基因对,则删除重复项。然而,如果一个 snpID 的对应基因不同,它必须进入同一行对于上面的示例,它应该如下所示:

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个文件

关于如何克服这个问题的想法!

4

4 回答 4

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]))
于 2013-01-02T14:50:43.067 回答
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])

然后从那里去......

于 2013-01-02T14:56:35.923 回答
1

您可以将之后的行替换为col1 = line.split()[1]

if col0 in dict_snps_genes:
    dict_snps_genes[col0].add(col1)
else:
    dict_snps_genes[col0] = set([col1])

您可以在此处阅读有关套装的更多信息。

于 2013-01-02T14:56:21.957 回答
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']
}
于 2013-01-02T15:23:53.157 回答