建模杂谈系列37-使用编辑距离和结巴进行文本比对

说明

假设场景:有一批表格文件,有两列文本需要比对结果是否一致。
简单考虑以下情况:

  • 1 如果文本本身就比较短,那么出现差异时就很难说对错
  • 2 如果文字本身较长,可以通过编辑距离检查两个文本的差异
  • 3 有可能文本虽然编辑距离大,但是意思接近,这时候简单的使用结巴分词比较词组

需求:原始文件是一批csv, 里面已经对两列数据进行了判定,字段结果为“无数据”、“不一致”,现在需要人对不一致的部分进行详细比对。(原程序只是比较了值是否一致,现在需要准确的确认。例如,“上海市” 不等于 “上海”,但是其实本来是一回事)

程序的作用是过滤出需要比对的记录,并给出相似度的量化参考。

处理

获取数据。原始文件使用csv保存存在问题,csv以逗号作为分隔符而数据本身存在逗号,这样导致了分列的失败。因此转为直接去取行文本直接处理。

import DataManipulation as dm 
import pandas as pd 
import os

data_folder = './人为对比优化/'
file_list = os.listdir('./人为对比优化/')

data_dict = {}
line_index_dict = {}
meta_dict = {}
for the_file in file_list:
    data_dict[the_file] = []
    line_index_dict[the_file] = []
    meta_dict[the_file] = {}
    meta_dict[the_file]['无数据'] = 0
    meta_dict[the_file]['不一致'] = 0
    meta_dict[the_file]['其他'] = 0
    with open(data_folder + the_file) as f:
        lines = f.readlines()
    for i,line in enumerate(lines):
        if '无数据' in line:
            meta_dict[the_file]['无数据'] += 1
        elif '不一致' in line:
            meta_dict[the_file]['不一致'] += 1
            data_dict[the_file].append(line)
            line_index_dict[the_file].append(i)
        else:
            meta_dict[the_file]['其他'] += 1
# 基本数据比对输出
base_compare = dm.flat_dict(meta_dict)
base_compare_df = dm.flat_dict2df(base_compare)
base_compare_df.to_excel('基本比对信息.xlsx')

基本结果如下:
在这里插入图片描述

接下来析取关键的比对字段,原字段的保存还是有一定规范的...,a平台:str1,测试数据:str2

# 析取不一致的字段对比
dif_dict = {}
for k in data_dict.keys():
    dif_dict[k] = []
    for i,the_line in enumerate(data_dict[k]):
        line_index = line_index_dict[k][i]
        the_line = the_line.replace('\n', '')
        pos1 = the_line.find(',a平台:')
        pos2 = the_line.find(',测试数据:')
        str1 = the_line[pos1+6:pos2].strip()
        str2 = the_line[pos2+6:].strip()

        str1_len = len(str1)
        str2_len = len(str2)

        is_len = str(1 if str1_len else 0) + str(1 if str2_len else 0)

        # 如果有长度才进行比较
        # 1 编辑距离
        import Levenshtein
        if str1_len and str2_len:
            ldis = Levenshtein.distance(str1, str2)
            lsimi =  ldis / max(str1_len, str2_len)
        else:
            ldis = -1
            lsimi= -1

        # 2 结巴分词
        import jieba 
        if str1_len and str2_len:
            set1 = set(jieba.cut(str1))
            set2 = set(jieba.cut(str2))

            uset = set1|set2 
            iset = set1& set2 
            uset_len = len(uset)
            iset_len = len(iset)
            jsimi = iset_len / uset_len
        else:
            jsimi = -1
            uset_len =-1
            iset_len =-1
        tem_dict = {}
        tem_dict['line_index'] = line_index
        tem_dict['str1_a平台'] = str1
        tem_dict['str2_测试'] = str2
        tem_dict['str1_len'] = str1_len
        tem_dict['str2_len'] = str2_len 
        tem_dict['is_len'] = is_len
        tem_dict['ldis'] = ldis
        tem_dict['lsimi_编辑距离相似度'] =   1 - lsimi if  lsimi >0 else lsimi
        tem_dict['并集词组长度'] = uset_len
        tem_dict['交集词组长度'] = iset_len
        tem_dict['词组相似度'] = jsimi
        dif_dict[k].append(tem_dict)


res_df_list = []
for k in dif_dict.keys():
    tem_df = pd.DataFrame(dif_dict[k])
    tem_df['file'] = k
    res_df_list.append(tem_df)

dif_res_df = pd.concat(res_df_list, ignore_index=True)

dif_res_df.to_excel('对比细节.xlsx')

以下是部分比对细节,例如 “陕西省西咸新区市场监督管理局秦汉新城分局”和“西咸新区工商行政管理局秦汉新城分局”数据肯定不一致,但是编辑距离差距并没有那么大,分割成词组也有一定的相似性。
在这里插入图片描述
编辑距离和结巴分词的介绍可以参考以下文章。

参考

编辑距离使用参考
结巴分词使用参考

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值