python实现多表格数据的不精确匹配

一、需求描述及实现思路

(一)需求描述

        将两个数据表格中有唯一相同的一列值,但该列值内容存有一定差异,有些事全程,有些事简写或者部分名称,现需将两个表格合并在一起。(多表格的模糊匹配

(二)总体思路

        首先,代码使用 pd.read_excel() 函数读取了两个 Excel 表格文件,分别存储在 df_fulldf_partial 数据框中。其中,df_full 存储了全称的信息,df_partial 存储了简写或部分字符的信息。

        然后,代码创建了一个空的结果数据框 df_result,用于存储匹配结果。接下来,通过遍历 df_partial 数据框中的每一行,获取每个简写或部分字符。

        对于每个简写或部分字符,代码使用 process.extract() 函数从 df_full['Full Name'] 列中查找与之匹配的全称。process.extract() 函数返回的是一个列表,其中每个元素包含匹配的全称和相似度得分。代码选择第一个匹配项作为最佳匹配,并获取其全称和得分。

        如果有多个匹配项且得分相同(即有相同的相似度得分),则会将当前行添加到 df_result 数据框中,并使用 .style.apply() 方法将添加的行背景颜色设置为黄色。

        如果只有一个最佳匹配项,则直接将当前行添加到 df_result 数据框中。

接下来,代码使用 pd.merge() 函数将 df_resultdf_partial 数据框按照 'Partial Name' 列进行合并,生成一个新的数据框 df_merged。合并后的结果包含了匹配的全称和原始表格中的其他信息。

        然后,代码创建一个 Workbook 对象,并为工作表设置名称为 'Merged Data'。接着,使用 dataframe_to_rows() 函数将 df_merged 数据框转换为行的迭代器,然后使用两层循环将数据写入工作表中的单元格。

        最后,代码遍历工作表中的每一行,如果发现背景颜色为黄色的单元格,就将整行的单元格背景颜色设置为黄色。最终,将合并结果保存到名为 'merged_table.xlsx' 的 Excel 文件中。

二、实现代码

(一)总体代码

import pandas as pd
from fuzzywuzzy import process
from openpyxl import Workbook
from openpyxl.styles import PatternFill
from openpyxl.utils.dataframe import dataframe_to_rows

# 读取两个表格
df_full = pd.read_excel('全称呼.xlsx')  # 全称表格
df_partial = pd.read_excel('半称呼.xlsx')  # 简写或部分字符表格

# 创建一个空的结果表格用于存储匹配结果
df_result = pd.DataFrame(columns=['Partial Name', 'Full Name'])

# 遍历每个简写或部分字符
for _, row_partial in df_partial.iterrows():
    partial_name = row_partial['Partial Name']

    # 使用fuzzywuzzy库的process.extract函数查找所有匹配项
    matches = process.extract(partial_name, df_full['Full Name'], limit=2)

    # 获取匹配得分最高的全称
    best_match = matches[0][0]
    best_score = matches[0][1]

    # 如果有多个匹配项且得分相同,则标记当前行
    if len(matches) > 1 and matches[0][1] == matches[1][1]:
        df_result = df_result.append({'Partial Name': partial_name, 'Full Name': best_match}, ignore_index=True).style.apply(lambda _: ['background-color: yellow'], subset=pd.IndexSlice[-1:, :])
    else:
        df_result = df_result.append({'Partial Name': partial_name, 'Full Name': best_match}, ignore_index=True)

# 合并两个表格
df_merged = pd.merge(df_full, df_partial, on='Partial Name', how='outer')

# 创建一个Workbook来保存结果
workbook = Workbook()
worksheet = workbook.active
worksheet.title = 'Merged Data'

# 将DataFrame写入工作表中
rows = dataframe_to_rows(df_merged, index=False, header=True)
for r_idx, row in enumerate(rows, 1):
    for c_idx, value in enumerate(row, 1):
        worksheet.cell(row=r_idx, column=c_idx, value=value)

# 标记有多个匹配项的行为黄色
yellow_fill = PatternFill(start_color="FFFF00", end_color="FFFF00", fill_type="solid")
for row in worksheet.iter_rows(min_row=2, max_row=worksheet.max_row):
    if row[0].fill.start_color.index == yellow_fill.start_color.index:
        for cell in row:
            cell.fill = yellow_fill

# 保存合并结果
workbook.save('merged_table.xlsx')

(二)代码讲解

(1)process.extract 函数

process.extract 函数是 fuzzywuzzy 库中的一个功能强大的模糊匹配函数。它的作用是在给定一个待匹配字符串时,在一个字符串列表中查找与之最相似的字符串。

该函数的语法如下:

process.extract(query, choices, scorer=fuzz.ratio, limit=5)

参数解释:

  • query:待匹配的字符串。
  • choices:用于匹配的字符串列表。
  • scorer:用于计算相似度得分的评分函数,默认使用 fuzz.ratio 函数,也可以自定义评分函数。
  • limit:限制返回的匹配项数量,默认为 5。

        函数返回一个结果列表,其中每个元素都是一个包含两个值的元组:匹配的字符串和相似度得分。limit 参数: limit 参数用于限制返回的匹配项数量。默认情况下,它的取值是 5,即返回相似度得分最高的 5 个匹配项。如果你希望返回更少或更多的匹配项,可以根据需要调整这个参数的值。

例如,如果你想返回相似度得分最高的 3 个匹配项,可以将代码改为:

matches = process.extract(query, choices, limit=3)
  1. scorer 参数: scorer 参数用于指定相似度得分的评分函数。默认情况下,它使用 fuzz.ratio 函数来计算相似度得分。fuzz.ratio 函数根据字符串的相似程度计算一个得分,得分越高表示两个字符串越相似。

    除了 fuzz.ratio 函数外,还有其他评分函数可供选择,例如:fuzz.partial_ratio:部分字符串匹配得分。fuzz.token_sort_ratio:对字符串进行标记排序后的匹配得分。fuzz.token_set_ratio:对字符串进行标记集的匹配得分。

        通过调整 limitscorer 参数,可以根据具体需求定制模糊匹配的行。process. extract 函数会根据评分函数计算待匹配字符串与列表中每个字符串的相似度得分,并返回相似度得分最高的匹配项列表。如果指定了 limit 参数,则返回相应数量的最佳匹配项。这个函数对于处理模糊匹配问题非常有用,例如在搜索、字符串匹配、数据清洗等任务中经常被使用。

(2)enumerate() 函数

  enumerate() 函数是 Python 内置函数之一,用于将一个可迭代对象(如列表、元组、字符串、字典、集合等)组合为一个索引序列,同时列出数据和数据的下标。它的语法如下:

enumerate(iterable, start=0)
  • iterable:表示要进行枚举的可迭代对象。
  • start:可选参数,表示索引起始值,默认为 0。

  enumerate() 函数会返回一个迭代器对象,可以使用 list()dict() 等函数将其转换成列表、字典等其他形式。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

封印师请假去地球钓鱼

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值