Python RapidFuzz: ratio, partial_ratio, and token_sort_ratio
python rapidfuzz ratio partial ratio and token sort ratio: Learn how RapidFuzz's ratio, partial_ratio, and token_sort_ratio differ, when to use each, and how to apply...
python rapidfuzz ratio partial ratio and token sort ratio requires a clear understanding of the core syntax, runtime behavior, and practical implementation patterns demonstrated in the examples below.
Why Fuzzy Matching Needs More Than One Similarity Function
Exact string comparison fails in many real-world situations: a user types a product name with a typo, a database contains extra whitespace, or a list of names has inconsistent word order. RapidFuzz is a Python library that provides fast, C-accelerated fuzzy string matching. Its ratio, partial_ratio, and token_sort_ratio functions each handle a different kind of mismatch. Choosing the right one depends on the nature of the strings you are comparing.
The ratio Function: Whole-String Similarity
ratio computes the similarity between two strings based on the Levenshtein distance. It returns a score from 0 to 100, where 100 means the strings are identical. The score reflects the number of insertions, deletions, and substitutions needed to transform one string into the other.
from rapidfuzz import fuzz print(fuzz.ratio("hello world", "hello world")) # 100.0 print(fuzz.ratio("hello world", "hello worl")) # 95.0 print(fuzz.ratio("hello world", "world hello")) # 55.0
The last example shows a major limitation: ratio is sensitive to word order. Two strings with the same words but different order get a low score, even though they are semantically similar. This is where token_sort_ratio becomes useful.
The partial_ratio Function: Substring Matching
partial_ratio looks for the best matching substring of the shorter string within the longer string. It is designed for cases where one string is a truncated or extended version of the other. For example, comparing a full product name to a shorter alias.
from rapidfuzz import fuzz print(fuzz.partial_ratio("hello world", "hello")) # 100.0 print(fuzz.partial_ratio("hello world", "world")) # 100.0 print(fuzz.partial_ratio("hello world", "hello there")) # 71.4
In the first two cases, the shorter string appears exactly as a substring, so the score is 100. In the third, the best matching substring is "hello", which gives a score based on the similarity of "hello" and "hello there". This function is useful when you expect one string to be a fragment of the other.
The token_sort_ratio Function: Word Order Independence
token_sort_ratio splits both strings into tokens, sorts them alphabetically, and then computes the ratio on the sorted sequences. This makes the score insensitive to the order of words.
from rapidfuzz import fuzz print(fuzz.token_sort_ratio("hello world", "world hello")) # 100.0 print(fuzz.token_sort_ratio("python rapidfuzz", "rapidfuzz python")) # 100.0 print(fuzz.token_sort_ratio("hello world", "hello there world")) # 80.0
The first two examples produce 100 because the same words appear in both strings, just in a different order. The third example scores 80 because "there" is an extra token that changes the sorted sequence.
Comparing the Three Functions on Realistic Input
To see how these functions behave, consider a set of strings with different types of variation:
| Input pair | ratio | partial_ratio | token_sort_ratio |
|---|---|---|---|
| "hello world" vs "world hello" | 55.0 | 55.0 | 100.0 |
| "hello world" vs "hello" | 71.4 | 100.0 | 71.4 |
| "hello world" vs "hello there world" | 80.0 | 80.0 | 80.0 |
| "python rapidfuzz" vs "rapidfuzz python" | 55.0 | 55.0 | 100.0 |
The table shows that no single function works for every scenario. ratio is the baseline, partial_ratio is best when one string is a substring of the other, and token_sort_ratio is best when word order varies.
Performance Considerations and Choosing the Right Function
The computational cost of these functions depends on the length of the input strings. ratio uses a full Levenshtein distance calculation, which has O(nm) time complexity. partial_ratio is more expensive because it tries to align the shorter string at every possible position in the longer string, leading to O(nm) as well but with a higher constant factor. token_sort_ratio adds the cost of splitting and sorting tokens, which is O(n log n) for the sorting step, but the subsequent ratio calculation is on the sorted strings.
In practice, RapidFuzz is implemented in C and is significantly faster than pure Python implementations. Still, for very long strings, partial_ratio can be slow. If you know that word order is irrelevant, token_sort_ratio is a good choice because it normalizes the order before comparison. If you are comparing short strings like usernames or product codes, ratio is usually sufficient.
Practical Example: Matching Product Names
Consider a scenario where you have a list of product names from a database and a user query that may contain typos or different word order. You can use all three functions to score the query against each product and pick the best match.
from rapidfuzz import fuzz products = [ "Wireless Mouse", "USB-C Hub", "Laptop Stand", "Mechanical Keyboard", ] query = "keyboard mechanical" best_match = None best_score = 0 for product in products: score = fuzz.token_sort_ratio(query, product) if score > best_score: best_match = product best_score = score print(f"Best match: {best_match} (score: {best_score})")
Here, token_sort_ratio is appropriate because the user reversed the words. Using ratio would give a lower score and might miss the correct product.
Edge Cases and Limitations
These functions operate on raw strings. They do not normalize punctuation, case, or whitespace beyond what the tokenization does. For example, token_sort_ratio splits on whitespace, so punctuation attached to tokens can affect the score. If your data contains inconsistent punctuation, you may need to preprocess the strings before calling these functions.
Another limitation is that partial_ratio can produce misleadingly high scores when the shorter string is a very common substring. For instance, comparing "the" to a long text will return 100 even if "the" is not a meaningful match. In such cases, you might need to set a minimum length for the shorter string or combine scores from multiple functions.
Finally, all these functions are case-sensitive. If case does not matter for your application, convert both strings to lowercase before comparing.