基于業(yè)務(wù)淺談python的數(shù)據(jù)處理思路【一】

一、背景:

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

【注:下圖中紅色代表完成量,藍(lán)色代表未完成量,數(shù)值9173為異常數(shù)據(jù)?!?div id="u0z1t8os" class="image-package">
BI看板截圖
思路:先連接數(shù)據(jù)庫查詢?cè)摼S度相關(guān)數(shù)據(jù)隨時(shí)間維度的分布情況,看看是否能找出異常的時(shí)間點(diǎn)。
二、本文主要包括如下幾方面內(nèi)容:
  • 用python連接數(shù)據(jù)庫,查詢數(shù)據(jù)
  • 將查詢出的數(shù)據(jù)轉(zhuǎn)變成DataFrame
  • 修改/替換DataFrame中某列的值
  • 修改DataFrame的column值
  • 對(duì)DataFrame重置索引
  • 對(duì)DataFrame作切片操作
  • 對(duì)時(shí)間不連續(xù)的數(shù)據(jù),作連續(xù)態(tài)處理
  • 利用DataFrame的數(shù)據(jù),繪制直方圖
三、數(shù)據(jù)處理
1、導(dǎo)入包,定義數(shù)據(jù)庫連接參數(shù)
#導(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)
2、輸入查詢語句,獲取相關(guān)數(shù)據(jù)
cur_test.execute("select ******************")
data_activity_order = cur_test.fetchall()#獲取查詢的數(shù)據(jù)
打印查詢的數(shù)據(jù)結(jié)果如下圖所示,其中0代表未完成,1代表完成。
3、將數(shù)據(jù)轉(zhuǎn)換成DataFrame
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ù)庫里的列名稱
4、將列表中狀態(tài)值為0、1分別替換成未完成、已完成

注釋: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'] = '已完成'
打印轉(zhuǎn)換后的DataFrame,其中c_state的值已經(jīng)進(jìn)行了替換。
5、更改索引為c_state(狀態(tài)),將列表作拆分
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,注意其中的時(shí)間存在不連續(xù)的情況。
6、將拆分后的表更改索引為days(日期),為后面的數(shù)據(jù)重塑作準(zhǔn)備。
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']#同上
7、構(gòu)建時(shí)間連續(xù)、值為0的空列表。
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)#同上
8、對(duì)數(shù)據(jù)進(jìn)行重塑,保證時(shí)間連續(xù),同時(shí)計(jì)算完成占當(dāng)日的比例情況。
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ù)
處理后的df

至此,已經(jīng)將數(shù)據(jù)從數(shù)據(jù)庫中提取出來,并已經(jīng)處理好了,按照日期序列作了重塑,保證時(shí)間的連續(xù)性,同時(shí)也計(jì)算了當(dāng)日完成的數(shù)據(jù)占當(dāng)日總數(shù)的比例情況。

四、數(shù)據(jù)可視化
1、對(duì)數(shù)據(jù)結(jié)果作可視化處理,便于直觀查看數(shù)據(jù)的分布情況。
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ù)圖,我們可以看出異常的數(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

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

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

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