Tìm số liệu tương tự giữa hai chuỗi


283

Làm thế nào để tôi có xác suất của một chuỗi tương tự như một chuỗi khác trong Python?

Tôi muốn nhận được một giá trị thập phân như 0,9 (có nghĩa là 90%), v.v. Tốt nhất là với thư viện và Python chuẩn.

ví dụ

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

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

6
Tôi không nghĩ "xác suất" là thuật ngữ đúng ở đây. Trong mọi trường hợp, hãy xem stackoverflow.com/questions/682367/ trên
NPE

1
Từ bạn đang tìm kiếm là tỷ lệ, không phải xác suất.
Inbar Rose

1
Hãy nhìn vào khoảng cách Hamming .
Diana

2
Cụm từ này là 'số liệu tương tự' , nhưng có nhiều số liệu tương tự (Jaccard, Cosine, Hamming, Levenshein, v.v.) đã nói nên bạn cần chỉ định. Cụ thể bạn muốn một số liệu tương tự giữa các chuỗi; @hbprotoss liệt kê một số.
smci

Câu trả lời:


542

Có một xây dựng trong.

from difflib import SequenceMatcher

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

Sử dụng nó:

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

42
Xem câu trả lời tuyệt vời này so sánh SequenceMatchervới python-Levenshteinmô-đun. stackoverflow.com/questions/6690739/ từ
ssoler

1
Bài viết và công cụ thú vị: chủ tịch
Anthony Perot

7
Tôi rất muốn giới thiệu kiểm tra hiện toàn bộ difflib doc docs.python.org/2/library/difflib.html có được một get_close_matchesxây dựng trong, mặc dù tôi thấy sorted(... key=lambda x: difflib.SequenceMatcher(None, x, search).ratio(), ...)đáng tin cậy hơn, với tùy chỉnh sorted(... .get_matching_blocks())[-1] > min_matchkiểm tra
ThorSummoner

2
@ThorSummoner mang đến sự chú ý đến một hàm rất hữu ích ( get_closest_matches). Đó là một chức năng tiện lợi có thể là những gì bạn đang tìm kiếm, AKA đọc tài liệu! Trong ứng dụng cụ thể của tôi, tôi đã thực hiện một số kiểm tra / báo cáo lỗi cơ bản cho người dùng cung cấp đầu vào xấu và câu trả lời này cho phép tôi báo cáo cho họ các kết quả khớp tiềm năng "sự giống nhau" là gì. Tuy nhiên, nếu bạn không cần hiển thị sự tương tự, chắc chắn hãy xemget_closest_matches
svenevs

Điều này làm việc hoàn hảo. Đơn giản và hiệu quả. Thankyou :)
Karthic Srinivasan


45

Giải pháp số 1: Tích hợp Python

sử dụng SequenceMatcher từ difflib

ưu : thư viện python bản địa, không cần gói thêm.
Nhược điểm : quá hạn chế, có rất nhiều thuật toán tốt khác cho tính tương tự chuỗi ngoài kia.

ví dụ :
>>> from difflib import SequenceMatcher
>>> s = SequenceMatcher(None, "abcd", "bcde")
>>> s.ratio()
0.75

Giải pháp số 2: thư viện sứa

nó là một thư viện rất tốt với độ bao phủ tốt và một vài vấn đề. nó hỗ trợ:
- Khoảng cách Levenshtein - Khoảng cách
Damerau-Levenshtein
- Khoảng cách
Jaro - Khoảng cách Jaro-Winkler
- So sánh xếp hạng so sánh
- Khoảng cách Hamming

ưu điểm : dễ sử dụng, gam màu của các thuật toán được hỗ trợ, đã thử nghiệm.
Nhược điểm : không phải thư viện bản địa.

ví dụ :

>>> 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 Wuzzylà một gói thực hiện khoảng cách Levenshtein trong python, với một số hàm trợ giúp để trợ giúp trong các tình huống nhất định mà bạn có thể muốn hai chuỗi riêng biệt được coi là giống hệt nhau. Ví dụ:

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

Bạn có thể tạo một chức năng như:

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

nhưng tương tự ('appel', 'apple') cao hơn tương tự ('appel', 'ape')
tenstar

1
Hàm của bạn sẽ so sánh một chuỗi đã cho với các chuỗi khác. Tôi muốn một cách để trả về chuỗi có tỷ lệ tương tự cao nhất
answerSeeker

1
@SaulloCastro, if self.similar(search_string, item.text()) > 0.80:hoạt động ngay bây giờ. Cảm ơn,
answerSeeker


6

Nội dung SequenceMatcherrất chậm trên đầu vào lớn, đây là cách thực hiện với 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

Lưu ý, difflib.SequenceMatcher chỉ tìm thấy chuỗi kết hợp liền kề dài nhất, đây thường không phải là điều mong muốn, ví dụ:

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

Tìm sự tương đồng giữa hai chuỗi có liên quan chặt chẽ với khái niệm căn chỉnh trình tự cặp trong tin sinh học. Có nhiều thư viện dành riêng cho việc này bao gồm cả biopython . Ví dụ này thực hiện thuật toán Needman Wunsch :

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

Sử dụng biopython hoặc gói tin sinh học khác linh hoạt hơn bất kỳ phần nào của thư viện chuẩn python do có nhiều sơ đồ và thuật toán chấm điểm khác nhau. Ngoài ra, bạn thực sự có thể có được các chuỗi phù hợp để hình dung những gì đang xảy ra:

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

Bạn có thể tìm thấy hầu hết các phương pháp tương tự văn bản và cách chúng được tính toán theo liên kết này: https://github.com/luozhouyang/python-opes-similarity#python-opes-similarity Dưới đây là một số ví dụ;

  • Chuẩn hóa, số liệu, độ tương tự và khoảng cách

  • (Chuẩn hóa) tương tự và khoảng cách

  • Khoảng cách số liệu

  • Sự tương đồng và khoảng cách dựa trên bệnh zona (n-gram)
  • Levenshtein
  • Bình thường hóa Levenshtein
  • Levenshtein có trọng số
  • Damerau-Levenshtein
  • Sắp xếp chuỗi tối ưu
  • Jaro-Winkler
  • Hậu quả chung dài nhất
  • Số liệu kết quả chung dài nhất
  • N-Gram
  • Các thuật toán dựa trên Shingle (n-gram)
  • Q-Gram
  • Tương tự cosine
  • Chỉ số Jaccard
  • Hệ số xúc xắc
  • Hệ số chồng lấp (nghĩa là Szymkiewicz-Simpson)
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.