专栏首页源懒由码pandas系列 - (三)关于时点时期数据的处理

pandas系列 - (三)关于时点时期数据的处理

实际工作场景中,会遇到需要处理时序表。对于少量的时点时序数据,明细数据+数据透视表,也是很快能处理完成。大量的话,可能会出现有一点慢,同时一些计算字段的每次都要设置,不太方便处理。整理一个思路:将系统的时点时序数据进行汇总整合,并形成时序表。

  思路:结构化的数据是很方便处理,表格类的数据不方便程序处理,但是方便计算字段。所有思路是,
将制定指标归并,形成数据数据透视表,再通过列运算形成计算字段,再转回明细数据,最终根据自己
的需要进行处理。
  1、数据源读取;
  2、数据指标归并,将A1、A2指标,归并为A,归并的参照表以EXCEL的形式储存;
  3、数据汇总,用于原始数据是单个地方数据,比如通过汇总关系,汇总出华北地区,华南地区数据;
  4、增加计算字段,比如:原始数据中有销售额、销售人数,通过参照表:形成 人均销售额 = 销售额/销售人数。
  5、增加相对数据,一般时点数据都是当期值,用于分析的化,还需要知道“比上期”、“比年初”、“同比”等值、

 主函数:

%%time
# 获取源数据
df = get_src_data(r'data/input/20200930 zonghe3/' )
date_format = "%Y%m%d"
stack_drop = False  # 不删除指标为空的指标

# 保留基础数据,储存共有多少机构产品
df_base = df.loc[:,['机构名称','产品品种','数据管理机构']].drop_duplicates(subset =['机构名称','产品品种'],keep='first')
# 数据预处理
df = pre_handle_data(df)
# 读取参照表,参照表存放指标的归并关系,以及计算字段的公式
dfcz = pd.read_excel(r'data/input/cz-zgbgst.xlsx',dtype=object,sheet_name=0)
df['指标名称'] = df['行指标名称'] + df['列指标名称']
# 数据归并
df = reduce_data(df)
# 数据汇总
df = hz_data(df)
# 计算字段,df是处理过后的原始数据源
df = calcu_data(df)
# 在原始数据源的基础上,计算出相对数据
df_deal = calcu_relative_data(df)

1、数据源读取:

# 获取数据源
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 reduce_data(df):
    # 筛选字段
    # 选择需要的数
    df = df[df['指标名称'].isin(dfcz.loc[dfcz['是否筛选'] == 1,'指标名称'].values.tolist())].copy()
    # 内容转换
    df['指标名称'] = df['指标名称'].replace(dfcz['指标名称'].values.tolist(),dfcz['对应'].values.tolist())
    df.drop(columns=['行指标名称', '列指标名称', '数据表名称','机构产品标识'],inplace=True) 
    return df

3、增加计算字段,遍历参照表中的计算字段名,以及对应公式,使用df.eval进行计算。

# 计算字段,通过现有指标,计算出新的指标
def calcu_data(df):
    # 补充没有的列名,形成差集,补充新的列,这里是为了避免最后计算时造成的误差
    dft = dfcz[(dfcz['对应'].notnull())].drop_duplicates(subset =['对应'],keep='first')
    for dyl in dft['对应'].values.tolist():
        if not dyl in list(df.columns):
            df[dyl] = 0.0

    # 根据计算过程,得出计算字段
    df.fillna(0,inplace = True) # 填0,防止影响后面计算
    zbmcdf = dfcz[(dfcz['计算字段'].notnull()) & dfcz['计算过程'].notnull()].drop_duplicates(subset =['计算字段'],keep='first')
    for i,row in zbmcdf.iterrows():
        df[ str(row['计算字段'])] = df.eval(str(row['计算过程']))

    #将占比的列补充一个(%)
    dname = {}
    for c in df.columns:
        if str(c).find('占比') != -1 or str(c).find('率') != -1 or str(c).find('比率') != -1 or str(c).find('净值') != -1:
            if str(c).find('%') == -1:
                dname[str(c)] = str(c) + '(%)'
    if len(dname) > 0 :
        df.rename(columns=dname,inplace = True)
    
    # 将数据打散为明细
    dfout = df.set_index(['数据日期', '产品品种', '机构名称'])
    dfout.columns.names = ['指标名称'] 
    dfout[dfout == 0] = np.nan
    dfout.dropna(axis=1,how='all',inplace=True)   # 删除空列,减少后面的计算
    dfout = dfout.stack(dropna = True).reset_index() # 这里将新形成的指标转置,如果是空的话,择不保留。
    dfout.rename(columns={0:'00 当期值'},inplace = True)
    
    return dfout

返回数据类型:

4、增加相对数据,使用apply逐行增加比上期,比年初,同比增速,同比增减数据。

# 增加相对计算字段
def calcu_relative_data(df):
    # 计算相对数 calcu_relative_data

    # 生成日期范围列表
    date_list = list(set(df['数据日期'].values.tolist()))


    # 构建唯一索引
    df['unique'] = df['数据日期'] + ' ' + df['产品品种'] + ' ' + df['机构名称']+ ' ' + df['指标名称']
    dftest = df.set_index('unique',drop=False)
    df.drop(columns=['unique'],inplace=True)
    dftest.fillna(0,inplace = True) # 填0,防止影响后面计算
    # 计算前可以考虑做好,缺失值转换为0
    dftest['10 比上期'] = dftest.apply(add_huanbi,axis=1,args=(dftest,date_list,'数据日期','unique','00 当期值'))
    dftest['11 比上期-同比增减'] = dftest.apply(add_huanbi_onyear,axis=1,args=(dftest,date_list,'数据日期','unique','00 当期值'))
    dftest['20 比年初'] = dftest.apply(add_binianchu,axis=1,args=(dftest,date_list,'数据日期','unique','00 当期值'))
    dftest['21 比年初-同比增减'] = dftest.apply(add_binianchu_onyear,axis=1,args=(dftest,date_list,'数据日期','unique','00 当期值'))
    dsel = dftest['指标名称'].str.contains('%')
    dftest.loc[~dsel,'30 同比增速'] = dftest[~dsel].apply(add_tongbizengsu,axis=1,args=(dftest,date_list,'数据日期','unique','00 当期值'))
    # 根据指标名称,包含%只需要增加同比增减,不包含的化计算增速
    dftest.loc[dsel,'31 同比增减'] = dftest[dsel].apply(add_tongbi,axis=1,args=(dftest,date_list,'数据日期','unique','00 当期值'))
    dftest = dftest.reset_index(drop=True)
    dftest.drop(columns=['unique'],inplace=True)
    dftest = dftest.set_index(['数据日期', '产品品种', '机构名称', '指标名称'])
    dftest.columns.names = ['数据类型']
    # 这里可以考虑设置 dropna = False ,这样的话,就可以保持空值存在。
    dftest[dftest == 0] = np.nan
    dftest = dftest.stack(dropna = True).reset_index()  # 将数据转化为台账类型
    dftest.rename(columns={0:'数据值'},inplace = True)
    #这里把不需要的删除
    if stack_drop == False:
        dftest.drop(index=dftest[ (~(dftest['指标名称'].str.contains('%'))) & (dftest['数据类型'] == '31 同比增减') ].index,inplace=True)
        dftest.drop(index=dftest[ ((dftest['指标名称'].str.contains('%'))) & (dftest['数据类型'] == '30 同比增速') ].index,inplace=True)
    return dftest

最终输出样式是:

数据日期 产品品种 机构名称 指标名称 数据类型 数据值

A A A A 当期数 XX

最后,可以通过再处理一次pivot_table数据透视表得到想到的时序数据。后续,只需要修改参照表就可以快速转换成其他数据。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

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

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

    forxtz
  • python 行政区域地址标准化:业务经理填报的地址乱起八糟,高德接口有点厉害!

    需求:由于业务检查需求,需要将一个结构化地址,如”XX省XX市XX区XXX号“地区转化为对应国家统计区行政划分的

    forxtz
  • 关于pandas.eval使用的一些问题。

    https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.eval...

    forxtz
  • LAMP架构应用实战——PHP环境安装配置

    下载地址:http://ftp.gnu.org/pub/gnu/libiconv/

    民工哥
  • 谷歌大脑发布神经网络的「核磁共振」,并公开相关代码

    作者:杨晓凡、camel、思颖、杨文 AI 科技评论按:神经网络的可解释性一直是所有研究人员心头的一团乌云。传统的尝试进行可解释性研究的方法是通过查看网络中哪个...

    AI科技评论
  • 生鲜电商大比拼,大数据告诉你2015是谁的优胜年

    <数据猿导读> 随着电商事业的蓬勃发展,现在人们足不出户就能采购各类商品,便捷、优质的体验吸引了大量用户群体,各类生鲜电商们间的竞争也愈加激烈,下面就让我们看看...

    数据猿
  • 谷歌大脑发布神经网络的「核磁共振」,并公开相关代码

    神经网络的可解释性一直是所有研究人员心头的一团乌云。传统的尝试进行可解释性研究的方法是通过查看网络中哪个神经元被激发来来理解,但是即使我们知道「第 538 号神...

    AI研习社
  • redis 读写锁实现

    关于redis读写锁,我写了一次之后,总觉得很怪,然后就上网看到大神的redisson了,果断借鉴一番。

    ydymz
  • 全球顶尖公司的烧脑面试题,普通人一道都答不出来!

    一些世界知名的企业在招聘时,可能会提供面试智力题,来筛选应聘者。那些越是大牌,越是有名的国内500强,乃至世界500强,给出的面试真是一般人都答不出来。 谷歌...

    顶级程序员
  • CentOS 7.4 安装后优化配置 原

    1.网卡  [root@zhg1 ~]# vim /etc/sysconfig/network-scripts/ifcfg-ens32  显示结果:   ...

    拓荒者

扫码关注云+社区

领取腾讯云代金券