首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >将字典与其本身进行比较,但如果已经比较,则避免对键进行两次比较

将字典与其本身进行比较,但如果已经比较,则避免对键进行两次比较
EN

Stack Overflow用户
提问于 2017-07-21 08:07:44
回答 2查看 73关注 0票数 2

请再帮我一次。

我有一个名为vf_to_cluster.txt的文件,如下所示:

由此,我制作了一个名为vf_accession_to_cluster_groups的字典,其中键是vf_accession (AI0.)值是群集组(['1','2','3'...])的列表。

我是用这种方式编写代码的(我知道这不是一个很好的代码,但我现在可以用我所知道的(对不起)来完成):

代码语言:javascript
复制
f = 'script_folder/vf_to_cluster.txt'
vf_accession_to_cluster_groups = {}

with open(f, 'r') as f6:
    for lines in f6.readlines():
        lines = lines.replace('[', '')
        lines = lines.replace(']', '')
        lines = lines.replace(',', '')
        lines_split = lines.strip().split(' ')
        vf_keys = lines_split[0]
        cluster_values = lines_split[1:]
        vf_accession_to_cluster_groups[vf_keys] = cluster_values

在得到这本字典之后,我的主要目标是看看有多少vf_accessions (AI0.)共享相同的群集组。例如,我可以说AI001和AI002共享4个集群组,这意味着这两个vf_accession可能是相同的或非常接近的(由相同的基因编码)。

我做了这个代码:

代码语言:javascript
复制
for vf_1 in vf_accession_to_cluster_groups.keys():
    print '-'*40
    for vf_2 in (vf_accession_to_cluster_groups.keys():
        res = 0 
        if vf_1 != vf_2:
            for i in vf_accession_to_cluster_groups[vf_1]:
                for j in vf_accession_to_cluster_groups[vf_2]:
                    if i == j : 
                        res = res + 1

            print vf_1, vf_2, res

我得到了这样的东西:

我设法放弃了这样的比较: AI001 AI001或AI002 AI002.

通过使用if vf_1 != vf_2

但是我不能不允许这样的比较: AI014,AI015,然后,我的代码用另一种方式-- AI015 AI014 --对它们进行比较,所以基本上,我想要的是放弃这种比较类型。如果比较过一次,就不要再用另一种方式来比较。有人能帮我吗?

此外,如果任何生物信息学家看到我的矩阵-ish,您是否认为我应该将集群列表的大小包括到我的vf_accession比较中,就像这样:

代码语言:javascript
复制
dist = float(res) / len(set(vf_accession_to_cluster_groups[vf_1] + vf_accession_to_cluster_groups[vf_2]))

谢谢大家的帮助。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2017-07-23 09:12:59

如果您没有数百万个键,您可以将这些键存储在列表中并对它们进行排序(使结果具有可读性)。

代码语言:javascript
复制
cluster_groups = list(vf_accession_to_cluster_groups.keys())
cluster_groups.sort()

现在,您可以使用enumerate循环所有键(除了最后一个键,因为不需要将其与其自身进行比较):

代码语言:javascript
复制
for index, vf_1 in enumerate(cluster_groups[:-1]):

对于所有键的比较循环,在您刚刚用于外部循环的键之后。

代码语言:javascript
复制
    for vf_2 in cluster_groups[index + 1:]:

完整代码

代码语言:javascript
复制
cluster_groups = list(vf_accession_to_cluster_groups.keys())
cluster_groups.sort()

for index, vf_1 in enumerate(cluster_groups[:-1]):
    print('-'*40)
    for vf_2 in cluster_groups[index + 1:]:
        res = 0 
        for i in vf_accession_to_cluster_groups[vf_1]:
            for j in vf_accession_to_cluster_groups[vf_2]:
                if i == j : 
                    res = res + 1

        print(vf_1, vf_2, res)

一些小建议

  • 将结果存储在字典中,以便稍后检索它们。你可以用一本字典。
  • 如果要检查某项是否在列表中,只需使用 if item in my_list:

更新代码

代码语言:javascript
复制
cluster_groups = list(vf_accession_to_cluster_groups.keys())
cluster_groups.sort()

results = dict()

for index, vf_1 in enumerate(cluster_groups[:-1]):
    print('-'*40)
    results[vf_1] = dict()
    for vf_2 in cluster_groups[index + 1:]:
        res = 0 
        for i in vf_accession_to_cluster_groups[vf_1]:
            if i in vf_accession_to_cluster_groups[vf_2]:
                res = res + 1

        print(vf_1, vf_2, res)
        results[vf_1].update({vf_2: res})


def get_results(key1, key2, results):
    if key1 > key2:
        key1, key2 = key2, key1

    if results.get(key1):
        return results[key1].get(key2)
    return None
票数 1
EN

Stack Overflow用户

发布于 2017-07-26 10:40:37

您可以使用itertools.combinations只获取每对一次。

在下面的代码中,我定义了一个Accession类来表示文件一行中包含的信息:访问ID (key属性)和集群(clusters属性)。集群以集合的形式存储,这使得计算两种访问之间共有的集群数变得很容易。这是在nb_common方法中实现的,只需取两个集合之间的交集(&)的长度。Accession是从文件中的每一行创建的,这要归功于__init__方法中的代码。加入的列表被传递给combinations函数,2作为第二个参数,因为我们需要一对附加项。我们在结果对上循环,并使用nb_common方法获得当前对的两个可访问性之间的公共集群数。

这里,我还使用sys.argv[1]作为命令行中的第一个参数来获取文件。

代码语言:javascript
复制
#!/usr/bin/env python

import sys
from itertools import combinations

class Accession(object):
    """This represents an accession and the corresponding clusters."""
    def __init__(self, line):
        line_parts = line.strip().split(" ")
        self.key = line_parts[0]
        # "".join(...) re-creates a string representing the list of clusters
        # [1:-1] eliminates the brackets
        self.clusters = set("".join(line_parts[1:])[1:-1].split(","))

    def nb_common(self, other):
        return len(self.clusters & other.clusters)

with open(sys.argv[1], "r") as cluster_file:
    accessions = [Accession(line) for line in cluster_file]

for (acc1, acc2) in combinations(accessions, 2):
    print acc1.key, acc2.key, acc1.nb_common(acc2)

我将该脚本称为:

代码语言:javascript
复制
$ ./compare_accessions.py vf_to_cluster.txt 
AI001 AI002 4
AI001 AI004 4
AI001 AI005 4
AI001 AI010 0
AI001 AI011 0
AI001 AI012 4
AI001 AI013 0
AI001 AI014 0
AI001 AI015 5
AI001 AI016 0
AI001 AI017 0
AI002 AI004 4
AI002 AI005 4
AI002 AI010 0
AI002 AI011 0
AI002 AI012 4
AI002 AI013 0
AI002 AI014 0
AI002 AI015 4
AI002 AI016 0
AI002 AI017 0
AI004 AI005 4
AI004 AI010 0
AI004 AI011 0
AI004 AI012 4
AI004 AI013 0
AI004 AI014 0
AI004 AI015 5
AI004 AI016 0
AI004 AI017 0
AI005 AI010 0
AI005 AI011 0
AI005 AI012 4
AI005 AI013 0
AI005 AI014 0
AI005 AI015 4
AI005 AI016 0
AI005 AI017 0
AI010 AI011 0
AI010 AI012 0
AI010 AI013 0
AI010 AI014 1
AI010 AI015 1
AI010 AI016 0
AI010 AI017 0
AI011 AI012 0
AI011 AI013 1
AI011 AI014 0
AI011 AI015 1
AI011 AI016 0
AI011 AI017 0
AI012 AI013 0
AI012 AI014 0
AI012 AI015 4
AI012 AI016 0
AI012 AI017 0
AI013 AI014 0
AI013 AI015 1
AI013 AI016 0
AI013 AI017 0
AI014 AI015 1
AI014 AI016 0
AI014 AI017 0
AI015 AI016 1
AI015 AI017 0
AI016 AI017 0

如何将公共集群的数量转化为一段距离似乎是一个很开放的问题。你可以在bioinformatics stackexchange site上问这个问题,不要忘了介绍你的生物学问题。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/45232360

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档