Python 如何找到多个字符串之间的相似性并绘制它

Python 如何找到多个字符串之间的相似性并绘制它,python,Python,我有一个包含一列和10000个字符串的xls文件 我想做几件事 1-制作一张热图或一个聚类图,显示每个字符串与另一个字符串之间的相似性百分比 为了找出两者之间的相似性百分比,我找到了这篇文章,并试图让它为我工作 例如,我在一个xls文件中有这些,其中每行是一个字符串 AAAAAAAAAAAAAADPVAGDHENIVSDSTQASR AAAAAGPLQPETENAGTSV AAAAANNGAAPPDLSLMALAR AAAAASAVNDYYGTWGQK AAAAASGASNTDSSATKPK A

我有一个包含一列和10000个字符串的xls文件 我想做几件事

1-制作一张热图或一个聚类图,显示每个字符串与另一个字符串之间的相似性百分比

为了找出两者之间的相似性百分比,我找到了这篇文章,并试图让它为我工作

例如,我在一个xls文件中有这些,其中每行是一个字符串

AAAAAAAAAAAAAADPVAGDHENIVSDSTQASR
AAAAAGPLQPETENAGTSV
AAAAANNGAAPPDLSLMALAR
AAAAASAVNDYYGTWGQK
AAAAASGASNTDSSATKPK
AAAAGFNWDDADVK
AAAAGFNWDDADVKK
我不知道如何使用这个例子,例如当我有许多组合时 例如,在我的示例中,我有7个字符串,每个字符串都与另一个字符串相似

import xlrd
from difflib import SequenceMatcher

workbook = xlrd.open_workbook('data.xlsx')
    def similar(a, b):
        return SequenceMatcher(None, a, b).ratio()

由于您正在处理文本数据,因此可以使用该数据计算X和Y样本之间的余弦相似性。您还可以使用sklearn.feature_extraction.text.{TfidfVectorizer,CountVectorizer}将原始文档集合转换为数字向量 下面是一些代码:

from sklearn.metrics.pairwise import cosine_similarity
from sklearn.feature_extraction.text import CountVectorizer
text_data = load_function(...)
count_vect = CountVectorizer()
X_train_counts = count_vect.fit_transform(text_data)
similarities = cosine_similarity(X_train_counts)
percent_sim = similarities * 100

您需要使用嵌套循环,如下所示:

    L = ['NIVSDSTQASR', 'QPETENAGTSV', 'AAPPDLSLMALAR', 'AASAVNDYYGTWGQK']
    T = []
    for i in L:
        for j in L:
            if i != j:
                T.append((i+j))
    for k in T:
    print k

只需用序列匹配器函数替换“append”。

您所描述的称为字符串匹配,这是一类存在许多解决方案的问题:

  • 列文施坦
  • 贾卡德
  • 加罗
  • 仿射间隙
  • 针线
  • 史密斯·沃特曼
  • 余弦相似性
  • 欧几里得的

它们中的每一个都有适合某些问题的特征。基因组学研究推动了这一领域的许多创新,需要比较两组DNA序列。该列表应为您提供一个起点,以找到符合您需求的解决方案。但是Levenshtein对于大多数用例来说是最常见的。

以列表中的两个字符串为例,我提供了这种计算度量值的方法

>>> from collections import Counter
>>> stringA = 'AAAAAGPLQPETENAGTSV'
>>> stringB = 'AAAAANNGAAPPDLSLMALAR'
>>> unionSize = len(stringA) + len(stringB)
>>> A=Counter(list(stringA))
>>> B=Counter(list(stringB))
>>> A
Counter({'A': 6, 'G': 2, 'E': 2, 'T': 2, 'P': 2, 'V': 1, 'Q': 1, 'S': 1, 'N': 1, 'L': 1})
>>> B
Counter({'A': 9, 'L': 3, 'N': 2, 'P': 2, 'G': 1, 'M': 1, 'S': 1, 'R': 1, 'D': 1})
>>> symDiff = set(A.keys()).symmetric_difference(set(B.keys()))
>>> symDiff
{'M', 'V', 'Q', 'E', 'T', 'D', 'R'}
>>> symDiffSize = 0
>>> for key in symDiff:
...     if key in A.keys():
...         symDiffSize += A[key]
...     else:
...         symDiffSize += B[key]
...         
>>> symDiffSize, unionSize
(9, 40)
如果两个字符串的所有字母都是相同的,那么它们的“对称差”中就没有字母了,这将使分母为零。这似乎意味着共同的字母越多,非共享的字母越少,分数越大。你可以取它的对数


我没有Excel。此代码接受可以从Excel中收集的字符串列表。它避免了多集(又名包)的冗余计算,以节省资源。此外,它返回一对,而不是一个比率,因为有时分母可以是零

from collections import Counter

strings = [
    'AAAAAAAAAAAAAADPVAGDHENIVSDSTQASR', 
    'AAAAAGPLQPETENAGTSV', 
    'AAAAANNGAAPPDLSLMALAR', 
    'AAAAASAVNDYYGTWGQK', 
    'AAAAASGASNTDSSATKPK', 
    'AAAAGFNWDDADVK', 
    'AAAAGFNWDDADVKK', 
    ]

class NikDistance():
    def __init__ (self, strings):
        self.stringLengths = [len(str) for str in strings]
        self.stringCounters = []
        for str in strings:
            self.stringCounters.append(Counter(list(str)))
    def __call__ (self, i, j):
        unionDiff = self.stringLengths[i] + self.stringLengths[j]
        symDiff = set(self.stringCounters[i].keys()).symmetric_difference(set(self.stringCounters[j].keys()))
        symDiffSize = 0
        for key in symDiff:
            if key in self.stringCounters[i].keys():
                symDiffSize += self.stringCounters[i][key]
            else:
                symDiffSize += self.stringCounters[j][key]
        return (symDiffSize, unionDiff)

nikDistance = NikDistance(strings)

for i in range(len(strings)):
    for j in range(i+1, len(strings)):
        print (strings[i], strings[j], nikDistance(i,j))
结果:

AAAAAAAAAAAAAADPVAGDHENIVSDSTQASR AAAAAGPLQPETENAGTSV (7, 52)
AAAAAAAAAAAAAADPVAGDHENIVSDSTQASR AAAAANNGAAPPDLSLMALAR (11, 54)
AAAAAAAAAAAAAADPVAGDHENIVSDSTQASR AAAAASAVNDYYGTWGQK (9, 51)
AAAAAAAAAAAAAADPVAGDHENIVSDSTQASR AAAAASGASNTDSSATKPK (9, 52)
AAAAAAAAAAAAAADPVAGDHENIVSDSTQASR AAAAGFNWDDADVK (13, 47)
AAAAAAAAAAAAAADPVAGDHENIVSDSTQASR AAAAGFNWDDADVKK (14, 48)
AAAAAGPLQPETENAGTSV AAAAANNGAAPPDLSLMALAR (9, 40)
AAAAAGPLQPETENAGTSV AAAAASAVNDYYGTWGQK (10, 37)
AAAAAGPLQPETENAGTSV AAAAASGASNTDSSATKPK (8, 38)
AAAAAGPLQPETENAGTSV AAAAGFNWDDADVK (15, 33)
AAAAAGPLQPETENAGTSV AAAAGFNWDDADVKK (16, 34)
AAAAANNGAAPPDLSLMALAR AAAAASAVNDYYGTWGQK (14, 39)
AAAAANNGAAPPDLSLMALAR AAAAASGASNTDSSATKPK (9, 40)
AAAAANNGAAPPDLSLMALAR AAAAGFNWDDADVK (12, 35)
AAAAANNGAAPPDLSLMALAR AAAAGFNWDDADVKK (13, 36)
AAAAASAVNDYYGTWGQK AAAAASGASNTDSSATKPK (6, 37)
AAAAASAVNDYYGTWGQK AAAAGFNWDDADVK (6, 32)
AAAAASAVNDYYGTWGQK AAAAGFNWDDADVKK (6, 33)
AAAAASGASNTDSSATKPK AAAAGFNWDDADVK (10, 33)
AAAAASGASNTDSSATKPK AAAAGFNWDDADVKK (10, 34)
AAAAGFNWDDADVK AAAAGFNWDDADVKK (0, 29)
考虑最后一项。总共有29个字符,没有(零)个字符不出现在两个字符串中


看倒数第二项。总共有34个字符。其中有十(10)个不同时出现在两个字符串中

你可能需要重新措辞。您发现的示例不够好,因为它显示了两个字符串之间的相似性,您需要每个字符串与其他字符串之间的相似性?@user3718294谢谢您的消息,是的。“你可以修改我的问题,我肯定会接受这些弦是怎么形成的?”比尔·贝尔说,“它们来自一个实验。”。每一个都显示了一个特定的分子,那么如果你要比较这两个字符串中的任意两个,考虑到它们的分子相似性,你会如何分配一个数字来表示它们的相似性?我已经喜欢你的答案了。然而,问题仍然存在,因为当我有这么多字符串时,如果你看我的问题,很难计算。我问我是如何用尽可能多的弦来做的?如果你修改你的问题。我肯定会接受它。这可能现在就可以了。它肯定会起作用,但是,有些事情不清楚,每次我得到两个整数值,例如(0,66),什么是0,什么是66?还可以显示哪个字符串与哪个字符串产生哪个值吗?例如,A1 A2:(0,66),A1 A3:(7,52)etcI更改了最后一行以显示产生结果的字符串。最后还有对结果的解释。