我需要合并两个不同的数据框,并且在合并发生之前需要清理合并列('title')。示例数据示例如下所示;
data1 = pd.DataFrame({'id': ['a12bcde0','b20bcde9'], 'title': ['a.b. company','company_b']})
data2 = pd.DataFrame({'serial_number': ['01a2b345','10ab2030','40ab4060'],'title':['ab company','company_b (123)','company_f']})
正如预期的那样,合并将不会在第一个标题上成功。我一直在使用replace()
方法,但它很快就无法管理,因为我有100个标题需要纠正,因为拼写,区分大小写等。
关于如何最好地清理和合并数据的任何其他建议?
完整示例:
import pandas as pd
import numpy as np
data1 = pd.DataFrame({'id': ['a12bcde0','b20bcde9'], 'title': ['a.b. company','company_b']})
data2 = pd.DataFrame({'serial_number': ['01a2b345','10ab2030','40ab4060'],'title':['ab company','company_b (123)','company_f']})
data2['title'].replace(regex=True,inplace=True,to_replace=r"\s\(.*\)",value=r'')
replacements = {
'title': {
r'a.b. company *.*': 'ab company'
}
}
data1.replace(replacements, regex=True, inplace=True)
pd.merge(data1, data2, on='title')
答案 0 :(得分:2)
首先,对于这个问题没有完美的解决方案,但我建议做两件事:
你会发现这并不完美,因为即使这个例子也没有100%的效率。
首先,让我们首先让你的例子变得更复杂,引入一个常规拼写错误(coampany_b
而不是company_b
,这些东西不会被下面的简单清理所吸引。< / p>
data1 = pd.DataFrame({'id': ['a12bcde0','b20bcde9', 'csdfsjkbku'], 'title': ['a.b. company','company_b', 'coampany_b']})
data2 = pd.DataFrame({'serial_number': ['01a2b345','10ab2030','40ab4060'],'title':['ab company','company_b (123)','company_f']})
然后让我们假设您只希望[a-z]字符为@MaartenFabré提到。所以,让我们小写一切,删除其他任何东西。
data1['cleaned_title'] = data1['title'].str.lower().replace(regex=True,inplace=False,to_replace=r"[^a-z]", value=r'')
data2['cleaned_title'] = data2['title'].str.lower().replace(regex=True,inplace=False,to_replace=r"[^a-z]", value=r'')
现在,让我们使用difflib's get_close_matches(阅读更多和其他选项here)
import difflib
data1['closestmatch'] = data1.cleaned_title.apply(lambda x: difflib.get_close_matches(x, data2.cleaned_title)[0])
data2['closestmatch'] = data1.cleaned_title.apply(lambda x: difflib.get_close_matches(x, data2.cleaned_title)[0])
这是结果数据1,看起来不错!
id title cleaned_title closestmatch
0 a12bcde0 a.b. company abcompany abcompany
1 b20bcde9 company_b companyb companyb
2 csdfsjkbku coampany_b coampanyb companyb
现在,这里是data2,看起来有点不太好 ...我们要求它找到最接近的匹配,所以它找到了一个for company_f,而你显然不想要它。 / p>
serial_number title cleaned_title closestmatch
0 01a2b345 ab company abcompany abcompany
1 10ab2030 company_b (123) companyb companyb
2 40ab4060 company_f companyf companyb
理想的情况是,如果您有一个干净的公司标题列表,在这种情况下,您应该根据找到最接近的匹配。如果你不这样做,你将不得不发挥创意或手动清理命中和错过。
要将其包装起来,您现在可以在'nearestmatch'上执行常规合并。
答案 1 :(得分:0)
您可以尝试在2个数据框的每一个中创建一个simplified_name列,方法是将所有字符设置为小写并删除所有非[a-z]字符,如果这不会导致冲突,则加入此列