我可以找到相似的条目并将它们分组吗?

1 投票
2 回答
1489 浏览
提问于 2025-04-17 21:28

我有一个文件,里面记录了用户输入的信息,格式是这样的:

  • 用户搜索的书名,搜索次数

举几个例子:

  • A Wrinkle in Time, 100
  • The Adventures of Huckleberry Finn, 100
  • Wrinkle in Time, 20
  • Peter Pan, 100
  • rinkle in time, 5
  • Huckleberry Finn, 100
  • Adventures of Huckleberry Finn, 150
  • Time wrinkle, 2

书名有很多不同的写法,比如拼写错误、用词不当、顺序不对,或者名字稍微不同。因为这些原因,当我们按字母顺序(A到Z)对列表进行排序时,书名不会被归为一类:

  • A Wrinkle in Time, 100
  • Wrinkle in Time, 20
  • rinkle in time, 5
  • Time wrinkle, 2
  • Peter Pan, 100
  • The Adventures of Huckleberry Finn, 100
  • Huckleberry Finn, 100
  • Adventures of Huckleberry Finn, 150

A Wrinkle in Time 这些书名被归为一组,而 Huckleberry Finn 的书名又是另一组,每一行仍然保留了它原来的搜索次数。

有没有办法通过模糊逻辑(比如使用 Levenshtein 距离来进行分组)在 Python 或 Ruby 中重新排序这些书名?如果可以的话,有什么简单直接的方法呢?这个问题 在 Python 中分组相似条目 和我的情况类似,只不过我用的是字母字符串而不是数字。

2 个回答

2

如果你能得到一个已知有效的标题列表,那会让你的工作轻松很多:

import csv
from fuzzywuzzy import process
from itertools import groupby

good_titles = [
    "a wrinkle in time",
    "the adventures of huckleberry finn",
    "peter pan"
]
def best_title(title):
    return process.extractOne(title.lower(), choices=good_titles)[0]

def read_csv(fname, header=False, **kwargs):
    with open(fname, "rb") as inf:
        incsv = csv.reader(inf, **kwargs)
        if header:
            head = next(incsv, None)
        for row in incsv:
            yield row

def main():
    searches = read_csv("search_data.csv", header=True)
    searches = [(best_title(title), int(num), title) for title,num in searches]
    searches.sort(key=lambda x: (x[0], -x[1], x[2]))

    for key,items in groupby(searches, lambda s:s[0]):
        for bt, num, t in items:
            print("{:40} {:>5}".format(t, num))
        print('')

if __name__=="__main__":
    main()

会产生

A Wrinkle in Time                          100
Wrinkle in Time                             20
rinkle in time                               5
Time wrinkle                                 2

Peter Pan                                  100

Adventures of Huckleberry Finn             150
Huckleberry Finn                           100
The Adventures of Huckleberry Finn         100
2

当然可以,我们使用的是 FuzzyWuzzy。网上有一些不错的教程。简单来说,如果我要做这个,我会用一个递归函数来找匹配的东西。

我刚开始用的时候遇到了一些问题,所以我问了 这个问题

如果你有一组已知的项目来进行匹配,那就简单多了,但我问的问题是关于你一开始不想限制输入集合的情况。

不过要开始的话,可以看看 这个例子

撰写回答