Python – 基于相似度超过80的结果,在新列中为类别进行模糊匹配

huangapple go评论94阅读模式
英文:

Python - Fuzzy matching result in new column for category based on ratio over 80

问题

I would like to scan a folder to pick up all the files end with '.txt' and then create a data frame by creating a new column for categorization with similar file names (partial score of ratio >=80)

import os
path = '../../../files'
text_files = [f for f in os.listdir(path) if f.endswith('.txt')]
text_files

from fuzzywuzzy import fuzz
from fuzzywuzzy import process

s1 = "programmi.txt"
s2 = "programmi-2.txt"
fuzz.ratio(s1, s2)

The result I expect to see is like below:

Python – 基于相似度超过80的结果,在新列中为类别进行模糊匹配

英文:

I would like to scan a folder to pick up all the files end with '.txt' and then create a data frame by creating a new column for categorization with similar file names (partial score of ratio >=80)

  1. import os
  2. path = '../../../files'
  3. text_files = [f for f in os.listdir(path) if f.endswith('.txt')]
  4. text_files
  5. from fuzzywuzzy import fuzz
  6. from fuzzywuzzy import process
  7. s1 = "programmi.txt"
  8. s2 = "programmi-2.txt"
  9. fuzz.ratio(s1, s2)

The result I expect to see is like below:

Python – 基于相似度超过80的结果,在新列中为类别进行模糊匹配

答案1

得分: 1

这是一个使用两个for循环比较每个文本与其他所有文本以获得所需模糊比率的解决方案。

  1. import pandas as pd
  2. from fuzzywuzzy import fuzz
  3. from fuzzywuzzy import process
  4. txt_list = [
  5. "programmi.txt",
  6. "readl-001.txt",
  7. "dict_class124.txt",
  8. "readl-002.txt",
  9. "programmi-2.txt",
  10. "programmi-re.txt",
  11. "readl-003.txt",
  12. "dict_class125.txt",
  13. "dict_class1264.txt",
  14. "hello world"
  15. ]
  16. list_categorised_texts = []
  17. txt_category = []
  18. category_index = 0
  19. threshold = 80
  20. # two for loops since we need to compare each text to all the others
  21. for txt_1 in txt_list:
  22. if txt_1 not in list_categorised_texts: # if the first text of the current pair is not yet categorised, add as a new category
  23. category_index += 1
  24. list_categorised_texts.append(txt_1)
  25. txt_category.append(category_index)
  26. for txt_2 in txt_list:
  27. if txt_1 == txt_2: # we don't want to compare the same texts
  28. continue
  29. elif txt_2 in list_categorised_texts: # skip already classified texts
  30. continue
  31. else: # if txt_2 is similar, add to the list of classified texts with the corresponding category
  32. similarity = fuzz.ratio(txt_1, txt_2)
  33. if similarity >= threshold:
  34. list_categorised_texts.append(txt_2)
  35. txt_category.append(category_index)
  36. data = {
  37. 'texts': list_categorised_texts,
  38. 'category': txt_category
  39. }
  40. df = pd.DataFrame(data)
  41. print(df.to_markdown())

结果:

  1. | | texts | category |
  2. |---:|:-------------------|-----------:|
  3. | 0 | programmi.txt | 1 |
  4. | 1 | programmi-2.txt | 1 |
  5. | 2 | programmi-re.txt | 1 |
  6. | 3 | readl-001.txt | 2 |
  7. | 4 | readl-002.txt | 2 |
  8. | 5 | readl-003.txt | 2 |
  9. | 6 | dict_class124.txt | 3 |
  10. | 7 | dict_class125.txt | 3 |
  11. | 8 | dict_class1264.txt | 3 |
  12. | 9 | hello world | 4 |

警告:

请注意,此方法具有顺序依赖性:在下面的示例中,将dict_cl.txt与其他名称进行比较只导致一个匹配,而将dict_class12.txt与所有其他名称进行比较导致3个匹配。对于您的用例,我们假设每个组与其他组非常不同,这不应该是问题。但是,此示例显示在更复杂的情况下,成对比较有点棘手。

  1. print(fuzz.ratio('dict_cl.txt', 'dict_class125.txt')) # 79 -> not same category
  2. print(fuzz.ratio('dict_cl.txt', 'dict_class1264.txt')) # 76 -> not same category
  3. print(fuzz.ratio('dict_cl.txt', 'dict_class12.txt')) # 81 -> same category
  4. print("###")
  5. print(fuzz.ratio('dict_class12.txt', 'dict_cl.txt')) # 81 -> same category
  6. print(fuzz.ratio('dict_class12.txt', 'dict_class125.txt')) # 97 -> same category
  7. print(fuzz.ratio('dict_class12.txt', 'dict_class1264.txt')) # 94 -> same category
英文:

Here's a solution which uses two for loops to compare each text to all the others to obtain the fuzz ratio needed for the categorisations.

  1. import pandas as pd
  2. from fuzzywuzzy import fuzz
  3. from fuzzywuzzy import process
  4. txt_list = [
  5. "programmi.txt",
  6. "readl-001.txt",
  7. "dict_class124.txt",
  8. "readl-002.txt",
  9. "programmi-2.txt",
  10. "programmi-re.txt",
  11. "readl-003.txt",
  12. "dict_class125.txt",
  13. "dict_class1264.txt",
  14. "hello world"
  15. ]
  16. list_categorised_texts = []
  17. txt_category = []
  18. category_index = 0
  19. threshold = 80
  20. # two for loops since we need to compare each text to all the others
  21. for txt_1 in txt_list:
  22. if txt_1 not in list_categorised_texts: # if the first text of the current pair is not yet categorised, add as new category
  23. category_index += 1
  24. list_categorised_texts.append(txt_1)
  25. txt_category.append(category_index)
  26. for txt_2 in txt_list:
  27. if txt_1 == txt_2: # we don't want to compare the same texts
  28. continue
  29. elif txt_2 in list_categorised_texts: # skip already classified texts
  30. continue
  31. else: # if the txt_2 is similar, add to list of classified texts with corresponding category
  32. similarity = fuzz.ratio(txt_1, txt_2)
  33. if similarity >= threshold:
  34. list_categorised_texts.append(txt_2)
  35. txt_category.append(category_index)
  36. data = {
  37. 'texts': list_categorised_texts,
  38. 'category': txt_category
  39. }
  40. df = pd.DataFrame(data)
  41. print(df.to_markdown())

Result:

  1. | | texts | category |
  2. |---:|:-------------------|-----------:|
  3. | 0 | programmi.txt | 1 |
  4. | 1 | programmi-2.txt | 1 |
  5. | 2 | programmi-re.txt | 1 |
  6. | 3 | readl-001.txt | 2 |
  7. | 4 | readl-002.txt | 2 |
  8. | 5 | readl-003.txt | 2 |
  9. | 6 | dict_class124.txt | 3 |
  10. | 7 | dict_class125.txt | 3 |
  11. | 8 | dict_class1264.txt | 3 |
  12. | 9 | hello world | 4 |

Warning:

Please note that this approach has an order-dependency: In the example below, comparing dict_cl.txt to the other names only leads to one match, while comparing dict_class12.txt to all other names leads to 3 matches. For your use case, where we assume that each group is very distinct from each other, this should not be a problem. However, this example shows that pairwise comparisons are a bit tricky in more sophisticated situations.

  1. print(fuzz.ratio('dict_cl.txt', 'dict_class125.txt')) # 79 -> not same category
  2. print(fuzz.ratio('dict_cl.txt', 'dict_class1264.txt')) # 76 -> not same category
  3. print(fuzz.ratio('dict_cl.txt', 'dict_class12.txt')) # 81 -> same category
  4. print("###")
  5. print(fuzz.ratio('dict_class12.txt', 'dict_cl.txt')) # 81 -> same category
  6. print(fuzz.ratio('dict_class12.txt', 'dict_class125.txt')) # 97 -> same category
  7. print(fuzz.ratio('dict_class12.txt', 'dict_class1264.txt')) # 94 -> same category

huangapple
  • 本文由 发表于 2023年5月11日 03:37:18
  • 转载请务必保留本文链接:https://go.coder-hub.com/76222031.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定