想必大家在公司都要填周报,月报,季度报表,年度报表,朋友小乐在一家公司的财务部门工作,她每天需要整理20家公司的销售额还有员工的绩效表,她每天的状态是这样的:
有什么能够让她脱离苦海呢?
那当然是报表自动化了!
们知道利用Excel的数据透视表功能就制作该报表:选中数据表中任意一个单元格,点击插入数据透视表,然后按以下步骤执行:
当处理到单位字段时我们会发现,表中每一笔贷款都有三家网点进行业绩分成。我们需要将分成比例也考虑进去。所以透视表中的行区域及值区域不能简单的放入单位1和贷款金额。此时大部分人都会想到先在数据源表格中添加三列按分成比例分成以后的贷款金额。
三个数值的计算方法分别为:
分成贷款金额1=贷款金额*分成比例1分成贷款金额2=贷款金额*分成比例2分成贷款金额3=贷款金额*分成比例3
然后将单位1及分成贷款金额1拖放到透视表的行区域及值区域。求出每个网点在分成金额1上的贷款投放,用同样的方法将各网点在分成贷款金额2及3的和。于是就会得到结构如下的三个数据透视表:
最后一步就是运用VlOOKUP将同一家网点的同种贷款金额整合相加到日报相对应的单元格里,实现最后的报表输出。
以上流程每天都需要进行重复:插入列、编写公式、做数据透视表、VLOOKUP,相信就算是熟悉Excel的人也需要华20到25分钟,而在操作过程中很容易因为疏忽而造成错误。
如此循环往复,效率低下并且出错率高。而从操作上来讲,整个流程都是标准化的,因此我们可以考虑使用Python进行自动化设计。
数据加载过程比较简单,使用read_excel()进行设置即可,这里不在赘述。仅提出以下建议,供大家参考,
import pandas as pd
from datetime import datetime # 因为后面需要处理到日期筛选,所以需要将datetime类从datetime模块中加载进来
data=pd.read_excel(r"E:\个人贷款客户信息表.xlsx",usecols=[1,4,6,7,8,9,10,11,12]) # 假设个人贷款客户信息表放在本地E盘
data.shape
---
(50585, 9)
以上为导入个人贷款信息表格代码,由于个人贷款客户信息表为工作簿第一张工作表,因此缺省sheet_name参数。
通过指定导入例的方法将与计算无关的“协议编号”,“贷款余额”,“固定利率”,“合同到期日”去除。
#查看data表的基本信息
data.info()
---
RangeIndex: 50585 entries, 0 to 50584
Data columns (total 9 columns):
贷款金额 50585 non-null int64
合同生效日 50585 non-null datetime64[ns]
用途 50585 non-null object
单位1 50585 non-null object
分成比例1 50585 non-null int64
单位2 16418 non-null object
分成比例2 16418 non-null float64
单位3 958 non-null object
分成比例3 958 non-null float64
dtypes: datetime64[ns](1), float64(2), int64(2), object(4)
memory usage: 3.5+ MB
接下来预览一下data表的数据,默认显示前5行
data.head()
3.2日期筛选
个人贷款信息表包含该银行所有的历史数据,而我们每日的报表只需要统计当年的投放情况。所以计算投放金额前,我们需要将合同生效日期不符合要求的贷款记录排除掉。这里我们通过判断日期是否为2019年(大于2018-12-31)返回TRUE/FALSE进行选择判断。这种利用判断条件来选择数据的方式叫布尔索引。
这里解释一下import datetime和from datetime import datetime的区别。datetime 是模块,而datetime模块里面还包含一个datetime类。通过from datetime import datetime能从datetime模块直接导入datetime类。如果导入import datetime ,则在定义时间时,需要使用datetime.datetime()格式。
data=data[data["合同生效日"]>datetime(2018,12,31)]
data.shape #经过对日期的过滤,输出了1673行,9列
---
(1673, 9)
对日期列进行观察,可以看到合同生效日都是2019年的日期了。
data.head()
3.3数据表拆分
下一步,我们需要处理分成比例问题了。此案例的重点也是在这里。按照 1.3节 Python优化报表制作过程中的分析,我们需要先将贷款金额分别与分成单位1、2、3及分成比例1、2、3组成三张分表。数据表的拆分代码很简单。直接用普通索引将需要的列传导给分表就可以了。
data1=data[["用途","贷款金额","单位1","分成比例1"]]
data2=data[["用途","贷款金额","单位2","分成比例2"]]
data3=data[["用途","贷款金额","单位3","分成比例3"]]
对data1表进行预览
data1.head()
对data2表进行预览
data2.head()
对data3表进行预览
data3.head()
3.4数据追加合并
接下来我们需求是将三个分离的表进行纵向的拼接。在我们的例子中,需要将三个表的单位及分成比例字段追加在同一列。但是目前三个新表中的单位及分成比例字段名字是不一致的,不能直接追加。所以我们需要先将分表的名字统一。
3.4.1重命名列索引
在Python中重命名,使用rename()函数。并使用键值对的方式对columns参数进行赋值。将各分表的单位字段统一命名为单位,分成比例字段统一命名为分成比例。
data1=data1.rename(columns={"单位1":"单位","分成比例1":"分成比例"})
data2=data2.rename(columns={"单位2":"单位","分成比例2":"分成比例"})
data3=data3.rename(columns={"单位3":"单位","分成比例3":"分成比例"})
预览data3表
data3.head()
3.4.2纵向拼接分表
通过以上重命名操作,三个分表列名已经一致,这时我们可以将三个表格纵向追加起来。纵向追加使用concat()函数,并使用参数ignore_index重置行索引。
data4=pd.concat([data1,data2,data3],ignore_index=True)
预览合并后的表
data4.head()
3.5数据分组/透视
3.5.1空值处理
此时利用info()返回的数据可以判断data4是否存在空值。从以下运行结果来看,data4数据表格共5019行,贷款金额及贷款用途都含有5019行非空值,说明者两列都没有空值出现。而单位及分成比例只有2041行数据为非空。其他行为空值。
根据业务逻辑可知,如果单位列数据为空,则一定不存在分成比例,即:分成比例也为空。那么该条记录就是无效的。因此可以直接将其删除。使用dropna()函数进行空值处理。
data4.info()
---
RangeIndex: 5019 entries, 0 to 5018
Data columns (total 4 columns):
用途 5019 non-null object
贷款金额 5019 non-null int64
单位 2041 non-null object
分成比例 2041 non-null float64
dtypes: float64(1), int64(1), object(2)
memory usage: 156.9+ KB
对空值进行删除
data4=data4.dropna() # 此处对不设置 how="all",因为此场景中只要出现空值,就将记录删除。从以下输出结果可知存在空值的记录已经被删除。
查看删除后表的信息3.5.2插入新列
接下来一步是计算分成贷款金额,即:我们需要插入一列,使其等于贷款金额列剩余分成比例。注意到分成比例并非百分比格式,我们需要将其转化为百分比(除以100)。插入新列可以使用insert()函数,也可以直接以索引的方式进行。为了演示,我们分别选择不同的方法插入百分比列及分成贷款金额列。
使用insert()插入百分比列
data4.insert(2,"分成百分比",data4["分成比例"]/100)
对插入数据后的表进行预览
data4.head()
使用普通索引方式插入分成贷款金额列
data4["分成贷款金额"]=data4["贷款金额"]*data4["分成百分比"]/10000 # 除以10000,将结果单位换算为万元
对插入数据后的表进行预览
data4.head()
3.5.3数据透视
至此,数据清洗过程基本上已经完成了,接下来只需要对数据进行分组透视啦。这里还是遵循排除干扰的原则,先使用普通索引的方式提取需要用到的列,排除不必要的干扰。然后使用pivot_table()设置相关参数进行透视。
data5=data4[["单位","用途","分成贷款金额"]]
pd.pivot_table(data5,values="分成贷款金额",columns="用途",index="单位",aggfunc='sum').fillna(0).reset_index() #将无投放数据的地方填充为0
至此,我们的任务就完成了。至于结果输出部分,我们可以选择直接复制黏贴到结果表上。当然也可以使用to_excel()将输出结果保存为excel文件。甚至我们还可以导入xlrd模块,直接对我们的日报表进行修改输出。这里就不多做演示了,请读者们自己动起手来。
模型建立好以后,我们只需要将最新的个人贷款客户信息表放置在E盘,覆盖旧的数据文件。然后按下图所示点击 Run All 执行以上代码就可以一键完成我们每天需要的日报了。
数据采集快速搞定
亿信ABI实现报表自动化的第一个关键要点,就是能够直连数据库。亿信ABI支持支持关系型数据库,如:Oracle、Mysql、DB、SQL Server等;也支持分布式数据库,如:PetaBase、Greenplum、Impala、HBase等;以及各种文件数据源和接口数据源,方便快速接入其他系统数据进行分析。
在亿信ABI的数据配置-数据连接管理中新建好数据连接,保证数据连接测试成功。然后添加周期性报表相关的业务包,将相关数据表加入并且建好立表间关联关系即可。这样,相当于亿信ABI在数据库的支撑下搭建了一个数据中心,所有产生的数据都可以集中到系统上去,并且数据库中的数据按照字段实时更新,可以做到随时取数随时做表。
△亿信ABI-数据源支持
周期报表自动生成
亿信ABI能够轻松实现自动统计、自动计算、数据初始化等,支持关键报表一键输出,涵盖报表分析、敏捷分析、可视化分析、报告分析、移动应用、数据填报等多种分析类型。无论你的日报、周报、月报是采用报表、PPT报告、Word报告还是移动报表形式,亿信ABI全部支持。
举两个例子:
一、报表月报实现
场景描述:某销售部门需对每月北京市门店,销售额大于300万的门店,进行相关数据汇总,呈送总公司。
实现方法:亿信ABI可以采用参数过滤,将参数组件与月报中需要进行筛选的时间字段进行绑定,然后对相应的数据格添加过滤条件,就可以实现报表自动化。只需切换参数的值,即可查看不同时期的数据,形成相应的月报等,避免一遍一遍的重复做表。
二、移动端资金日报实现
场景描述:某公司财务部门需对每日的资金情况做汇报,发送给领导层查看,且要求移动端能够查看。
实现方法:亿信ABI支持移动端报表,可以利用各类统计图制作。只需要做一次日报,然后将其作为模板,以后再需要时可以直接只要调用模板填数就可以。数据填报汇总后,资金日报汇报数据即刻自动刷新。
以上所有报表,亿信ABI都支持将其转化为模板保存在数据库中,需要制作报表时就可以直接将模板调出来,大大减少制作报表的流程和时间,将繁琐复杂的日报、周报、月报变成再简单不过的取数填数。
报表自动发送
在报表制作完成后,只需要通过报表的订阅功能,就可以将做好的报表定时发布出去,从不厌其烦的重复发布操作中解脱,方便快捷地设置日报、月报、季报、年报等任务,不需要额外的工作。报告也可以通过邮箱订阅定时发送。
此外,除了定时发送订阅外,还可以设置预警条件,实现预警订阅。当统计报表数据达到预警值会自动发送邮件预警,将异常情况邮件发送相关部门,便于应急处理。