[python] 두 문자열 사이의 유사성 메트릭 찾기

파이썬에서 문자열이 다른 문자열과 비슷할 확률을 어떻게 얻습니까?

0.9 (90 %를 의미하는) 등의 10 진수 값을 얻고 싶습니다. 표준 Python 및 라이브러리를 사용하는 것이 좋습니다.

예 :

similar("Apple","Appel") #would have a high prob.

similar("Apple","Mango") #would have a lower prob.



답변

내장되어 있습니다.

from difflib import SequenceMatcher

def similar(a, b):
    return SequenceMatcher(None, a, b).ratio()

그것을 사용 :

>>> similar("Apple","Appel")
0.8
>>> similar("Apple","Mango")
0.0


답변

아마 당신은 문자열 사이의 거리를 설명하는 알고리즘을 찾고 있다고 생각합니다. 다음은 참조 할 수있는 것입니다.

  1. 해밍 거리
  2. 레 벤슈 테인 거리
  3. Damerau–Levenshtein 거리
  4. 자로-윙클러 거리

답변

솔루션 # 1 : 파이썬 내장

difflib 에서 SequenceMatcher 사용

장점 : 네이티브 파이썬 라이브러리, 별도의 패키지가 필요 없습니다.
단점 : 너무 제한적이며 문자열 유사성을위한 다른 좋은 알고리즘이 많이 있습니다.

:

>>> from difflib import SequenceMatcher
>>> s = SequenceMatcher(None, "abcd", "bcde")
>>> s.ratio()
0.75

솔루션 # 2 : 해파리 라이브러리

적용 범위가 좋고 문제가 거의없는 매우 훌륭한 라이브러리입니다. 그것은 지원
– Levenshtein 거리
– Damerau – Levenshtein 거리
– JARO의 거리
– JARO – 윈 클러 거리
– 경기 평가 접근법 비교
– 해밍 거리

장점 : 사용하기 쉽고 지원되는 알고리즘의 범위가 테스트되었습니다.
단점 : 네이티브 라이브러리가 아닙니다.

:

>>> import jellyfish
>>> jellyfish.levenshtein_distance(u'jellyfish', u'smellyfish')
2
>>> jellyfish.jaro_distance(u'jellyfish', u'smellyfish')
0.89629629629629637
>>> jellyfish.damerau_levenshtein_distance(u'jellyfish', u'jellyfihs')
1


답변

Fuzzy Wuzzy파이썬에서 Levenshtein 거리를 구현 하는 패키지 이며, 두 가지 별개의 문자열을 동일하게 고려하려는 특정 상황에서 도움이되는 도우미 함수가 있습니다. 예를 들면 다음과 같습니다.

>>> fuzz.ratio("fuzzy wuzzy was a bear", "wuzzy fuzzy was a bear")
    91
>>> fuzz.token_sort_ratio("fuzzy wuzzy was a bear", "wuzzy fuzzy was a bear")
    100


답변

다음과 같은 함수를 만들 수 있습니다.

def similar(w1, w2):
    w1 = w1 + ' ' * (len(w2) - len(w1))
    w2 = w2 + ' ' * (len(w1) - len(w2))
    return sum(1 if i == j else 0 for i, j in zip(w1, w2)) / float(len(w1))


답변

패키지 거리 에는 Levenshtein 거리가 포함됩니다 :

import distance
distance.levenshtein("lenvestein", "levenshtein")
# 3


답변

내장 SequenceMatcher은 큰 입력에서 매우 느립니다. diff-match-patch 로 수행하는 방법은 다음과 같습니다.

from diff_match_patch import diff_match_patch

def compute_similarity_and_diff(text1, text2):
    dmp = diff_match_patch()
    dmp.Diff_Timeout = 0.0
    diff = dmp.diff_main(text1, text2, False)

    # similarity
    common_text = sum([len(txt) for op, txt in diff if op == 0])
    text_length = max(len(text1), len(text2))
    sim = common_text / text_length

    return sim, diff