【问题标题】:Can I find similar entries and group them together?我可以找到类似的条目并将它们组合在一起吗?
【发布时间】:2014-04-12 04:52:42
【问题描述】:

我有一个包含这种格式的用户输入的文件:

  • 用户正在搜索的书名,条目被搜索的次数

例子:

  • 时间的皱纹,100
  • 哈克贝利·费恩历险记,100
  • 时间皱纹,20
  • 彼得潘,100
  • 及时收敛,5
  • 哈克贝利·费恩,100
  • 哈克贝利费恩历险记,150
  • 时间皱纹,2

书名有变体:拼写错误、措辞不正确、顺序不正确或命名略有不同。因为它们,当列表按标题按 A->Z 排序时,标题不会全部组合在一起:

  • 时间的皱纹,100
  • 时间的皱纹,20
  • 及时收敛,5
  • 时间皱纹,2
  • 彼得潘,100
  • 哈克贝利费恩历险记,100
  • 哈克贝利·费恩,100
  • 哈克贝利费恩历险记,150

A Wrinkle in Time 标题分组在一起,Huckleberry Finn 标题在自己的组中,而每一行仍保留其原始各自的数字输入。

是否可以通过 Python 或 Ruby 基于模糊逻辑重新排序(可能使用 Levenshtein 距离,然后以这种方式分组)?如果是这样,什么是简单/直接的方法? Group Similar Entries in Python 的问题与我的情况类似,只是我使用的是字母字符串而不是数字。

【问题讨论】:

  • 有没有什么地方可以获得实际、正确书名的规范列表?因为那会让生活变得更简单......
  • 不幸的是没有。我几乎只是使用通过 Google Analytics 的“搜索词”用户行为部分导出的 CSV。 GA 中的“搜索词”工具通过解析 my-site.com/search?q= 的每个条目以及“search?q=”部分之后的内容来告诉我用户在搜索框中输入了什么。

标签: python ruby algorithm distance levenshtein-distance


【解决方案1】:

可以,我们使用FuzzyWuzzy 有一些很好的教程。基本上,如果我要这样做,我会使用递归函数来查找匹配项。

当我开始使用它时,我最初遇到了一些问题,所以我问了this question

如果您有一组已知项目来匹配事物,那就很简单了,但我的问题解决了您最初不想限制输入集的情况。

要开始使用,请参阅this example

【讨论】:

  • 谢谢!我一直在阅读 FuzzyWuzzy,这与使用 Hugh Bothwell 提到的已知良好标题列表的示例方式相结合,这给了我一个很好的起点!如果我有足够高的声誉,我会投票!
  • 太糟糕了,链接的例子已经不存在了。这正是是人们应该将示例复制到答案中的原因。 -1
【解决方案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

【讨论】:

  • 您应该在每个分数旁边添加分数,以便 OP 可以开始“学习”应该在哪里截止。此外,添加递归性后效果会更好
  • 谢谢你们!在重新阅读了这些建议并集思广益之后,我可以如何以及在何处获得所需的数据,我意识到我可以在我的数据库上运行查询并提取已知良好标题的列表!在关闭此线程之前,我将尝试一下并返回我的结果/问题。再次 - 谢谢!你们摇滚!
  • 我使用“Good-Known Titles”列表尝试了它(减去@PyNEwbie 提到的“学习”递归)我得到了这个:Traceback(最近一次通话最后一次):文件“显示标题模糊logic grouping.py”,第 1594 行,在 main() 文件中“显示标题模糊逻辑 grouping.py”,第 1585 行,在主搜索中 = [(best_title(title), int(num), title) for title ,num in search] 文件“显示标题模糊逻辑 grouping.py”,第 1579 行,在 read_csv head = next(incsv, None) _csv.Error: new-line character seen in unquoted field - 你需要在通用换行模式?
猜你喜欢
  • 2021-08-28
  • 1970-01-01
  • 2021-02-22
  • 1970-01-01
  • 2021-01-26
  • 2013-04-03
  • 2011-10-18
  • 1970-01-01
  • 2010-12-09
相关资源
最近更新 更多