一、背景:
在對(duì)運(yùn)營看板進(jìn)行數(shù)據(jù)分析時(shí),發(fā)現(xiàn)一個(gè)極端異常數(shù)據(jù),在同類維度中,未完成量明顯高于其他維度,如下圖所示。于是通過python對(duì)數(shù)據(jù)作進(jìn)一步挖掘、處理、分析,找到背后的原因。

BI看板截圖
在對(duì)運(yùn)營看板進(jìn)行數(shù)據(jù)分析時(shí),發(fā)現(xiàn)一個(gè)極端異常數(shù)據(jù),在同類維度中,未完成量明顯高于其他維度,如下圖所示。于是通過python對(duì)數(shù)據(jù)作進(jìn)一步挖掘、處理、分析,找到背后的原因。
#導(dǎo)入需要用到的一些包
from pyecharts import Bar
import pymysql
import pandas as pd
import numpy as np
#輸入數(shù)據(jù)庫相關(guān)參數(shù),連接數(shù)據(jù)庫
conn_test = pymysql.connect(
host='*********',
port=3306,
user='********',
passwd='********',
db='*********'
)
cur_test = conn_test.cursor()#使用cursor()方法獲取操作游標(biāo)
cur_test.execute("select ******************")
data_activity_order = cur_test.fetchall()#獲取查詢的數(shù)據(jù)
columnDes = cur_test.description#所有數(shù)據(jù)的描述
columnNames = [columnDes[i][0] for i in range(len(columnDes))]#通過描述,得到列名稱
df_activity_order= pd.DataFrame(list(data_activity_order))#得到的數(shù)據(jù)data_activity_order是元組,元組要轉(zhuǎn)為list,list再次轉(zhuǎn)為dataframe
df_activity_order.columns = columnNames#修改df_activity_order列名稱為數(shù)據(jù)庫里的列名稱
注釋:c_state即為數(shù)據(jù)表中表示狀態(tài)的字段名。
df_activity_order.loc[df_activity_order['c_state']==0,'c_state'] = '未完成'#通過df.loc函數(shù),按特定的標(biāo)簽獲取數(shù)據(jù),并對(duì)數(shù)據(jù)進(jìn)行替換。
df_activity_order.loc[df_activity_order['c_state']==1,'c_state'] = '已完成'
df_activity_order = df_activity_order.set_index(['c_state'],inplace=False)#將索引替換成c_pay_state,進(jìn)而便于后續(xù)對(duì)數(shù)據(jù)進(jìn)行拆分、重塑操作。
df_activity_order_finish = df_activity_order.loc[df_activity_order.index == '已完成']#通過df.loc函數(shù)提取“已完成”的數(shù)據(jù),并且存入新的df中。
df_activity_order_unfinish = df_activity_order.loc[df_activity_order.index == '未完成']#通過df.loc函數(shù)提取“未完成”的數(shù)據(jù),并且存入新的df中。
df_activity_order_finish = df_activity_order_finish.set_index(['days'],inplace=False)#對(duì)df重置索引為日期
df_activity_order_unfinish = df_activity_order_unfinish.set_index(['days'],inplace=False)#同上
df_activity_order_finish.columns = ['amount_finish']#由于查詢出來的column都是amount,于是在此將df_activity_order_finish的columns 修改成amount_finish
df_activity_order_unfinish.columns = ['amount_unfinish']#同上
date_list = pd.date_range(start='20181011',end='20190820')#獲取起始日期至末尾日期之間的日期序列。
len_date_list = len(date_list)#獲取時(shí)間序列的長度,作為后續(xù)df的行數(shù)
df_date_list_finish = pd.DataFrame(np.zeros((len_date_list,1),dtype=np.int),columns = ['amount_finish'],index=date_list)#利用np.zeros構(gòu)建全0的array,再用pd.DataFrame轉(zhuǎn)換成df
df_date_list_unfinish = pd.DataFrame(np.zeros((len_date_list,1),dtype=np.int),columns = ['amount_unfinish'],index=date_list)#同上
df_activity_order_finish_new = (df_date_list_finish + df_activity_order_finish).fillna(0)#將拆分后完成的df與時(shí)間連續(xù)的df進(jìn)行合并,缺失值以0補(bǔ)齊。
df_activity_order_unfinish_new = (df_date_list_unfinish + df_activity_order_unfinish).fillna(0)#同上
df_per = pd.concat([df_activity_order_finish_new,df_activity_order_unfinish_new],axis=1, join_axes=[df_activity_order_unfinish_new.index])#將重塑后的已完成、未完成df進(jìn)行合并。
#計(jì)算已完成的數(shù)量在當(dāng)日的占比情況,
with np.errstate(invalid='ignore'):#由于可能存在分母為0的情況,計(jì)算過程中會(huì)報(bào)錯(cuò),因而需要對(duì)此類報(bào)錯(cuò)進(jìn)行忽略。
df_per['per'] = df_per.apply(lambda x: x['amount_finish'] / (x['amount_unfinish']+x['amount_finish']), axis=1)#計(jì)算已完成的數(shù)量在當(dāng)日的占比情況。
df_per = df_per.fillna(0)#錯(cuò)誤值以0補(bǔ)齊。
df_per = df_per.round(3)#保留三位小數(shù)
至此,已經(jīng)將數(shù)據(jù)從數(shù)據(jù)庫中提取出來,并已經(jīng)處理好了,按照日期序列作了重塑,保證時(shí)間的連續(xù)性,同時(shí)也計(jì)算了當(dāng)日完成的數(shù)據(jù)占當(dāng)日總數(shù)的比例情況。
bar_df_per = Bar("每日訂單情況","")
bar_df_per.add('完成數(shù)',df_new.index,df_new.amount_finish,mark_point=["max", "min"],mark_line=["average"],is_more_utils = True,is_datazoom_show=True, datazoom_type="both",is_stack= True)
bar_df_per.add('未完成數(shù)',df_new.index,df_new.amount_unfinish,mark_point=["max", "min"],mark_line=["average"],is_more_utils = True,is_datazoom_show=True, datazoom_type="both",is_stack= True)
bar_df_per.add('完成數(shù)占當(dāng)日的比例',df_new.index,df_new.per,mark_point=["max", "min"],mark_line=["average"],is_more_utils = True,is_datazoom_show=True, datazoom_type="both",)
bar_df_per.render()
從上面的數(shù)據(jù)圖,我們可以看出異常的數(shù)據(jù)來自于05.08日。接下來再從數(shù)據(jù)庫中,對(duì)這一天的數(shù)據(jù),按照相關(guān)的維度進(jìn)行進(jìn)一步挖掘、分析,進(jìn)而找到背后的原因。
寫在后面的話:
文中部分操作可能饒了彎路,有可以優(yōu)化的空間,但是主要是想借著這次業(yè)務(wù)場景,整理下python的部分?jǐn)?shù)據(jù)處理思路、方法。
另外,請(qǐng)忽略不規(guī)則的變量命名,畢竟調(diào)研得出,大部分人認(rèn)為編程中最困難的一件事就是給變量命名。o(╯□╰)o




