pandas數(shù)據(jù)處理+切片器創(chuàng)建每日數(shù)據(jù)動態(tài)看板

看板封面.png

1 讀取數(shù)據(jù)

import pandas as pd
import numpy as np
df = pd.read_csv(r'alldata(隨機抽15萬樣本).csv',low_memory=False)
df['時間戳']= pd.to_datetime(df['時間戳'])
df['月度'] = df['時間戳'].dt.year.astype(str)+'/'+df['時間戳'].dt.month.astype(str)
df['月度'] = pd.to_datetime(df['月度'],format='%Y/%M').dt.strftime('%Y-%M')
df['年度'] = df['時間戳'].dt.year
df['年度'] = df['年度'].astype(str)
df['日度'] = df['時間戳'].dt.date
df
image.png

1.2 每日不同產(chǎn)品線的同期數(shù)據(jù)

df_cateperday_2022 = (df.set_index('時間戳').query("年度=='2022'")
.groupby('產(chǎn)品').用戶.resample('D')
.count().to_frame('2022')
.reset_index()
.assign(月 = lambda x:x['時間戳'].dt.month
       ,日度 = lambda x:(x['時間戳'].dt.date).astype(str)
       ,日期 = lambda x:x['日度'].apply(lambda x:x.split('2022-')[1])
       )
)[['月','產(chǎn)品','日期','2022']]

df_cateperday_2021 = (df.set_index('時間戳').query("年度=='2021'")
.groupby('產(chǎn)品').用戶.resample('D')
.count().to_frame('2021')
.reset_index()
.assign(月 = lambda x:x['時間戳'].dt.month
       ,日度 = lambda x:(x['時間戳'].dt.date).astype(str)
       ,日期 = lambda x:x['日度'].apply(lambda x:x.split('2021-')[1])
       )
)[['月','產(chǎn)品','日期','2021']]

mer_result_li = pd.merge(df_cateperday_2021,df_cateperday_2022,how='outer')
mer_result_li['2021'] = mer_result_li['2021'].fillna(0)
mer_result_li
image.png

1.2.1 驗證一下產(chǎn)品A在2021年和2022年1月2日中的數(shù)據(jù)

len(df[(df['時間戳']>='2021-01-02')&(df['時間戳']<'2021-01-03')].query("產(chǎn)品=='A'")),len(df[(df['時間戳']>='2022-01-02')&(df['時間戳']<'2022-01-03')].query("產(chǎn)品=='A'"))

Out:(28, 17)

1.3 構(gòu)造一個新的產(chǎn)品數(shù)據(jù),其類型為:“所有數(shù)據(jù)”

all_li_2021 = (df.set_index('時間戳').query("年度=='2021'")
.用戶.resample('D')
.count().to_frame('2021')
.reset_index()
.assign(月 = lambda x:x['時間戳'].dt.month
       ,產(chǎn)品 = '所有數(shù)據(jù)'
       ,日度 = lambda x:(x['時間戳'].dt.date).astype(str)
       ,日期 = lambda x:x['日度'].apply(lambda x:x.split('2021-')[1])
       )
)[['月','產(chǎn)品','日期','2021']]

all_li_2022 = (df.set_index('時間戳').query("年度=='2022'")
.用戶.resample('D')
.count().to_frame('2022')
.reset_index()
.assign(月 = lambda x:x['時間戳'].dt.month
       ,產(chǎn)品 = '所有數(shù)據(jù)'
       ,日度 = lambda x:(x['時間戳'].dt.date).astype(str)
       ,日期 = lambda x:x['日度'].apply(lambda x:x.split('2022-')[1])
       )
)[['月','產(chǎn)品','日期','2022']]

All_li = pd.merge(all_li_2021,all_li_2022,how='outer')
All_li['2021'] = All_li['2021'].fillna(0)
All_li

注意將2021年的缺失值補為0,2022年的不需要,否則做折線圖的時候會有很長一段為0的數(shù)據(jù),影響視覺效果。


image.png

1.3.1 驗證1月1日的數(shù)據(jù)

len(df[(df['時間戳']>='2021-01-01')&(df['時間戳']<'2021-01-02')]),len(df[(df['時間戳']>='2022-01-01')&(df['時間戳']<'2022-01-02')])

[Out]:(37, 32)

1.4 拼接兩個模塊的數(shù)據(jù)

concat_apply_counts = (pd.concat([mer_result_li,All_li])#
   .assign(aa = lambda x:np.where(x['日期']<'04-29',x['2022'].fillna(0),np.NaN))
   .drop(labels='2022',axis=1).rename(columns={'aa':'2022'})
)#.to_clipboard()
concat_apply_counts

注意中間有個np.where的方法,當日期小于4月29日時,2022年的那一列填補缺失值為0,否則記為空值。


image.png

1.4.1 優(yōu)化小于日期的功能

每次運行程序盡量不要手動改日期,形成通用的數(shù)據(jù)處理流程應根據(jù)這張表的時間戳字段的最新日期作為數(shù)值,即數(shù)據(jù)更新到哪兒了。

查看新時間戳


image.png

+pd.DateOffset(days=1)可以使日期加上一天


image.png

str轉(zhuǎn)成字符串
image.png

最后取出相應的內(nèi)容


image.png
concat_apply_counts = (pd.concat([mer_result_li,All_li])#
   .assign(aa = lambda x:np.where(x['日期']<str(df['時間戳'].max()+pd.DateOffset(days=1))[5:10],x['2022'].fillna(0),np.NaN))
   .drop(labels='2022',axis=1).rename(columns={'aa':'2022'})
)#.to_clipboard()
concat_apply_counts

這時,時間戳字段就不能用lambda函數(shù)里面的x了,因為它代表了pd.concat中的那張表,因此得使用最開始的那張df表。

2 構(gòu)造每日不同產(chǎn)品的用戶數(shù)量(中間有大坑)

假設aaa用戶2021年1月1日,A產(chǎn)品,20次記錄。B產(chǎn)品,0次記錄。倘若用resample.count的方法,用戶數(shù)本應該是1個,但會記為2個。如果用resample.sum也是不行的。而且,當2021年1月2日,aaa用戶沒有記錄時,resample模塊會自動生成日期,并使得相應的數(shù)據(jù)等于0,那么第二次groupby的時候,一樣會記錄一次數(shù)據(jù)。

面對這樣的情形,resample就不合適了。需要通過時間戳構(gòu)造一列日期,所以第一次讀取數(shù)據(jù)時將日期做了處理。那么,沒有發(fā)生的數(shù)據(jù)就不會多出日期,并且對應數(shù)值為0的情況。

2.1 每個產(chǎn)品線的用戶數(shù)量

df_organ_cate_2022 = (df.query("年度=='2022'").groupby(['日度','用戶','產(chǎn)品']).日度.count().to_frame('次數(shù)').reset_index()
    .groupby(['日度','產(chǎn)品']).用戶.count().to_frame('2022點數(shù)').reset_index()
    .assign(日期 = lambda x:pd.to_datetime(x['日度'])
            ,月 = lambda x:x['日期'].dt.month
           )
)[['月','產(chǎn)品','日期','2022點數(shù)']]
df_organ_cate_2022['日期'] = df_organ_cate_2022['日期'].astype(str).apply(lambda x:x.split('2022-')[1])

df_organ_cate_2021 = (df.query("年度=='2021'").groupby(['日度','用戶','產(chǎn)品']).日度.count().to_frame('次數(shù)').reset_index()
    .groupby(['日度','產(chǎn)品']).用戶.count().to_frame('2021點數(shù)').reset_index()
    .assign(日期 = lambda x:pd.to_datetime(x['日度'])
            ,月 = lambda x:x['日期'].dt.month
           )
)[['月','產(chǎn)品','日期','2021點數(shù)']]
df_organ_cate_2021['日期'] = df_organ_cate_2021['日期'].astype(str).apply(lambda x:x.split('2021-')[1])

mer_result_cate = pd.merge(df_organ_cate_2021,df_organ_cate_2022,how='outer')
mer_result_cate['2021點數(shù)'] = mer_result_cate['2021點數(shù)'].fillna(0)
mer_result_cate
image.png

2.2 所有產(chǎn)品線的用戶數(shù)量

df_organ_all_2022 = (df.query("年度=='2022'").groupby(['日度','用戶']).日度.count().to_frame('次數(shù)').reset_index()
    .groupby(['日度']).用戶.count().to_frame('2022點數(shù)').reset_index()
    .assign(日期 = lambda x:pd.to_datetime(x['日度'])
            ,月 = lambda x:x['日期'].dt.month
            ,產(chǎn)品 = '所有數(shù)據(jù)'
           #,年度 = 
           )
)[['月','產(chǎn)品','日期','2022點數(shù)']]
df_organ_all_2022['日期'] = df_organ_all_2022['日期'].astype(str).apply(lambda x:x.split('2022-')[1])

df_organ_all_2021 = (df.query("年度=='2021'").groupby(['日度','用戶']).日度.count().to_frame('次數(shù)').reset_index()
    .groupby(['日度']).用戶.count().to_frame('2021點數(shù)').reset_index()
    .assign(日期 = lambda x:pd.to_datetime(x['日度'])
            ,月 = lambda x:x['日期'].dt.month
            ,產(chǎn)品 = '所有數(shù)據(jù)'
           #,年度 = 
           )
)[['月','產(chǎn)品','日期','2021點數(shù)']]
df_organ_all_2021['日期'] = df_organ_all_2021['日期'].astype(str).apply(lambda x:x.split('2021-')[1])

mer_result_all = pd.merge(df_organ_all_2021,df_organ_all_2022,how='outer')
mer_result_all['2021點數(shù)'] = mer_result_all['2021點數(shù)'].fillna(0)
mer_result_all
image.png

2.3 合并一下

concat_apply_members = (pd.concat([mer_result_cate,mer_result_all])#
   .assign(aa = lambda x:np.where(x['日期']<'04-29',x['2022點數(shù)'].fillna(0),np.NaN))
   .drop(labels='2022點數(shù)',axis=1).rename(columns={'aa':'2022點數(shù)'})
)
concat_apply_members
image.png

2.4 驗證1月1日A產(chǎn)品的用戶量

len(df[(df['時間戳']>='2021-01-01')&(df['時間戳']<'2021-01-02')].query("產(chǎn)品=='A'")['用戶'].unique()),len(df[(df['時間戳']>='2022-01-01')&(df['時間戳']<'2022-01-02')].query("產(chǎn)品=='A'")['用戶'].unique())

[Out]:(14, 8)

2.5 用每日數(shù)據(jù)量左連接每日用戶量,并粘貼到excel中

(pd.merge(concat_apply_counts,concat_apply_members,how='left')
    .assign(aa2021 = lambda x:x['2021點數(shù)'].fillna(0)
            ,aa2022 = lambda x:np.where(x['日期']<'04-29',x['2022點數(shù)'].fillna(0),np.NaN)
           )
     .drop(labels=['2021點數(shù)','2022點數(shù)'],axis=1)
     .rename(columns={'aa2021':'2021點數(shù)','aa2022':'2022點數(shù)'})
).to_clipboard(index=None,excel=True)#to_clipboard相當于復制,打開excel粘貼即可將數(shù)據(jù)傳入excel內(nèi)

2.6 嘗試寫一個類

默認使用2022年作為最新數(shù)據(jù),同期年份有所保留,是為了方便測試其他年份的數(shù)據(jù)

import pandas as pd
import numpy as np
df = pd.read_csv(r'alldata(隨機抽15萬樣本).csv',low_memory=False)
df['時間戳']= pd.to_datetime(df['時間戳'])
df['月度'] = df['時間戳'].dt.year.astype(str)+'/'+df['時間戳'].dt.month.astype(str)
df['月度'] = pd.to_datetime(df['月度'],format='%Y/%M').dt.strftime('%Y-%M')
df['年度'] = df['時間戳'].dt.year
df['年度'] = df['年度'].astype(str)
df['日度'] = df['時間戳'].dt.date
class Streaming_perday:
    
    def __init__(self,data,nowyear='2022',lastyear=None):
        self.data = data
        self.nowyear = nowyear
        self.nowformat = '%s點數(shù)'%self.nowyear
        self.lastyear = lastyear
        self.lastformat = '%s點數(shù)'%self.lastyear
        
    def perday_num(self):
        df_cateperday_2022 = (self.data.set_index('時間戳').query("年度=='%s'"%self.nowyear)
        .groupby('產(chǎn)品').用戶.resample('D')
        .count().to_frame('%s'%self.nowyear)
        .reset_index()
        .assign(月 = lambda x:x['時間戳'].dt.month
               ,日度 = lambda x:(x['時間戳'].dt.date).astype(str)
               ,日期 = lambda x:x['日度'].apply(lambda x:x.split('%s-'%self.nowyear)[1])
               )
        )[['月','產(chǎn)品','日期','%s'%self.nowyear]]

        df_cateperday_2021 = (self.data.set_index('時間戳').query("年度=='%s'"%self.lastyear)
        .groupby('產(chǎn)品').用戶.resample('D')
        .count().to_frame('%s'%self.lastyear)
        .reset_index()
        .assign(月 = lambda x:x['時間戳'].dt.month
               ,日度 = lambda x:(x['時間戳'].dt.date).astype(str)
               ,日期 = lambda x:x['日度'].apply(lambda x:x.split('%s-'%self.lastyear)[1])
               )
        )[['月','產(chǎn)品','日期','%s'%self.lastyear]]

        mer_result_li = pd.merge(df_cateperday_2021,df_cateperday_2022,how='outer')
        mer_result_li['%s'%self.lastyear] = mer_result_li['%s'%self.lastyear].fillna(0)

        #所有數(shù)據(jù)的resample
        all_li_2021 = (self.data.set_index('時間戳').query("年度=='%s'"%self.lastyear)
        .用戶.resample('D')
        .count().to_frame('%s'%self.lastyear)
        .reset_index()
        .assign(月 = lambda x:x['時間戳'].dt.month
               ,產(chǎn)品 = '所有數(shù)據(jù)'
               ,日度 = lambda x:(x['時間戳'].dt.date).astype(str)
               ,日期 = lambda x:x['日度'].apply(lambda x:x.split('%s-'%self.lastyear)[1])
               )
        )[['月','產(chǎn)品','日期','%s'%self.lastyear]]

        all_li_2022 = (self.data.set_index('時間戳').query("年度=='%s'"%self.nowyear)
            .產(chǎn)品.resample('D')
            .count().to_frame('%s'%self.nowyear)
            .reset_index()
            .assign(月 = lambda x:x['時間戳'].dt.month
                   ,產(chǎn)品 = '所有數(shù)據(jù)'
                   ,日度 = lambda x:(x['時間戳'].dt.date).astype(str)
                   ,日期 = lambda x:x['日度'].apply(lambda x:x.split('%s-'%self.nowyear)[1])
                   )
            )[['月','產(chǎn)品','日期','%s'%self.nowyear]]

        All_li = pd.merge(all_li_2021,all_li_2022,how='outer')
        All_li['%s'%self.lastyear] = All_li['%s'%self.lastyear].fillna(0)

        concat_apply_counts = (pd.concat([mer_result_li,All_li])#
       .assign(aa = lambda x:np.where(x['日期']<str(self.data['時間戳'].max()+pd.DateOffset(days=1))[5:10]#日期小于最大診斷時間的第二天,切割字符串
                                      ,x['%s'%self.nowyear].fillna(0),np.NaN)
                                      )
       .drop(labels='%s'%self.nowyear,axis=1).rename(columns={'aa':'%s'%self.nowyear})
        )

        return concat_apply_counts

    def perday_num_organ(self):
        df_organ_all_2022 = (self.data.query("年度=='%s'"%self.nowyear).groupby(['日度','用戶']).日度.count().to_frame('次數(shù)').reset_index()
            .groupby(['日度']).用戶.count().to_frame(self.nowformat).reset_index()
            .assign(日期 = lambda x:pd.to_datetime(x['日度'])
                    ,月 = lambda x:x['日期'].dt.month
                    ,產(chǎn)品 = '所有數(shù)據(jù)'
                   )
        )[['月','產(chǎn)品','日期',self.nowformat]]
        df_organ_all_2022['日期'] = df_organ_all_2022['日期'].astype(str).apply(lambda x:x.split('%s-'%self.nowyear)[1])

        df_organ_all_2021 = (self.data.query("年度=='%s'"%self.lastyear).groupby(['日度','用戶']).日度.count().to_frame('次數(shù)').reset_index()
            .groupby(['日度']).用戶.count().to_frame(self.lastformat).reset_index()
            .assign(日期 = lambda x:pd.to_datetime(x['日度'])
                    ,月 = lambda x:x['日期'].dt.month
                    ,產(chǎn)品 = '所有數(shù)據(jù)'
                   #,年度 = 
                   )
        )[['月','產(chǎn)品','日期',self.lastformat]]
        df_organ_all_2021['日期'] = df_organ_all_2021['日期'].astype(str).apply(lambda x:x.split('%s-'%self.lastyear)[1])

        df_organ_cate_2022 = (self.data.query("年度=='%s'"%self.nowyear).groupby(['日度','用戶','產(chǎn)品']).日度.count().to_frame('次數(shù)').reset_index()
            .groupby(['日度','產(chǎn)品']).用戶.count().to_frame(self.nowformat).reset_index()
            .assign(日期 = lambda x:pd.to_datetime(x['日度'])
                    ,月 = lambda x:x['日期'].dt.month
                   )
        )[['月','產(chǎn)品','日期',self.nowformat]]
        df_organ_cate_2022['日期'] = df_organ_cate_2022['日期'].astype(str).apply(lambda x:x.split('%s-'%self.nowyear)[1])

        df_organ_cate_2021 = (self.data.query("年度=='%s'"%self.lastyear).groupby(['日度','用戶','產(chǎn)品']).日度.count().to_frame('次數(shù)').reset_index()
            .groupby(['日度','產(chǎn)品']).用戶.count().to_frame(self.lastformat).reset_index()
            .assign(日期 = lambda x:pd.to_datetime(x['日度'])
                    ,月 = lambda x:x['日期'].dt.month
                   )
        )[['月','產(chǎn)品','日期',self.lastformat]]
        df_organ_cate_2021['日期'] = df_organ_cate_2021['日期'].astype(str).apply(lambda x:x.split('%s-'%self.lastyear)[1])

        mer_result_cate = pd.merge(df_organ_cate_2021,df_organ_cate_2022,how='outer')
        mer_result_cate[self.lastformat] = mer_result_cate[self.lastformat].fillna(0)

        mer_result_all = pd.merge(df_organ_all_2021,df_organ_all_2022,how='outer')
        mer_result_all[self.lastformat] = mer_result_all[self.lastformat].fillna(0)

        concat_apply_members = (pd.concat([mer_result_cate,mer_result_all])#
           .assign(aa = lambda x:np.where(x['日期']<str(self.data['時間戳'].max()+pd.DateOffset(days=1))[5:10]
                                          ,x[self.nowformat].fillna(0)
                                          ,np.NaN)
                                          )#注意選擇時間
           .drop(labels=self.nowformat,axis=1).rename(columns={'aa':self.nowformat})
        )
        return concat_apply_members
    
    def merge_result(self):
        mer_result = (
            pd.merge(self.perday_num(),self.perday_num_organ(),how='outer')
               .assign(aa2021 = lambda x:x[self.lastformat].fillna(0)
                       ,aa2022 = lambda x:np.where(
                                    x['日期']<str(self.data['時間戳'].max()+pd.DateOffset(days=1))[5:10]
                                    ,x[self.nowformat].fillna(0)
                                    ,np.NaN
                                       )
                        )
              .drop(labels=[self.lastformat,self.nowformat],axis=1)
              .rename(columns={'aa2021':self.lastformat,'aa2022':self.nowformat})
        )
        
        return mer_result#,mer_result.to_clipboard(index=None,excel=True),'已將數(shù)據(jù)結(jié)果進行復制,請移至excel中進行粘貼....'

# stream = Streaming_perday(data=df,lastyear='2021')
# stream.merge_result()
if __name__=="__main__":
    stream = Streaming_perday(data=df,lastyear='2021')
    print(stream.merge_result())

【Out】: 月 產(chǎn)品 日期 2021 2022 2021點數(shù) 2022點數(shù)
0 1 A 01-01 21.0 21.0 14.0 8.0
1 1 A 01-02 28.0 17.0 19.0 13.0
2 1 A 01-03 28.0 22.0 18.0 16.0
3 1 A 01-04 46.0 41.0 31.0 24.0
4 1 A 01-05 48.0 46.0 26.0 24.0
... .. ... ... ... ... ... ...
2273 12 所有數(shù)據(jù) 12-27 44.0 NaN 22.0 NaN
2274 12 所有數(shù)據(jù) 12-28 43.0 NaN 25.0 NaN
2275 12 所有數(shù)據(jù) 12-29 36.0 NaN 21.0 NaN
2276 12 所有數(shù)據(jù) 12-30 47.0 NaN 22.0 NaN
2277 12 所有數(shù)據(jù) 12-31 58.0 NaN 30.0 NaN

3 搭建動態(tài)看板

image.png

注意兩點即可:
1.更新數(shù)據(jù)源


image.png

2.右鍵切片器選擇報表鏈接,勾選透視表


image.png

3.選項功能添加自定義排序,使得產(chǎn)品切片器按鈕以對應數(shù)據(jù)量的大小來進行排序。


image.png

4.美化圖(略...)

5.從上圖不難發(fā)現(xiàn),從3月后半段開始,數(shù)據(jù)迅速下滑,同期下降30%+。然而根據(jù)3月的數(shù)據(jù)報告顯示,3月同期下降僅為10%,“10%”的指標有相當大的迷惑性。搭建每日的動態(tài)看板,及時向業(yè)務部反應情況,就能很好地彌補月匯報滯后性的不足。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容