如何解决Fuzzywuzzy 合并多列 - 熊猫
我有 2 个数据框:
数据框 1:
path hierarchy
0 path3 path1/path2/path3
1 path2 path1/path2
2 path6 path1/path2/path4/path5/path6
数据帧 2:
path hierarcy unique_id
0 path2 path1/<random_string>/path2 1
1 Path3 <random_string>/Path_2/path3 2
2 path2 path1/Path2 3
3 pAth6 path1/path2/path4/path6 4
4 path6 path1/path2/path4/path5/path6 5
预期输出:
path hierarchy unique_id
0 path3 path1/path2/path3 2
1 path2 path1/path2 3
2 path6 path1/path2/path4/path5/path6 5
现在,我想填写从第二个数据帧到第一个数据帧的 unique_id。但是,有一些问题-
- 我无法直接根据
merge(left)
列执行path
2 个数据帧,因为正确的路径也取决于hierarchy
列。 - hierarchy 列中的字符串
not
完全相同。有一些差异,例如Path_2
和path2
。这同样适用于路径列。
我尝试了 fuzzy
匹配,但导致问题的是 hierarchy
列。我想从层次结构列的右侧开始匹配,然后向左移动,在每个级别上应用模糊匹配。
我不确定这是否是一个好方法。
基本上,要求是根据两个路径/层次结构列确定最完美的匹配。
用于创建数据框的字典:
df1 = pd.DataFrame({'path': {0: 'path3',1: 'path2',2: 'path6'},'hierarchy': {0: 'path1/path2/path3',1: 'path1/path2',2: 'path1/path2/path4/path5/path6'}})
df2 = pd.DataFrame({'path': {0: 'path2',1: 'Path3',2: 'path2',3: 'path6',4: 'path6'},'hierarcy': {0: 'path1/<random_string>/path2',1: '<random_string>/Path_2/path3',2: 'path1/Path2',3: 'path1/path2/path4/path6',4: 'path1/path2/path4/path5/path6'},'unique_id': {0: 1,1: 2,2: 3,3: 4,4: 5}})
df3 = pd.DataFrame({'path': {0: 'path3',2: 'path1/path2/path4/path5/path6'},'unique_id': {0: 2,1: 3,2: 5}})
感谢任何帮助。
解决方法
将 df1 和 df2 中的文本转换为小写:
df1['path'] = df1['path'].str.lower()
df2['path'] = df2['path'].str.lower()
合并:
result = pd.merge(df1,df2,on=['path'])
结果:
,我尝试了模糊匹配,但没有得到令人满意的结果,因为层次结构的顺序在这里至关重要。让我建议一种替代方法,将层次结构视为向量,然后检索 idx
中向量的 df2
与最近的空间接近度。在下面的示例中,路径被清理,由 /
分割并被分配一个唯一值。随后,针对 df1
中具有相同长度的向量计算 df2
中每个层次的空间距离:
import pandas as pd
import numpy as np
from scipy import spatial
df1 = pd.DataFrame({'path': {0: 'path3',1: 'path2',2: 'path6'},'hierarchy': {0: 'path1/path2/path3',1: 'path1/path2',2: 'path1/path2/path4/path5/path6'}})
df2 = pd.DataFrame({'path': {0: 'path2',1: 'Path3',2: 'path2',3: 'path6',4: 'path6'},'hierarchy': {0: 'path1/<random_string>/path2',1: '<random_string>/Path_2/path3',2: 'path1/Path2',3: 'path1/path2/path4/path6',4: 'path1/path2/path4/path5/path6'},'unique_id': {0: 1,1: 2,2: 3,3: 4,4: 5}})
#clean up paths
df1['hierarchy'] = df1['hierarchy'].str.lower().str.replace('_','').str.split('/')
df2['hierarchy'] = df2['hierarchy'].str.lower().str.replace('_','').str.split('/')
#create unique integer ids per path and map them to the dataframes
unique_dirs = set(list(np.concatenate(df1['hierarchy'].to_list() + df2['hierarchy'].to_list())))
dir_map = dict(zip(unique_dirs,range(len(unique_dirs))))
df1 = df1.assign(mapped=[list(map(dir_map.get,x)) for x in df1.hierarchy])
df2 = df2.assign(mapped=[list(map(dir_map.get,x)) for x in df2.hierarchy])
#calculate spatial distance to vectors from df2 with the same length,then return the matched hierarchy and idx
def check(row):
value = row['mapped']
arr = np.array(df2[df2['mapped'].str.len() == len(value)]['mapped'].to_list())
tree = spatial.KDTree(arr)
distances,indices = tree.query(value)
matches = df2[df2['mapped'].astype(str) == str(tree.data[indices].tolist())]
return matches['hierarchy'].tolist()[0],matches['unique_id'].tolist()[0]
df1[['match','idx']] = df1.apply(check,axis=1,result_type="expand")
结果df1
:
路径 | 层次结构 | 映射 | 匹配 | idx | |
---|---|---|---|---|---|
0 | path3 | ['path1','path2','path3'] | [0,1,3] | [' |
2 |
1 | path2 | ['path1','path2'] | [0,1] | ['path1','path2'] | 3 |
2 | path6 | ['path1','path4','path5','path6'] | [0,6,5,4] | ['path1','path6'] | 5 |
如果在同一位置存在多个具有随机路径的类似层次结构,代码可能会在计算上进行优化,并且将无法运行。在这种情况下,我不会分配随机整数,而是在计算距离之前使用语言模型检索路径的嵌入。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。