嘿,伙计们,我有一个脚本,可以比较每个可能的用户,并判断他们的文本有多相似:

    dictionary = {
        t.id: (
            t.text,
            t.set,
            t.compare_string
        )
        for t in dataframe.itertuples()
    }

    highly_similar = []

    for a, b in itertools.combinations(dictionary.items(), 2):
        if a[1][2] == b[1][2] and not a[1][1].isdisjoint(b[1][1]):
            similarity_score = fuzz.ratio(a[1][0], b[1][0])

            if (similarity_score >= 95 and len(a[1][0]) >= 10) or similarity_score == 100:
                highly_similar.append([a[0], b[0], a[1][0], b[1][0], similarity_score])

这个脚本运行大约需要15分钟,数据帧包含120k个用户,因此比较每个可能的组合需要相当多的时间,如果我只是在for循环上写pass,则需要2分钟来循环所有值.

我try 对if语句和模糊分数使用filter()和map(),但性能更差.我试着尽可能地改进 playbook ,但我不知道如何进一步改进.

非常感谢您的帮助!

推荐答案

由于您没有附上数据,因此对其进行推理有点复杂,但我们可以看到多个地方可能会提供改进:

  1. 首先,让我们以一种比使用索引更容易推理的方式重写代码:

    dictionary = {
        t.id: (
            t.text,
            t.set,
            t.compare_string
        )
        for t in dataframe.itertuples()
    }
    
    highly_similar = []
    
    for a, b in itertools.combinations(dictionary.items(), 2):
        a_id, (a_text, a_set, a_compre_string) = a
        b_id, (b_text, b_set, b_compre_string) = b
    
        if (a_compre_string == b_compre_string
                and not a_set.isdisjoint(b_set)):
            similarity_score = fuzz.ratio(a_text, b_text)
    
            if (similarity_score >= 95 and len(a_text) >= 10)
                    or similarity_score == 100):
                highly_similar.append(
                    [a_id, b_id, a_text, b_text, similarity_score])
    
  2. 您似乎只关心具有相同compare_string个值的配对.因此,假设这不是所有对共享的东西,我们可以通过任何值来设置键,以覆盖更少的对.

    把一些数字放进go ,假设你有120K个输入,每val[1][2]个值有1K个值-然后不是覆盖120K*120K=14*10^9组合,而是有120个大小为1K的箱子(在每个箱子中,我们需要判断所有对)=120*1K*1K=120*10^6,这大约快val[1][2]0倍.如果每个箱子的元素少于1K,速度会更快.

    import collections
    
    # Create a dictionary from compare_string to all items
    # with the same compare_string
    items_by_compare_string = collections.defaultdict(list)
    for item in dictionary.items():
        compare_string = item[1][2]
        items_by_compare_string[compare_string].append(items)
    
    # Iterate over each group of items that have the same
    # compare string
    for item_group in items_by_compare_string.values():
        # Check pairs only within that group
        for a, b in itertools.combinations(item_group, 2):
            # No need to compare the compare_strings!
            if not a_set.isdisjoint(b_set):
                similarity_score = fuzz.ratio(a_text, b_text)
    
                if (similarity_score >= 95 and len(a_text) >= 10)
                        or similarity_score == 100):
                    highly_similar.append(
                        [a_id, b_id, a_text, b_text, similarity_score])
    
  3. 但是,如果我们想要更快呢?让我们看看剩下的操作:

    • 我们要判断两组是否共享至少一项
    • 我们有一个fuzz.ratio计算,它是一些外部函数,我假设它很重
    • 我们有一些比较,我们不太可能加快速度
    • 我们有一个列表的附加项,它在每个操作的平均("摊销")恒定时间上运行,所以我们不能真正加快速度

因此,我不认为我们可以合理地建议在没有额外知识的情况下进行任何加速.如果我们知道一些关于集合的知识,可以帮助优化哪些配对是相关的,我们可能能够进一步加快速度,但我认为这就是问题所在.

编辑:正如其他答案中所指出的,显然可以在多线程中运行代码.我假设您正在寻找一种算法更改,它可能会显著减少操作数,而不仅仅是在更多CPU上拆分这些操作.

Python相关问答推荐

重置PD帧中的值

搜索按钮不工作,Python tkinter

用两个字符串构建回文

如何将一组组合框重置回无 Select tkinter?

在Python中控制列表中的数据步长

使用Python TCP套接字发送整数并使用C#接收—接收正确数据时出错

如何反转一个框架中列的值?

PySpark:如何最有效地读取不同列位置的多个CSV文件

如何根据一定条件生成段id

是否需要依赖反转来确保呼叫方和被呼叫方之间的分离?

按最大属性值Django对对象进行排序

在不降低分辨率的情况下绘制一组数据点的最外轮廓

如何获得症状表达式的真实部分?

用考克斯回归的生存分析系列的真值是模棱两可的.

Chrome 122-如何允许不安全的内容?(不安全下载被阻止)

给定Pandas 列DataFrame中的一个值,在其他DataFrame中 Select 与该值最接近的N行

收到Firebase推送通知时,电话不会震动

Polars-to_Dicts().词典目录的顺序有保证吗?

使用通配符标识扩展名为的文件

允许在枚举中使用一组特定的未定义值