pandas系列 - (二)关于两期时点数据的比较

2020-10-28 11:36:16 浏览数 (2)

统计数据来说,有时点数据和时期数据。通常情况下,会进行两期数据的比较,现整理一个两期数据比较的场景应用。主要流程分为:

1、数据读取

2、数据预处理

3、数据分类汇总

4、两期数据比较

5、数据输出到EXCEL

主程序如下:

代码语言:javascript复制
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进行数据合并。

代码语言:javascript复制
# 获取数据源
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、进行数据预处理,如单位转换,不需要的数据剔除。

代码语言:javascript复制
# 数据预处理,指标归并、数据删除
def pre_handle_data(df):
    # 预处理数据
    return df

3、由于当前处理的数据是单机构的数据,想进行汇总查看整体数据情况。使用pivot_table进行汇总,接着使用reset_index转化为明细项进行合并到源数据中。

代码语言:javascript复制
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拼接到一起。

代码语言:javascript复制
# 数据比较
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、最后输出,见主程序。

0 人点赞