事务背景
事务中需求用到类似企查查一类的数据平台进行数据导出,但企查查数据不一定精准,所以想选用另一个官方数据平台进行数据比照核验,企查查数据缺少的则弥补,数据一致的保存企查查数据,不一致的进行色彩标示。
完结逻辑
经过调研,python能够完结表格的兼并及数据处理,完结表格的兼并及数据比照、数据弥补、数据穿插验证。
首先将表格A数据和表格B数据穿插摆放,奇数位为表格A的数据,偶数位为表格B数据,每两行为同一公司主体,进行上下数据比照,上一行数据没有的下一行弥补,上下两行都有数据就进行比照,相同的不做处理,不同的标示色彩,并把表格B的数据放到大括号中拼接到表格A数据之后,最终删去偶数行的一切数据。
完结效果
表格A
表格B
合成后效果:
完结进程
1. Python环境安装:
下载地址:Python Releases for Windows | Python.org 下载时,留意选择自定义下载,并勾选增加路径,如下图:
下载安装完结后,按window R键输入cmd翻开命令行工具,输入python显示python版别即为安装成功。
2. Vscode代码编辑器下载及运用:
下载链接:Download Visual Studio Code – Mac, Linux, Windows
(1)转换为中文:安装好后可在扩展区搜索Chinese插件下载,页面工具栏即可变成中文,如下图一:
(2)vscode增加python:新建或翻开编写的python程序后,vscode右下角会弹出增加python环境的提示,点击增加;
(3)代码运转:按ctrl ~键翻开终端运转程序,运转代码如下:
切换到运转文件所在目录: cd 目录
运转python文件: python 文件名.py
3. Python代码:
# 导入表格数据读取及处理模块
import pandas as pd
# 导入数据核算模块
import numpy as np
# 导入时刻处理模块
# from datetime import datetime
# 导入读取和修正excel的模块
from openpyxl import load_workbook,Workbook
# 导入表格款式处理模块
from openpyxl.styles import *
# 比较字符串类似度的模块
import difflib
# 导入表格数据读取及处理模块
import pandas as pd
# 导入数据核算模块
import numpy as np
# 导入时刻处理模块
# from datetime import datetime
# 导入读取和修正excel的模块
from openpyxl import load_workbook,Workbook
# 导入表格款式处理模块
from openpyxl.styles import *
# 比较字符串类似度的模块
import difflib
# 表格寄存目录
url = "D:\finance\rank\数据表格.xlsx"
# 整合后的表格寄存目录
# afterUrl = ''
# 两个表格的sheetname称号
before = 'ifinds' //表格A称号
after = 'winds' //表格B称号
# 最终整合后表格称号
finalName = '比照数据成果'
# 读取两个表格-经过sheet称号读取
data1 = pd.read_excel(url, header = 0, sheet_name = before )
data2 = pd.read_excel(url, header = 0, sheet_name = after )
# 将数据从头赋值,避免修正数据后将原始ifind和wind数据修正
data3 = data1
data4 = data2
# 进行表头重命名以统一表头称号
# 对ifind表格的表头称号重命名
data3 = data3.rename(columns = { '所属国民经济职业类别':'国民一级', '所属国民经济职业大类':'国民二级', '币种':'注册资本币种', '注册资本':'注册资本(万元)','参保人数(人)':'参保人数', '地级市':'城市','企业中文称号':'公司中文称号',})
# 对wind表格的表头称号重命名
data4 = data4.rename(columns = { '企业称号':'公司称号', '公司属性':'企业性质', '国民经济分类类别':'国民一级','国民经济分类大类':'国民二级','国民经济职业-类别':'国民一级','国民经济职业-大类':'国民二级', '所属省份':'省份', '所属城市':'城市', '所属区县':'区/县', '负债及股东权益算计2022':'负债和一切者权益总计2022', '运营活动现金净流量2022':'运营活动发生的现金流量净额2022','负债及股东权益算计2023':'负债和一切者权益总计2023', '运营活动现金净流量2023':'运营活动发生的现金流量净额2023','主体最新信用评级':'最新最低主体评级','是否城投债':'是否城投(THS)', '公司发行股票一览':'股票代码','币种':'注册资本币种','参保人数(人)':'参保人数','注册资本(万元)':'注册资本(万元)','注册资本':'注册资本(万元)','是否城投':'是否城投(THS)','是否城投债':'是否城投(THS)',})
# # wind币种数据英文改中文
if '注册资本币种' in data4.columns:
data4['注册资本币种'] = data4['注册资本币种'].replace('CNY', '人民币').replace('HKD', '港元').replace('MOP', '澳元').replace('USD', '美元').replace('EUR', '欧元').replace('IDR', '卢比').replace('RUB', '俄罗斯卢布').replace('AUD', '澳元').replace('GBP', '英镑')
# ifind企业性质改动
if '企业性质' in data3.columns:
data3['企业性质'] = data3['企业性质'].replace('中心企业', '国企').replace('中心国有企业', '国企').replace('当地国有企业', '国企').replace('国有企业', '国企').replace('民营企业', '私企').replace('私营', '私企').replace('外商独资', '外资企业')
# wind企业性质改动
if '企业性质' in data4.columns:
data4['企业性质'] = data4['企业性质'].replace('中心国有企业', '国企').replace('当地国有企业', '国企').replace('民营企业', '私企').replace('国有企业', '国企').replace('区县级国有企业', '国企').replace('市级国有企业', '国企').replace('省级国有企业', '国企')
# ifind运营状况的改动
if '运营状况' in data3.columns:
data3['运营状况'] = data3['运营状况'].replace('在业', '存续')
# ifind和wind的企业规模的改动
if '企业规模' in data3.columns:
data3['企业规模'] = data3['企业规模'].replace('L大型', '大型企业').replace('M中型', '中型企业').replace('S小型', '小型企业').replace('XS微型', '微型企业').replace('L(大型)', '大型企业').replace('M(中型)', '中型企业').replace('S(小型)', '小型企业').replace('XS(微型)', '微型企业')
if '企业规模' in data4.columns:
data4['企业规模'] = data4['企业规模'].replace('大型', '大型企业').replace('中型', '中型企业').replace('小型', '小型企业').replace('小微企业', '小型企业')
# 参保人数数据取整函数
def newList(inputList):
result = []
for num in inputList:
if pd.isnull(num) or num == "--":
num = 0
result.append(int(num))
return result
# 调用函数
# ifind参保人数取整
if '参保人数' in data3.columns:
data3['参保人数'] = newList(data3['参保人数'])
# wind参保人数取整
if '参保人数' in data4.columns:
data4['参保人数'] = newList(data4['参保人数'])
# 保存两位小数的函数
def rateList(inputList):
result = []
for num in inputList:
num = float(num)
if pd.isnull(num) or num == "--":
num = 0
num = "{:.2f}".format(num)
result.append(num)
return result
# 将wind的财务数据缩小10000倍 or value[:5] == '负债和一切'
for value in data4.columns:
if value[:5] == '一切者权益' or value[:4] == '经营收入' or value[:4] == '利润总额' or value[:4] == '财物总额' or value[:5] == '运营活动产':
data4[value] = data4[value].apply(lambda x: x/10000)
# 将ifind的财务数据保存两位 大股东持股份额、 注册资本(万元)
for value in data3.columns:
if value[:5] == '一切者权益' or value[:5] == '负债和一切' or value[:4] == '经营收入' or value[:4] == '利润总额' or value[:4] == '财物总额' or value[:5] == '运营活动产'or value[:5] == '注册资本(' or value[:5] == '大股东持股':
data3[value] = rateList(data3[value])
# 将wind的财务数据保存两位
for value in data4.columns:
if value[:5] == '一切者权益' or value[:5] == '负债和一切' or value[:4] == '经营收入' or value[:4] == '利润总额' or value[:4] == '财物总额' or value[:5] == '运营活动产'or value[:5] == '注册资本(' or value[:5] == '大股东持股':
data4[value] = rateList(data4[value])
# # 运营范围重复度高于50%则取ifind的运营范围数据,不然标识出来
# 核算重复度的办法
# pdData3 = pd.DataFrame(data3)
pdData4 = pd.DataFrame(data4)
def string_similar(s1, s2):
return difflib.SequenceMatcher(None, s1, s2).quick_ratio()
if '运营范围' in data3.columns:
for index in range(0, len(data3['运营范围']), 1):
# 调用办法
if string_similar(str(data3['运营范围'][index]), str(data4['运营范围'][index])) > 0.5:
# pdData4.loc[index,'运营范围'] = data3['运营范围'][index]
data4['运营范围'][index] = data3['运营范围'][index]
# wind省份数据北京、天津、重庆、上海增加‘市’字的函数
def addword(addData):
result = []
for value in addData:
if value == '北京' or value == '上海' or value == '天津' or value == '重庆':
value = value '市'
result.append(value)
return result
# 调用函数
if '省份' in data4.columns:
data4['省份']= addword(data4['省份'])
# wind地市级去掉北京、重庆、上海、天津的函数
def deleteword(addData):
result = []
for value in addData:
if value == '北京市' or value == '上海市' or value == '天津市' or value == '重庆市':
value = '0'
result.append(value)
return result
# 调用函数
if '城市' in data4.columns:
data4['城市']= deleteword(data4['城市'])
# wind的股票代码去掉股票简称函数
def removeName(word):
result = []
for value in word:
value = str(value).split('(')[0]
result.append(value)
return result
# 调用去掉股票简称的函数
if '股票代码' in data4.columns:
data4['股票代码'] = removeName(data4['股票代码'])
# 有股票代码的将上市公司信息改为是,不然改为否
pdData3 = pd.DataFrame(data3)
if '股票代码' in data3.columns:
for index in range(0, len(data3['股票代码']), 1):
# 如果wind股票代码单元格的字符长度大于2,则将代码编号改为是,不然改为否
if len(str(data3['股票代码'][index])) > 2:
pdData3.loc[index:, '是否上市'] = "是"
else:
pdData3.loc[index:, '是否上市'] = "否"
# 如果wind股票代码单元格的字符长度大于2,则将代码编号改为是,不然改为否
if '股票代码' in data4.columns and len(str(data4['股票代码'][index])) > 2:
pdData4.loc[index:, '是否上市'] = "是"
else:
pdData4.loc[index:, '是否上市'] = "否"
# 兼并两个表格数据,并且ifind数据在前,wind数据在后
result = pd.concat([data3, data4], ignore_index = True)
# 得到的兼并表格的标题,从头创立新表格,增加表头
dfNew = pd.DataFrame(columns = result.columns)
# 获取兼并的两个表格的索引,经过索引使两个表格的数据穿插摆放
data3 = data3.set_index(np.arange(1, data3['序号'].count() 1, 1), drop = False)
data4 = data4.set_index(np.arange(1, data4['序号'].count() 1, 1), drop = False)
# 兼并两个表格的索引到一个表格
for i in np.arange(1, data3['序号'].count() 1, 1):
dfNew.loc[2*i-2] = data3.loc[i]
dfNew.loc[2*i-1] = data4.loc[i]
# 遍历判断:如果榜首行数据为nan或为0,就把第二行的数据填充到榜首行,
for column in np.arange(0, dfNew.shape[0]):
if column % 2 == 0:
for index in range(len(dfNew.iloc[column].values)):
if pd.isnull(dfNew.iloc[column].values[index]) or str(dfNew.iloc[column].values[index]) == '0' or str(dfNew.iloc[column].values[index]) == '0.00' or str(dfNew.iloc[column].values[index]) == '0.0':
dfNew.iloc[column, index]= dfNew.iloc[column 1].values[index]
# # 定义list,用来存储数据不同的列的下标数据
rowsList = []
columnsList = [[] for _ in range(dfNew.shape[0])]
# 如果第二行数据和榜首行数据不同,就把wind的数据增加括号拼接到ifind后
for row in np.arange(0, dfNew.shape[0]):
if row % 2 == 0:
rowsList.append(row)
for index in range(len(dfNew.iloc[row].values)):
if pd.notnull(dfNew.iloc[row 1].values[index]):
# 处理因中英文括号导致的差异
if(str(dfNew.iloc[row].values[index]).replace('(','(').replace(')',')') != str(dfNew.iloc[row 1].values[index]).replace('(', '(').replace(')',')') and str(dfNew.iloc[row 1].values[index]) != '0' and str(dfNew.iloc[row 1].values[index]) != '0.00' and str(dfNew.iloc[row 1].values[index]) != '0.0') :
dfNew.iloc[row, index] = str(dfNew.iloc[row].values[index]) '{' str(dfNew.iloc[row 1].values[index]) '}'
# 每一行的列的增加有问题
columnsList[row].append(index)
else:
dfNew.iloc[row, index] = str(dfNew.iloc[row].values[index])
# 将三个表格导出为三个sheet
writer = pd.ExcelWriter(url)
dfNew.to_excel(writer, sheet_name = finalName, index = False)
data1.to_excel(writer, sheet_name = before, index = False)
data2.to_excel(writer, sheet_name = after, index = False)
writer._save()
writer.close()
# # 增加不同数据组的高亮
wb = load_workbook(url)
sheet1 = wb['比照数据成果']
for row in rowsList:
for column in columnsList[row]:
sheet1.cell(row 2,column 1).fill = PatternFill('solid', fgColor = Color('9dff00'))
# # 删去wind行的数据 第二行
deleteRow = []
for i in np.arange(dfNew.shape[0] 5,2, -1):
if i%2 == 1:
sheet1.delete_rows(i)
# # 导出增加款式后的表格
wb.save(url)
wb.close()
print("祝贺你,兼并完结!")
留意事项
1.留意两个表格榜首列的表头为序号,榜首列传入从1开始的序号作为兼并数据的摆放下标,不然程序会报错;
2.两组表格摆放顺序要一致;
3.留意程序运转前要将表格关闭,表格被占用时程序不能运转会报错;
4.将两张表格放到一个excel文件的两个sheet中,比照数据表格放到第三个sheet中,留意称号要和代码里对应上;
总结
我基本上现已处理到了表格兼并遇上的大多问题,代码也增加了详细注释,欢迎大家来积极提出问题,一起解决问题。