获取多个字符串的相似度百分比

时间:2018-12-16 17:27:08

标签: python string similarity sentence-similarity

Python内是否有任何函数可以接受多行字符串并返回它们具有多少相似度的百分比?类似于SequenceMatcher,但包含多个字符串。

例如,我们有以下句子

Hello how are you?
Hi how are you?
hi how are you doing?
Hey how is your day?

我希望能够根据句子之间的相似程度获得一个百分比

假设我们有这三个句子

Hello how are you?
Hello how are you?
Hello how are you?

那么我们应该获得100%相似

但如果有

Hello how are you?
Hello how are you?
hola como estats?

然后我们应该将相似度提高到67%。

3 个答案:

答案 0 :(得分:1)

天真的,您可以按照以下方式做一些事情:

from collections import Counter 
from itertools import zip_longest

cases=[('Hello how are you?','Hello how are you?','Hello how are you?'),
       ('Hello how are you?','Hello how are you?','hola como estats?')]

for t in cases:    
    sums=[]
    for st in zip_longest(*t,fillvalue='|'):
        sums.append((st,(len(Counter(st))-1)/len(st)))
    print(t)
    print('\n'.join(map(str, sums)))   

打印:

('Hello how are you?', 'Hello how are you?', 'Hello how are you?')
(('H', 'H', 'H'), 0.0)
(('e', 'e', 'e'), 0.0)
(('l', 'l', 'l'), 0.0)
(('l', 'l', 'l'), 0.0)
(('o', 'o', 'o'), 0.0)
((' ', ' ', ' '), 0.0)
(('h', 'h', 'h'), 0.0)
(('o', 'o', 'o'), 0.0)
(('w', 'w', 'w'), 0.0)
((' ', ' ', ' '), 0.0)
(('a', 'a', 'a'), 0.0)
(('r', 'r', 'r'), 0.0)
(('e', 'e', 'e'), 0.0)
((' ', ' ', ' '), 0.0)
(('y', 'y', 'y'), 0.0)
(('o', 'o', 'o'), 0.0)
(('u', 'u', 'u'), 0.0)
(('?', '?', '?'), 0.0)
('Hello how are you?', 'Hello how are you?', 'hola como estats?')
(('H', 'H', 'h'), 0.3333333333333333)
(('e', 'e', 'o'), 0.3333333333333333)
(('l', 'l', 'l'), 0.0)
(('l', 'l', 'a'), 0.3333333333333333)
(('o', 'o', ' '), 0.3333333333333333)
((' ', ' ', 'c'), 0.3333333333333333)
(('h', 'h', 'o'), 0.3333333333333333)
(('o', 'o', 'm'), 0.3333333333333333)
(('w', 'w', 'o'), 0.3333333333333333)
((' ', ' ', ' '), 0.0)
(('a', 'a', 'e'), 0.3333333333333333)
(('r', 'r', 's'), 0.3333333333333333)
(('e', 'e', 't'), 0.3333333333333333)
((' ', ' ', 'a'), 0.3333333333333333)
(('y', 'y', 't'), 0.3333333333333333)
(('o', 'o', 's'), 0.3333333333333333)
(('u', 'u', '?'), 0.3333333333333333)
(('?', '?', '|'), 0.3333333333333333)

因此,第二种情况下的差异将略小于1/3,因为最终西班牙语句子中有两个相同的字符。

然后将序列减少到完全不同。

答案 1 :(得分:1)

您可以使用pandas来处理数据框,itertools.combinations可以从列表中计算2个字符串的组合,而difflib.SequenceMatcher可以用于相似度计算:

import pandas as pd
import itertools
from difflib import SequenceMatcher

def similarity(a,b):
    seq = SequenceMatcher(a=a, b=b)
    return seq.ratio()    

strings = ['Hello how are you?', 'Hi how are you?', 'hi how are you doing?', 'Hey how is your day?']
combinations = itertools.combinations(strings,2)

df = pd.DataFrame(list(combinations))
df['similarity'] = df.apply(lambda x: similarity(x[0],x[1]), axis=1)

df.similarity.mean()
0.68

答案 2 :(得分:0)

您可以使用numpyitertools.product创建成对相似矩阵。然后,您可以从该矩阵中提取所需的相似性度量。无论如何,您都需要提出适合您问题的指标(即成对量词)。

import itertools as it
import numpy as np


def similarity_check(sentences, metric):
    pairwise = np.fromiter(map(
        metric,
        it.product(sentences, sentences)),
    dtype=float).reshape(len(sentences), -1)
    # return pairwise[np.triu_indices(len(sentences), 1)].mean()  # Option 1.
    return pairwise.mean(axis=0).max()  # Option 2.


print(similarity_check([
    'Hello how are you?',
    'Hello how are you?',
    'Hello how are you?'
], lambda x: float(x[0] == x[1])))  # Plug in your own metric here.

print(similarity_check([
    'Hello how are you?',
    'Hello how are you?',
    'hola como estats?'
], lambda x: float(x[0] == x[1])))  # Plug in your own metric here.