小编典典

如何根据最接近的匹配从另一个有效地替换大型数据框(100k +行)中的值?

python

因此,我使用莱文郡距离来查找最接近的匹配项,并使用此答案作为基础来替换大型数据框中的许多值:

import operator

def levenshteinDistance(s1, s2):
    if len(s1) > len(s2):
        s1, s2 = s2, s1

    distances = range(len(s1) + 1)
    for i2, c2 in enumerate(s2):
        distances_ = [i2+1]
        for i1, c1 in enumerate(s1):
            if c1 == c2:
                distances_.append(distances[i1])
            else:
                distances_.append(1 + min((distances[i1], distances[i1 + 1], distances_[-1])))
        distances = distances_
    return distances[-1]

def closest_match(string, matchings):
    scores = {}
    for m in matchings:
        scores[m] = 1 - levenshteinDistance(string,m)

    return max(scores.items(), key=operator.itemgetter(1))[0]

因此,在从具有类似大小的另一个大型数据帧(100k +行)中替换许多值时,将永远需要运行:(从最近半小时开始运行!)

results2.products = [closest_match(string, results2.products) 
                    if string not in results2.products else string 
                    for string in results.products]

有没有办法更有效地做到这一点?我出于相同的目的添加了if-else条件,这样,如果存在直接匹配,就不会涉及任何计算,而这些计算也将产生相同的结果。

样本数据

results

   products
0, pizza
1, ketchup
2, salami
3, anchovy
4, pepperoni
5, marinara
6, olive
7, sausage
8, cheese
9, bbq sauce
10, stuffed crust

results2

   products
0, salaaaami
1, kechap
2, lives
3, ppprn
4, pizzas
5, marinara
6, sauce de bbq
7, marinara sauce
8, chease
9, sausages
10, crust should be stuffed

我希望将值results2替换为最接近的匹配项results


阅读 212

收藏
2021-01-20

共1个答案

小编典典

因此,我采取了一些措施来提高速度,并使速度提高了近4800倍。

在此处发布内容可以使处理熊猫上任何CPU密集型任务的性能降低的人受益:

  1. 我没有像问题中那样一次替换掉所有内容,而是制作了一个替换字典,用每个数据帧中的唯一值进行替换,这使它从永远花费(我2小时后停止)到2分钟,因为有很多重复价值观。多数民众赞成在60倍加速:

    replacements = {string: closest_match(string, results2.products.unique())
              if string not in results2.products.unique() else string 
                for string in results.products.unique()}
    

    results.replace({‘products’:replacements}, inplace = True)

  2. 我使用了一个基于C的实现,它利用了:editdistance库来计算levenshtein距离。在研究中,我发现许多这样的任务都具有基于C的实现,例如矩阵乘法和搜索算法等都可以轻松获得。此外,您始终可以使用C编写模块并在python中使用它。 editdistance.eval('banana', 'bahama')1.71 µs ± 289 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)与我定义的函数levenshteinDistance('banana', 'bahama')进行了比较,后者34.4 µs ± 4.2 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)的速度提高了20倍。

  3. 然后,我通过并行性立即利用了所有核心。为此,我经历了多种选择,例如多处理和线程处理,但是它们都没有提供与modin.pandas一样快的比较结果。它的变化很小(只需输入一行即可modin.pands as pd代替import pandas as pd),并且运行优雅。它使以前的运行速度提高了约4倍。

这样一来,总的加速比达到了4800倍,整个过程瞬间就实现了。

2021-01-20