在合并之前清除数据的更好方法是什么?

时间:2016-11-07 22:15:53

标签: python pandas replace merge

我需要合并两个不同的数据框,并且在合并发生之前需要清理合并列('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') 

2 个答案:

答案 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]字符,如果这不会导致冲突,则加入此列