2つの文字列間の類似性メトリックを見つける


283

文字列がPythonの別の文字列と類似している確率を取得するにはどうすればよいですか?

0.9(90%を意味する)などの10進数値を取得したいのですが、できれば標準のPythonとライブラリを使用します。

例えば

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

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

6
ここでは「確率」はまったく正しい用語だとは思いません。いずれにしても、stackoverflow.com
questions /

1
あなたが探している言葉は確率ではなく比率です。
インバーローズ2013

1
ハミング距離を見てください。
ダイアナ

2
フレーズは「類似性メトリック」ですが、複数の類似性メトリック(Jaccard、Cosine、Hamming、Levensheinなど)があるため、どれを指定する必要があります。具体的には、文字列間の類似性メトリックが必要です。@hbprotossはいくつかをリストしました。
smci

回答:


542

内蔵されています。

from difflib import SequenceMatcher

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

それを使う:

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

42
比較この偉大な答えを参照してくださいSequenceMatcherpython-Levenshteinモジュールを。stackoverflow.com/questions/6690739/...
ssoler

1
興味深い記事とツール:chairnerd.seatgeek.com/…–
Anthony Perot

7
私は非常に全体difflibドキュメントのチェックアウトをお勧めしdocs.python.org/2/library/difflib.htmlがされてget_close_matches私が見つけたものの、内蔵のをsorted(... key=lambda x: difflib.SequenceMatcher(None, x, search).ratio(), ...)、より信頼性の高いカスタムで、sorted(... .get_matching_blocks())[-1] > min_matchチェック
ThorSummoner

2
@ThorSummonerは、非常に便利な関数(get_closest_matches)に注目を集めます。それはあなたが探しているものかもしれない便利な機能です、別名ドキュメントを読んでください!私の特定のアプリケーションでは、基本的なエラーチェック/悪い入力を提供するユーザーへのレポートを行っていました。この答えにより、潜在的な一致「類似性」が何であったかをユーザーにレポートできます。あなたが類似度を表示する必要がない場合は、しかし、間違いなくチェックアウトget_closest_matches
svenevs

これは完全に機能しました。シンプルで効果的。
ありがとうございました


45

ソリューション#1:Python組み込み

difflibのSequenceMatcherを使用する

長所:ネイティブPythonライブラリ。追加のパッケージは必要ありません。
短所:制限が多すぎます。文字列の類似性には他にも優れたアルゴリズムがたくさんあります。

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

解決策2:クラゲライブラリ

カバレッジが良く、問題が少ない非常に良いライブラリです。それはサポートします:
-レーベンシュタイン距離
-ダメラウ-レーベンシュタイン距離
-ジャロ距離
-ジャロ-ウィンクラー距離
-マッチレーティングアプローチの比較
-ハミング距離

長所:使いやすく、サポートされているアルゴリズムの範囲でテスト済み。
短所:ネイティブライブラリではありません。

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

26

Fuzzy Wuzzyは、Pythonでレーベンシュタイン距離を実装するパッケージです。2つの異なる文字列を同一と見なしたい場合に役立つヘルパー関数がいくつかあります。例えば:

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

9

次のような関数を作成できます。

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

しかし、similar( 'appel'、 'apple')は、similar( 'appel'、 'ape')よりも高い
tenstar

1
関数は、指定された文字列を他の文字列と比較します。最高の類似率を持つ文字列を返す方法が必要です
answerSeeker

1
@SaulloCastro、if self.similar(search_string, item.text()) > 0.80:今のところ機能します。おかげで、
answerSeeker


6

ビルトイン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

5

は、最長の連続する一致するサブシーケンスdifflib.SequenceMatcher のみを検出することに注意してください。これは、多くの場合、望ましいものではありません。次に例を示します。

>>> a1 = "Apple"
>>> a2 = "Appel"
>>> a1 *= 50
>>> a2 *= 50
>>> SequenceMatcher(None, a1, a2).ratio()
0.012  # very low
>>> SequenceMatcher(None, a1, a2).get_matching_blocks()
[Match(a=0, b=0, size=3), Match(a=250, b=250, size=0)]  # only the first block is recorded

2つの文字列間の類似性を見つけることは、バイオインフォマティクスにおけるペアワイズシーケンスアラインメントの概念と密接に関連しています。biopythonを含む、このための多くの専用ライブラリがあります。この例では、Needleman Wunschアルゴリズムを実装しています

>>> from Bio.Align import PairwiseAligner
>>> aligner = PairwiseAligner()
>>> aligner.score(a1, a2)
200.0
>>> aligner.algorithm
'Needleman-Wunsch'

多くの異なるスコアリングスキームとアルゴリズムが利用できるため、biopythonまたは別のバイオインフォマティクスパッケージを使用すると、python標準ライブラリのどの部分よりも柔軟になります。また、実際に一致するシーケンスを取得して、何が起こっているのかを視覚化できます。

>>> alignment = next(aligner.align(a1, a2))
>>> alignment.score
200.0
>>> print(alignment)
Apple-Apple-Apple-Apple-Apple-Apple-Apple-Apple-Apple-Apple-Apple-Apple-Apple-Apple-Apple-Apple-Apple-Apple-Apple-Apple-Apple-Apple-Apple-Apple-Apple-Apple-Apple-Apple-Apple-Apple-Apple-Apple-Apple-Apple-Apple-Apple-Apple-Apple-Apple-Apple-Apple-Apple-Apple-Apple-Apple-Apple-Apple-Apple-Apple-Apple-
|||-|-|||-|-|||-|-|||-|-|||-|-|||-|-|||-|-|||-|-|||-|-|||-|-|||-|-|||-|-|||-|-|||-|-|||-|-|||-|-|||-|-|||-|-|||-|-|||-|-|||-|-|||-|-|||-|-|||-|-|||-|-|||-|-|||-|-|||-|-|||-|-|||-|-|||-|-|||-|-|||-|-|||-|-|||-|-|||-|-|||-|-|||-|-|||-|-|||-|-|||-|-|||-|-|||-|-|||-|-|||-|-|||-|-|||-|-|||-|-|||-|-|||-|-
App-elApp-elApp-elApp-elApp-elApp-elApp-elApp-elApp-elApp-elApp-elApp-elApp-elApp-elApp-elApp-elApp-elApp-elApp-elApp-elApp-elApp-elApp-elApp-elApp-elApp-elApp-elApp-elApp-elApp-elApp-elApp-elApp-elApp-elApp-elApp-elApp-elApp-elApp-elApp-elApp-elApp-elApp-elApp-elApp-elApp-elApp-elApp-elApp-elApp-el

0

あなたは、テキストの類似性方法のほとんどを見つけることができ、それらは、このリンクの下に計算する方法:https://github.com/luozhouyang/python-string-similarity#python-string-similarity ここではいくつかの例。

  • 正規化、メトリック、類似性、距離

  • (正規化された)類似性と距離

  • メートル距離

  • 帯状疱疹(n-gram)ベースの類似性と距離
  • レーヴェンシュタイン
  • 正規化されたレーベンシュタイン
  • 加重レーベンシュタイン
  • ダメラウ=レヴェンシュタイン
  • 最適なストリング配置
  • ジャロ・ウィンクラー
  • 最長共通サブシーケンス
  • メトリック最長共通サブシーケンス
  • N-グラム
  • シングル(n-gram)ベースのアルゴリズム
  • Q-グラム
  • コサイン類似度
  • Jaccardインデックス
  • ソレンセン・ダイス係数
  • オーバーラップ係数(つまり、Symmkiewicz-Simpson)
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.