两个DataFrame之间的模糊匹配缓慢

时间:2016-11-25 14:10:47

标签: python fuzzywuzzy

我有一个带有cli id和origin的数据框A(df_cam):

cli id |            origin
------------------------------------
123    | 1234 M-MKT XYZklm 05/2016

带有快捷方式和广告系列的DataFrame B(df_dict

shortcut |         campaign
------------------------------------
M-MKT    | Mobile Marketing Outbound

我知道,例如,来源1234 M-MKT XYZklm 05/2016的客户实际上来自广告系列Mobile Marketing Outbound,因为它包含关键字M-MKT

请注意,快捷方式是一个通用关键字,基于算法应该决定的内容。原点也可以是M-MarketingMMKTMob-MKT。我通过首先分析所有起源来手动创建快捷方式列表。我也正在使用正则表达式来清除origin,然后才能将其提取到程序中。

我希望通过快捷方式将客户来源与广告系列相匹配,并附上得分以查看差异。如下所示:

cli id | shortcut |         origin            |        campaign           | Score
---------------------------------------------------------------------------------
123    | M-MKT    | 1234 M-MKT XYZklm 05/2016 | Mobile Marketing Outbound | 0.93

以下是我的程序,但真的慢。 DataFrame A有~400.000行,另一个DataFrame B有~40行。

有没有办法让它更快?

from fuzzywuzzy import fuzz
list_values = df_dict['Shortcut'].values.tolist()

def TopFuzzMatch(tokenA, dict_, position, value):
    """
    Calculates similarity between two tokens and returns TOP match and score
    -----------------------------------------------------------------------
    tokenA: similarity to this token will be calculated
    dict_a: list with shortcuts
    position: whether I want first, second, third...TOP position
    value: 0=similarity score, 1=associated shortcut
    -----------------------------------------------------------------------
    """
    sim = [(fuzz.token_sort_ratio(x, tokenA),x) for x in dict_]
    sim.sort(key=lambda tup: tup[0], reverse=True)
    return sim[position][value]

df_cam['1st_choice_short'] = df_cam.apply(lambda x: TopFuzzMatch(x['cli_origin'],list_values,0,1), axis=1 )
df_cam['1st_choice_sim'] = df_cam.apply(lambda x: TopFuzzMatch(x['cli_origin'],list_values,0,0), axis=1 )

请注意,我还想计算第二和第三个最佳匹配来评估准确性。

修改

我找到了process.ExtractOne方法,但速度保持不变。 所以我的代码现在看起来像这样:

def TopFuzzMatch(token, dict_, value):
    score = process.extractOne(token, dict_, scorer=fuzz.token_sort_ratio)
    return score[value]

1 个答案:

答案 0 :(得分:1)

我找到了一个解决方案 - 在用正则表达式清理原始列(没有数字和特殊字符)之后,只有几百个重复的不同值,所以我只计算那些Fuzz算法,这显着改善了时间。

int numericValue = Character.getNumericValue(toInteger) + 1; // Note the parenthesis
String asString = String.valueOf(numericValue);
String prefix = str.subString(9);
String suffix = str.subString(10, str.length());
str = prefix + asString + suffix;