【问题标题】:Merge two csv-files by columns with similars strings按具有相似字符串的列合并两个 csv 文件
【发布时间】:2020-05-11 07:53:51
【问题描述】:

我开始使用 pandas,但遇到了一个我不知道如何解决的问题。

我有两个数据框。

第一个包含汽车信息,包括汽车型号(DESCR_MARCA_VEICULO 列)

df1
col1   col2   DESCR_MARCA_VEICULO
....   ....   'GM/CELTA 5 PORTAS SUPER'
....   ....   'VW/VOYAGE LS'
....   ....   'VW/GOL LS'
....   ....   'I/AUDI A4 2.0T FSI'
....   ....   'FIAT/UNO CS IE'

第二个包含一个包含汽车模型和与该模型关联的唯一 ID 的两列 de-para,如下所示:

df2
ID     DESCR_MARCA_VEICULO
1      'GM - CELTA 5'
2      'VW - VOYAGE LS'
3      'VW - GOL LS'
4      'ACURA - INTEGRA GS 1.8'
5      'AUDI - 80 S2 AVANT'

而且它不一定遵循将“/”替换为“-”之类的模式。

但是,我在 DF1 中有超过 5000 种不同的汽车型号(这让我无法逐个查看),我需要将 DF1 和 DF2 结合起来,将 ID 列带到 DF1(这将是一个合并)。但是,当我合并 dfs 时,由于字符串的这些差异,没有匹配项。

有什么方法可以通过DESCR_MARCA_VEICULO 列中的字符串之间的相似性来合并这些dfs?

谢谢你:)

【问题讨论】:

  • 只是猜测,但第二列只有品牌名称和型号(GM - CELTA)。您可以使用 str.split 在多个拆分中提取它,并为模式使用正则表达式。如果您可以提供一个混合了不同分隔符的示例,我相信这里的人们可以解决问题。
  • 我在示例中添加了几行。但是,它不一定遵循逻辑。因为这两个柱子都有品牌和纯模型,如 VW GOL 或 AUDI A3,但有时它们会放置尽可能多的阀门或气缸

标签: python pandas dataframe merge similarity


【解决方案1】:

我建议您使用fuzzywuzzy 包查看模糊匹配

一个技巧是从字符串中删除除字母和数字之外的所有字符

df1['var'] = df1['DESCR_MARCA_VEICULO'].str.replace('[^A-Za-z0-9]','')
df2['var'] = df2['DESCR_MARCA_VEICULO'].str.replace('[^A-Za-z0-9]','')

m = pd.merge(df1,df2,on='var').drop('var',axis=1)

print(m)

    col1     col2 DESCR_MARCA_VEICULO_x     matches  ID DESCR_MARCA_VEICULO_y
0  ....     ....           VW/VOYAGE LS  VWVOYAGELS   2        VW - VOYAGE LS
1  ....     ....              VW/GOL LS     VWGOLLS   3           VW - GOL LS

我们需要匹配几个缺少的键:让我们使用来自post 的 Erfan 的答案

from fuzzywuzzy import fuzz
from fuzzywuzzy import process
def fuzzy_merge(df_1, df_2, key1, key2, threshold=90, limit=2):
    """
    df_1 is the left table to join
    df_2 is the right table to join
    key1 is the key column of the left table
    key2 is the key column of the right table
    threshold is how close the matches should be to return a match, based on Levenshtein distance
    limit is the amount of matches that will get returned, these are sorted high to low
    """
    s = df_2[key2].tolist()

    m = df_1[key1].apply(lambda x: process.extract(x, s, limit=limit))    
    df_1['matches'] = m

    m2 = df_1['matches'].apply(lambda x: ', '.join([i[0] for i in x if i[1] >= threshold]))
    df_1['matches'] = m2

    return df_1

print(fuzzy_merge(df1, df2, 'var', 'var', threshold=80))

    col1     col2      DESCR_MARCA_VEICULO                  var     matches
0  ....     ....   GM/CELTA 5 PORTAS SUPER  GMCELTA5PORTASSUPER    GMCELTA5
1  ....     ....              VW/VOYAGE LS           VWVOYAGELS  VWVOYAGELS
2  ....     ....                 VW/GOL LS              VWGOLLS     VWGOLLS
3  ....     ....        I/AUDI A4 2.0T FSI        IAUDIA420TFSI            
4  ....     ....            FIAT/UNO CS IE          FIATUNOCSIE   

【讨论】:

  • 感谢您的帮助!但是,df1 大约有 200 万行,并且 Def 模糊匹配已经运行了 12 个小时。我能做些什么来优化时间吗?
  • @DaniloPerl 我认为不是你在处理字符串,也许你可以提取关键字.. 但我不是专家,为什么不看看链接的帖子或者做这个任务在Dask 或pyspark 或其他数据处理软件中
  • 我还继续运行引用的帖子中涵盖的 difflib 包的算法。我等着看哪一个先结束。我的问题是我是否正确应用了 difflib。但是我稍后会看到并将结果放在这里:)
  • 一个疑问:如果我把 n = 1 放在函数中,它是否会大大减少处理时间?
  • 我不确定,因为它使用不同的包并且您使用字符串,最好问一个新问题,询问如何优化此解决方案 - 我相信有人会知道。否则我唯一能想到的就是投入更多的计算以使其运行得更快,这就是 Dask 或 Pyspark 之类的东西发挥作用的地方
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-09-24
  • 2021-07-13
  • 1970-01-01
  • 1970-01-01
  • 2017-06-24
  • 1970-01-01
相关资源
最近更新 更多