统计数据来说,有时点数据和时期数据。通常情况下,会进行两期数据的比较,现整理一个两期数据比较的场景应用。主要流程分为:
1、数据读取
2、数据预处理
3、数据分类汇总
4、两期数据比较
5、数据输出到EXCEL
主程序如下:
df = get_src_data(r'../data/learn_pandas/20200930 zongheqixian/')
# 预处理数据
df = pre_handle_data(df)
df = hz_data(df)
# 进行数据比较
df = compare_data(df,'20200930','20200831')
df.sort_values(by=['产品品种','机构名称', '数据表名称','列指标名称','行指标名称'],inplace=True)
name = r'data/output/20200930 数据审核.xlsx'
with pd.ExcelWriter(name) as writer:
df.to_excel(writer,'仅合计项',index=False,freeze_panes=(1,6)) # freeze_panes可以EXCEL设置冻结位置
writer.save()
1、源数据读取,出入文件夹作为参数,合并所有源数据到一起。使用pd.concat进行数据合并。
# 获取数据源
def get_src_data(folder_name):
file_list = os.listdir(folder_name)
ldf = [] # 先放入list,最后一起concat比较高效率
if len(file_list) > 0 :
# 遍历文件夹下所有文件
for i in range(len(file_list)):
# 如果是excel择用这个,如果是csv择用另一个
ldf.append(pd.read_excel(folder_name + str(file_list[i]),dtype=object))
return pd.concat(ldf,ignore_index=True)
else:
return None
2、进行数据预处理,如单位转换,不需要的数据剔除。
# 数据预处理,指标归并、数据删除
def pre_handle_data(df):
# 预处理数据
return df
3、由于当前处理的数据是单机构的数据,想进行汇总查看整体数据情况。使用pivot_table进行汇总,接着使用reset_index转化为明细项进行合并到源数据中。
def hz_data(df):
# 分产品、全部汇总
hz_list = []
table = pd.pivot_table(df,values=['数据值'],index=['数据日期','产品品种','数据表名称', '行指标名称', '列指标名称'],aggfunc=np.sum,fill_value = 0)
table.reset_index(inplace=True)
table['机构名称'] = '# 合计 ' + table['产品品种']
hz_list.append(table)
table = pd.pivot_table(df,values=['数据值'],index=['数据日期','数据表名称', '行指标名称', '列指标名称'],aggfunc=np.sum,fill_value = 0)
table.reset_index(inplace=True)
table['机构名称'] = '# 合计 '
table['产品品种'] = '# 合计 '
hz_list.append(table)
hz_list.append(df)
return pd.concat(hz_list,ignore_index=True)
4、进行两期数据比较,将数据拆分成两个时点,并使用pd.merge拼接到一起。
# 数据比较
def compare_data(df,cur_date,pre_date):
# 进行拼接
cur = df[df['数据日期'] == cur_date].copy()
pre = df[df['数据日期'] == pre_date].copy()
pre.drop(columns=['数据日期','数据ID','指标ID','行序号','列序号', '数据表序号', '数据位数','数据批次'],inplace=True)
cur.drop(columns=['数据ID','指标ID','行序号','列序号', '数据表序号', '数据位数','数据批次'],inplace=True)
# on为合并依赖字段
df = pd.merge(cur,pre,how='outer',on=[ '行指标编码', '行指标名称', '列指标编码', '列指标名称', '数据表名称', '数据管理机构', '产品品种',
'机构名称', '社会信用代码','机构产品标识'],suffixes=['_当期','_上期'])
# 列位置调整
df = df[order]
# 修改一个列名
df.rename(columns={'数据值_当期':'当期值(亿元/只)','数据值_上期':'上期值(亿元/只)'},inplace = True)
# 删除无用列名
df.drop(columns=['社会信用代码','行指标编码', '列指标编码','机构产品标识'],inplace=True)
# 补充数据日期,注意这里要先补充缺失字段,否则进行批量计算的时候,会跳过空值,因此要先fillna(0)
df['数据日期'] = cur_date
df.fillna(0,inplace=True)
df['变动值'] = df['当期值(亿元/只)'] - df['上期值(亿元/只)']
dfsel = ~(df['上期值(亿元/只)'] == 0)
df.loc[dfsel,'变幅(%)'] = df.loc[dfsel,'变动值'] / df.loc[dfsel,'上期值(亿元/只)']
# 增加比例判断
df.loc[(abs(df['变幅(%)'])>0.3) & (abs(df['变幅(%)'])<1),'备注'] = "变幅大于30%"
df.loc[(abs(df['变幅(%)'])>=1) & (abs(df['变幅(%)'])<100),'备注'] = "变幅大于100%"
df.loc[(abs(df['变幅(%)'])>=100),'备注'] = "变幅大于100倍"
df.loc[df['上期值(亿元/只)'].isnull(),'备注'] = '本期新增'
df.loc[df['当期值(亿元/只)'].isnull(),'备注'] = '上期有,本期无'
df[df == 0] = np.nan
return df
5、最后输出,见主程序。