本文使用到的技术点
- 使用pandas读取和写入exel;
- DataFrame类型转化为list
- difflib比较字符串的相似度
- python多线程
- 队列queue
import pandas as pd
import difflib
import queue
import threading
import time
time_start=time.time()
#a表读取
shanda_df=pd.read_excel('shanda.xlsx')
# data=df['ADH分泌过多综合征'].tolist()
# b表读取
hexin_df=pd.read_excel('hexin.xlsx')
hexin_data=[]
shanda_data=[]
# 遍历山大地纬dataframe插入list中,组成一个二元数组
for i in shanda_df.index.values:
row_data=shanda_df.loc[i,['诊断ID','诊断名称']].tolist()
shanda_data.append(row_data)
# 遍历核心dataframe插入list中,组成一个二元数组
for i in hexin_df.index.values:
row_data=hexin_df.loc[i,['诊断ID','诊断名称']].tolist()
hexin_data.append(row_data)
length=len(hexin_data)
sucs=[]
fail=[]
j=0
print('**************开始匹配****************')
# 多线程
def matchhx(arg):
# 遍历核心list
i=0
for hexin in hexin_data:
like = difflib.SequenceMatcher(None, arg[1], hexin[1]).quick_ratio()
# 相似度大于0.7则匹配成功
if like > 0.7:
tem = []
tem.append(arg[0])
tem.append(arg[1])
tem.append(hexin[0])
tem.append(hexin[1])
sucs.append(tem)
break
else:
# 如果到最后一个还没有匹配到,则认为失败
if i == length - 1:
f = []
f.append(arg[0])
f.append(arg[1])
fail.append(f)
i += 1
que=queue.Queue(20)
# 遍历山大list
for shanda in shanda_data:
# 创建线程执行函数
t=threading.Thread(target=matchhx,args=(shanda,))
t.start()
que.put(t)
# 计数器
j += 1
print('计数器', j)
if que.full():
for i in range(20):
q=que.get()
q.join()
print('队列中的线程已经被执行完')
if que.qsize():
for i in range(que.qsize()):
q = que.get()
q.join()
print('剩余线程已经被执行完')
print('****************************匹配结束*********************************')
time_end=time.time()
print('****************************匹配时间:{shijian}*********************************'.format(shijian=time_end-time_start))
sucs_df=pd.DataFrame(sucs)
fail_df=pd.DataFrame(fail)
sucs_df.to_excel('success.xlsx',sheet_name='比较成功')
fail_df.to_excel('fail.xlsx',sheet_name='比较失败')
由于python的GIL锁特性,这种cpu复杂性用多线程解决并不适合,所以我重新写了一个多进程版的。
用到了进程池和正则表达式
import pandas as pd
import difflib
import queue
import threading
import time
import multiprocessing
import re
# 多进程
def matchhx(arg,reg1,reg2,reg3,hexin_data,length,j):
# 遍历核心list
i=0
res=''
res1=reg1.search(arg[1])
res2 = reg2.search(arg[1])
res3 = reg3.search(arg[1])
if res1:
res=res1.group(0)
elif res2:
res=res2.group(0)
elif res3:
res=res3.group(0)
else:
res=arg[1]
keyword=''
if len(res) <= 3:
keyword=res
elif 3<len(res)<=5:
keyword=res[-3:]
else:
keyword=res[3:6]
for hexin in hexin_data:
if hexin[1].find(keyword)>=0:
tem = []
tem.append(arg[0])
tem.append(arg[1])
tem.append(hexin[0])
tem.append(hexin[1])
print('计数器', j)
return tem
else:
# 如果到最后一个还没有匹配到,则认为失败
if i == length - 1:
f = []
f.append(arg[0])
f.append(arg[1])
print('计数器', j)
return f
i += 1
if __name__ == "__main__":
time_start = time.time()
# 山大地纬码表读取
shanda_df = pd.read_excel('fail.xlsx')
# data=df['ADH分泌过多综合征'].tolist()
# 核心码表读取
hexin_df = pd.read_excel('hexin.xlsx')
print('读取excel')
hexin_data = []
shanda_data = []
# 遍历山大地纬dataframe插入list中,组成一个二元数组
for i in shanda_df.index.values:
row_data = shanda_df.loc[i, [0, 1]].tolist()
shanda_data.append(row_data)
# 遍历核心dataframe插入list中,组成一个二元数组
for i in hexin_df.index.values:
row_data = hexin_df.loc[i, ['诊断ID', '诊断名称']].tolist()
hexin_data.append(row_data)
length = len(hexin_data)
sucs = []
fail = []
j = 0
print('**************开始匹配****************')
# 创建正则表达式对象
regex1 = r'(?<=\)|\)|\]).+?(?=\(|\(|\[)'
regex2 = r'.+?(?=\(|\(|\[)'
regex3 = r'(?<=\)|\)|\]).+'
reg1 = re.compile(regex1)
reg2 = re.compile(regex2)
reg3 = re.compile(regex3)
# que=queue.Queue(10)
# 创建进程池
pool = multiprocessing.Pool(6)
# 遍历山大list
for shanda in shanda_data:
# 计数器
j += 1
fail.append(pool.apply_async(matchhx,args=(shanda,reg1,reg2,reg3,hexin_data,length,j,)))
# 创建线程执行函数
# t=threading.Thread(target=matchhx,args=(shanda,))
# t.start()
# que.put(t)
# if que.full():
# for i in range(10):
# q=que.get()
# q.join()
# print('队列中的线程已经被执行完')
# if que.qsize():
# for i in range(que.qsize()):
# q = que.get()
# q.join()
# print('剩余线程已经被执行完')
# 关闭进程池
pool.close()
# 等待进程执行完毕
pool.join()
print('********进程结束***********')
for i in fail:
sucs.append(i.get())
print('****************************匹配结束*********************************')
time_end=time.time()
print('****************************匹配时间:{shijian}*********************************'.format(shijian=time_end-time_start))
sucs_df=pd.DataFrame(sucs)
# fail_df=pd.DataFrame(fail)
sucs_df.to_excel('keyword_s.xlsx',sheet_name='比较成功')
# fail_df.to_excel('keyword_f.xlsx',sheet_name='比较失败')