我有一个具有10个已解析地址的数据帧df_sample
,并将其与另一个具有成千上万个已解析地址记录df
的数据帧进行比较。 df_sample
和df
共享完全相同的结构:
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
放入新的数据框。一旦通过这些匹配创建了这个较小的新数据框,我将继续对city
,zip_code
等进行此操作。
df_match = df[fuzzy.ratio(df_sample['state'], df['state']) > 0.9]
除了不起作用。
我的目标是每次使用更严格的搜索条件时都缩小匹配的数量,并最终根据每个字段分别缩小范围而最终获得尽可能少匹配的数据框。但是我不确定如何对任何单个记录执行此操作。
答案 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:
这为您提供了两个DataFrame中的哪些行“相关”的信息 彼此。
优点是您不会生成完全交叉联接,并且(目前) 您只能对 state 列进行操作,而不要对完整行进行操作。
您没有描述最终结果应该是什么,但是我想一点 根据上述代码,您将可以继续进行操作。