我有两个数据帧:
import pandas as pd
first_df = pd.DataFrame({'Full Name': ['Mulligan Nick & Mary', 'Tsang S C', 'Hattie J A C '],
'Address': ['270 Claude Road', '13 Sunnyridge Place', '18A Empire Road']})
second_df = pd.DataFrame({'Owner' : ['David James Mulligan', 'Brenda Joy Mulligan ', 'Helen Kwok Hattie'],
'Add Match': ['19 Dexter Avenue', 'Claude Road ', 'Building NO 512']})
是否只将Full Name
列中的第一个字符串与Owner
列中的最后一个字符串匹配。
如果有匹配,那么我想比较Address
和Add match
,看看是否有类似的值。如果第一个条件通过,但第二个条件失败,则不会将其添加到新的数据帧中。
使用左联接的结果如下:
new_df = first_df.merge(second_df, how='left', left_on = ['Full Name', 'Address'], right_on = ['Owner', 'Add Match'])
print(new_df.head())
Full Name Address Owner Add Match
0 Mulligan Nick & Mary 270 Claude Road NaN NaN
1 Tsang S C 13 Sunnyridge Place NaN NaN
2 Hattie J A C 18A Empire Road NaN NaN
然而,所需的输出看起来更像这样:
new_df
Name Address
---- --------
Brenda Joy Mulligan Claude Road
发布于 2021-03-30 14:16:51
受此answer的启发,您可以使用类似的解决方案。
TL;DR
first_df[['last_name', 'start_name']] = first_df['Full Name'].str.split(' ', 1, expand=True)
second_df['last_name'] = second_df['Owner'].str.split(' ').str[-1]
df_final = first_df.merge(second_df, how='inner', left_on=['last_name'], right_on=['last_name'])
address_matches = df_final.apply(lambda x: True if difflib.get_close_matches(x['Address'], [x['Add Match']], n=1, cutoff=0.8) else False, axis=1)
df_final = df_final[address_matches].drop(columns=['last_name', 'start_name', 'Full Name', 'Address']).rename(columns={'Owner':'Name', 'Add Match': 'Address'})
分步
最初,您提取您想要的姓氏密钥。
first_df[['last_name', 'start_name']] = first_df['Full Name'].str.split(' ', 1, expand=True)
second_df['last_name'] = second_df['Owner'].str.split(' ').str[-1]
PS:,我们在这里使用来自熊猫/numpy组合体的内置字符串方法,给出了您的说明。但是,如果它更适合您,您也可以应用下面显示的地址部分的相似方法(例如,difflib.get_close_matches
)。
接下来,执行这些数据文件的内部连接,以匹配last_name
键。
df_temp = first_df.merge(second_df, how='inner', left_on=['last_name'], right_on=['last_name'])
然后,应用具有所需相似性的difflib.get_close_matches
(我使用了cutoff=0.8
,因为在此值之上没有返回值)方法来标记哪些行包含匹配,然后只得到所需的行。
matches_mask = df_final.apply(lambda x: True if difflib.get_close_matches(x['Address'], [x['Add Match']], n=1, cutoff=0.8) else False, axis=1)
df_final = df_final[matches_mask].drop(columns=['last_name', 'start_name'])
Full Name Address Owner Add Match
Mulligan Nick & Mary 270 Claude Road Brenda Joy Mulligan Claude Road
最后,为了匹配在问题末尾发布的结果的格式,需要删除或重命名一些列。
df_final.drop(columns=['Full Name', 'Address']).rename(columns={'Owner':'Name', 'Add Match': 'Address'})
Owner Add Match
Brenda Joy Mulligan Claude Road
发布于 2021-03-30 11:51:51
您可以利用Python库中的difflib
模块来查找不同列之间的相似之处。例如,可以定义以下函数:
from difflib import SequenceMatcher
def compare_df(left, right, col: str):
left[f"{col}_match_ratio"] = 0
for value in left[col]:
best_ratio = 0
for other in right[col]:
result = SequenceMatcher(None, str(value), str(other)).ratio()
if result > best_ratio:
best_ratio = result
left.loc[left[col] == value, f"{col}_match_ratio"] = round(best_ratio, 2)
然后:
您只需确保要比较的列在您称为second_df
new_df = second_df.loc[second_df["Owner_match_ratio"] > 0.7, :]
https://stackoverflow.com/questions/66869963
复制相似问题