【问题标题】:Fuzzywuzzy - copy info associated with a row from one df to another using a matchFuzzywuzzy - 使用匹配将与行关联的信息从一个 df 复制到另一个
【发布时间】:2021-11-23 23:31:01
【问题描述】:

我的目标是根据 2 个单独的数据框匹配地址信息。一个数据帧包含唯一值,而另一个数据帧不包含。我想从 df1 中获取唯一键,然后根据模糊匹配的相似程度将其复制到 df2。

这是一个例子:

df1 = 

index  address_df1           unique key     call #      Name        Sales amount
                      (value I want to copy)

1    123 nice road           Uniquekey1      11       jim bob             8
2    150  spring drive       Uniquekey2      151      jane doe            8213
3    240 happy lane          Uniquekey3      71       michael scott       909
4    80 sad parkway          Uniquekey4      1586     tracey jackson      109
5    122 big lane            Uniquekey5      161      lulu buzz           99
6    315 small pk            Uniquekey6      586      tinker bell         11
7    13  round rd ste 10     Uniquekey7      8601     jack ryan          681
8    97  square rd           Uniquekey8      66       peter paul         61968

df2 (*note address column in different place) =

index   cost center        country         address_df2  

1         1111              us              123 nice rd 
2         1111              us              97  square rd 
3         1112              us              13  round rd
4         1112              us              150  spring dr 

我希望最终的数据框看起来像这样:

RESULT 
df3 (with unique key) =

index   cost center(df2)      country(df2)      address_df2         **unique key(from df1)**   fuzzy match %

1         1111                  us              123 nice rd            Uniquekey1               90%
2         1111                  us              97  square rd          Uniquekey8               90%
3         1112                  us              13  round rd           Uniquekey7               90%
4         1112                  us              150  spring dr         Uniquekey2               90%

我试过了:

from fuzzywuzzy import process

THRESHOLD = 90

best_match = \
    df2['address_df2'].apply(lambda x: process.extractOne(x, df1['address_df1'],
                                                      score_cutoff=THRESHOLD))

我能够使用此代码找到匹配项,而且非常棒!但是,当我去合并两个数据框时,我无法获得匹配的地址。我认为来自 df1 的数据并没有对地址进行排序或匹配。

我已尝试使用此代码(如下)来匹配 2 个 dfs,但同样,地址未对齐。所以最终发生的是唯一 id 不正确。


df3 = pd.merge(df2, df1.set_index(best_match.apply(pd.Series)[2]),
               left_index=True, right_index=True, how='left')

【问题讨论】:

    标签: python pandas dataframe fuzzywuzzy


    【解决方案1】:

    extractOne返回的元组的第三项是df1的最佳匹配行的索引标签。因此,您可以使用locdf1 中选择unique key 列。

    # Prefer use thefuzz package
    from thefuzz import process
    
    THRESHOLD = 90
    
    best_match = lambda x: process.extractOne(x, df1['address_df1'])
    match = df2['address_df2'].apply(best_match).apply(pd.Series)
    
    df2['unique key'] = df1.loc[match[2], 'unique key'] \
                           .mask(match[1].lt(THRESHOLD).values) \
                           .values
    

    输出:

    >>> df2
       cost center country     address_df2  unique key
    1         1111      us     123 nice rd  Uniquekey1
    2         1111      us    97 square rd  Uniquekey8
    3         1112      us     13 round rd  Uniquekey7
    4         1112      us   150 spring dr  Uniquekey2
    5         1113      fr  26 chemin vert         NaN  # for testing
    
    >>> match
                        0    1  2
    1       123 nice road   92  1
    2        97 square rd  100  8
    3  13 round rd ste 10   90  7
    4    150 spring drive   90  2
    5       123 nice road   44  1  # for testing
    

    【讨论】:

    • @aero8991。你真的需要模糊匹配分数吗?
    • 好吧,我想我明白了。可能是因为score_cutoff。如果您没有超过 THRESHOLD 的响应,则返回的索引为 None。我会检查的
    • 工作正在进行中。
    • 做到了!非常感谢您的帮助,这真的会为我节省很多工作时间。非常感谢您在这方面的帮助!
    • 很高兴为您提供帮助。感谢您的支持:)
    【解决方案2】:

    试试这个:

    df3 = pd.concat([df2, best_match.apply(pd.Series).drop(2, axis=1)], axis=1).rename({0:'unique key', 1:'fuzzy match %'}, axis=1)
    

    输出:

    >>> df3
       index  cost-center country    address_df2          unique key  fuzzy match %
    0      1         1111      us    123-nice-rd       123-nice-road             92
    1      2         1111      us   97-square-rd        97-square-rd            100
    2      3         1112      us    13-round-rd  13-round-rd-ste-10             90
    3      4         1112      us  150-spring-dr    150-spring-drive             90
    

    【讨论】:

    • 感谢您发布此信息!我会测试它并让你知道。你能解释一下这里发生了什么吗?
    • 是的!非常简单,它将best_match(它的每一行)的每个匹配项转换为一个新的Series。然后,它只是将其附加到df2 的左侧。它还修复了列名。就这么简单。
    • 哦,好吧,让我看看我能不能为你做到这一点......
    • @aero8991,您能否将您的数据框添加到 dict 中以解决问题?像这样得到它:print(df.to_dict())。因为将这段文本转换为数据框真的很难,我需要再次这样做才能继续处理。
    • 看来Corralien的方法可能有效!我现在测试它。他有一个有趣的想法,将匹配过程作为一个函数,然后在另一个数据帧中定位唯一键
    猜你喜欢
    • 1970-01-01
    • 2020-04-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-06-09
    • 2023-02-02
    • 1970-01-01
    相关资源
    最近更新 更多