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

时间:2016-11-29 17:48:09

标签: python

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

1-制作热图或群集图显示每个字符串与另一个字符串之间的相似性百分比。

为了找到彼此之间的相似度百分比,我发现这篇文章Find the similarity percent between two strings并试图让它适合我

作为一个例子,我在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()

4 个答案:

答案 0 :(得分:1)

由于您正在处理文本数据,因此可以使用sklearn.metrics.pairwise.cosine_similarity来计算X和Y中样本之间的余弦相似度。您还可以使用sklearn.feature_extraction.text。{TfidfVectorizer,CountVectorizer}来转换原始集合文件到数字向量 这是一些代码:

var course = Number($('#choose-a-course').val());

答案 1 :(得分:1)

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

  • 的Levenshtein
  • 的Jaccard
  • 哈罗
  • Affine Gap
  • NeedlemanWunch
  • 史密斯-Waterman算法
  • Cosine Similarity
  • 欧几里得

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

答案 2 :(得分:1)

从列表中的两个字符串作为样本,我提供了这种计算度量的方法。

>>> 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)

如果两个字符串都有共同的字母,那么它们的'对称差异'中会有 no 字母,这会使分母为零。这似乎意味着共同的字母越多,未共享的字母越少,分数越大。你也许可以取其对数。

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

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)个不出现在两个字符串中。

答案 3 :(得分:0)

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

    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

只需替换"追加"使用序列匹配器功能。