如何使用模糊模糊比将一个数据框中的值与另一个数据框中的列进行比较

时间:2019-12-12 20:30:55

标签: python pandas dataframe match fuzzywuzzy

我有一个具有10个已解析地址的数据帧df_sample,并将其与另一个具有成千上万个已解析地址记录df的数据帧进行比较。 df_sampledf共享完全相同的结构:

zip_code     city        state     street_number    street_name   unit_number   country
 12345    FAKEVILLE     FLORIDA          123           FAKE ST        NaN          US

我想做的是将df_sample中的每一行与df中的每一行进行匹配,从state开始,仅将fuzzy.ratio(df['state'], df_sample['state']) > 0.9放入新的数据框。一旦通过这些匹配创建了这个较小的新数据框,我将继续对cityzip_code等进行此操作。

df_match = df[fuzzy.ratio(df_sample['state'], df['state']) > 0.9]

除了不起作用。

我的目标是每次使用更严格的搜索条件时都缩小匹配的数量,并最终根据每个字段分别缩小范围而最终获得尽可能少匹配的数据框。但是我不确定如何对任何单个记录执行此操作。

3 个答案:

答案 0 :(得分:1)

我对fuzzy不熟悉,所以这更多是评论而不是答案。也就是说,您可以执行以下操作:

# cross join
df_merge = pd.merge(*[d.assign(dummy=1) for d in (df, df_sample)],
                    on='dummy', how='left'
                   )

filters = pd.DataFrame()

# compute the fuzzy ratio for each pair of columns
for col in df.columns:
    filters[col] = (df_merge[[col+'_x', col+'_y']]
                       .apply(lambda x: fuzzy.ratio(x[col+'_x'], x[col+'_y']), axis=1) 
                   )

# filter only those with ratio > 0.9
df_match = df_merge[filter.gt(0.9).all(1)]

答案 1 :(得分:1)

创建数据框

import pandas as pd
from fuzzywuzzy import fuzz 

df = pd.DataFrame({'key': [1, 1, 1, 1, 1],
                   'zip': [1, 2, 3, 4, 5],
                   'state': ['Florida', 'Nevada', 'Texas', 'Florida', 'Texas']})

df_sample = pd.DataFrame({'key': [1, 1, 1, 1, 1],
                          'zip': [6, 7, 8, 9, 10],
                          'state': ['florida', 'Flor', 'NY', 'Florida', 'Tx']})

merged_df = df_sample.merge(df, on='key')
merged_df['fuzzy_ratio'] = merged_df.apply(lambda row: fuzz.ratio(row['state_x'], row['state_y']), axis=1)
merged_df

您会得到每对的模糊比

    key  zip_x  state_x  zip_y  state_y  fuzzy_ratio
0     1      6  florida      1  Florida           86
1     1      6  florida      2   Nevada           31
2     1      6  florida      3    Texas           17
3     1      6  florida      4  Florida           86
4     1      6  florida      5    Texas           17
5     1      7     Flor      1  Florida           73
6     1      7     Flor      2   Nevada            0
7     1      7     Flor      3    Texas            0
8     1      7     Flor      4  Florida           73
9     1      7     Flor      5    Texas            0
10    1      8       NY      1  Florida            0
11    1      8       NY      2   Nevada           25
12    1      8       NY      3    Texas            0
13    1      8       NY      4  Florida            0
14    1      8       NY      5    Texas            0
15    1      9  Florida      1  Florida          100
16    1      9  Florida      2   Nevada           31
17    1      9  Florida      3    Texas           17
18    1      9  Florida      4  Florida          100
19    1      9  Florida      5    Texas           17
20    1     10       Tx      1  Florida            0
21    1     10       Tx      2   Nevada            0
22    1     10       Tx      3    Texas           57
23    1     10       Tx      4  Florida            0
24    1     10       Tx      5    Texas           57

然后过滤掉不需要的内容

mask = (merged_df['fuzzy_ratio']>80)
merged_df[mask]

结果:

    key  zip_x  state_x  zip_y  state_y  fuzzy_ratio
0     1      6  florida      1  Florida           86
3     1      6  florida      4  Florida           86
15    1      9  Florida      1  Florida          100
18    1      9  Florida      4  Florida          100

答案 2 :(得分:1)

您写道 df 具有很多行, 因此完全交叉联接然后消除可能会导致您的代码 内存不足。

看看另一种需要更少内存的解决方案:

minRatio = 90
result = []
for idx1, t1 in df_sample.state.iteritems():
    for idx2, t2 in df.state.iteritems():
        ratio = fuzz.WRatio(t1, t2)
        if ratio > minRatio:
            result.append([ idx1, t1, idx2, t2, ratio ])
df2 = pd.DataFrame(result, columns=['idx1', 'state1', 'idx2', 'state2', 'ratio'])

它包含两个在两个DataFrame上运行的嵌套循环。 结果是一个包含包含以下行的DataFrame:

    df_sample 中的
  • index和 state
  • df 中的
  • index和 state
  • 比率。

这为您提供了两个DataFrame中的哪些行“相关”的信息 彼此。

优点是您不会生成完全交叉联接,并且(目前) 您只能对 state 列进行操作,而不要对完整行进行操作。

您没有描述最终结果应该是什么,但是我想一点 根据上述代码,您将可以继续进行操作。