1. 程式人生 > 實用技巧 >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資料透視表得到想到的時序資料。後續,只需要修改參照表就可以快速轉換成其他資料。