本案例數據集地址(百度網盤):鏈接:https://pan.baidu.com/s/1FsEcr3lanXYbYLxGELtJZw 提取碼:5nvw (此鏈接永久有效)
或掃描下方二維碼獲取:
在本次博客中,我將利用Python數據分析工具來做一個某醫院某年度的銷售情況匯總。
項目運行環境:
操作系統 | Windows 10 64位 |
Python | 3.7.0 |
開發工具 | Pycharm(ipython) |
數據分析的基本過程主要分為兩方面:
一、數據分析的目的
一方面是發現問題,並且找到問題的根源,最終通過切實可行的辦法解決存在的問題;另一方面,提取有用信息和形成結論而對數據加以詳細研究和概括,對以往的數據分析,總結發展趨勢,為網絡營銷決策提供支持。
二 、數據分析基本過程
數據分析基本過程包括:獲取數據、數據清洗、構建模型、數據可視化、得出結論。
1.獲取數據
注:本次項目使用的數據請在前面鏈接自行下載
導包
import os import pandas as pd import matplotlib.pyplot as plt |
os.chdir(r'填寫你的數據所在路徑') #比如:os.chdir(r'F:\360Downloads\朝陽醫院') |
dataDF=pd.read_ecxel('文件名(記得帶文件后綴名)') #比如:dataDF=pd.read_excel('朝陽醫院2018年銷售數據.xlsx') |
dataDF.head() #默認查看前5行 |
接下來查看數據的下列信息:shape(形狀)、index(索引)、columns(列名)、count(總數)
dataDF.shape #查看數據的結構(行、列數) |
dataDF.index #查看數據的索引 |
dataDF.columns #查看數據的列名 |
dataDF.count() #查看數據的總數 |
dataDF.describe() #查看數據的數值詳細信息 |
通過以上的數據可以看出: 總共有6578行7列數據,但是“購葯時間”和“社保卡號”這兩列只有6576個數據,而“商品編碼”一直到“實收金額”這些列都是只有6577個數據。這就意味着數據中存在缺失值,可以推斷出數據中存在一行缺失值。 此外“購葯時間”和“社保卡號”這兩列都各自存在一個缺失數據,這些缺失數據在后面步驟中需要進一步處理。 而且數據中存在負數,這將在后面也需要進一步處理。 |
2.數據清洗
數據清洗通常包括:選擇子集、修改列名稱、處理缺失值、處理異常值、轉換數據類型、數據排序(為可視化做准備),在這里我們根據實驗數據本身特征進行處理,過程如下:
選擇子集:
在進行數據分析時,通常會遇到非常龐大的數據包,並且其中難免會有一些‘無用’的數據,以及和本次項目不相關的信息,這時就需要將其分開並按照需求選擇,得到有價值的數據集來進行進一步分析,從而挖掘出我們需要的潛在信息。由於本次案例使用的數據集量小且簡單,因此可以忽略這一步。 |
修改列名稱:
在拿到的原始數據中,列名稱和數據和其他列名之間可能會相似或者不能夠‘見名知意’,導致給后續分析帶來困難,為了避免此現象,我們可以根據需求調用rename()函數將列名重命名,比如中文名稱(這里純屬個人習慣) |
dataDF=dataDF.rename(columns={'購葯時間':'銷售時間'}) dataDF.head() |
處理缺失值:
通過上面的dataDF.count()可以看出,數據的“購葯時間”和“社保卡號”行數和其他數據不相等,證明肯定存在空值,為了不對后續的操作造成干擾,在這里需要進一步處理,通常處理方式有兩種:第一,刪除;第二,填充。在本次案例中,由於數據簡單,我們采用第一種方式將含有空值的行刪除,得到‘干凈’數據,使用到的函數有dropna() |
dataDF=dataDF.dropna(subset=['銷售時間','社保卡號'],how='any') dataDF.count() |
處理異常值:
我們先來查看一下數據的當前信息:
dataDF.describe() |
可以看出數據當中存在異常值(負值)。
現在我們刪除負值所在的行
pop=dataDF.loc[:,'銷售數量']>0 |
dataDF=dataDF.loc[pop,:] dataDF.describe() |
接下來再查看一下數據信息(行數)
轉換數據類型:
我們先來查看一下數據的當前類型:
發現銷售時間這一列並不是我們想要的datetime格式,因此需要轉換,為后續分析做准備。這里使用到的函數有:astype()函數
在處理之前,原始數據如下圖(發現‘銷售時間’這一列存在星期*,顯然這並不是我們需要的,接下來我們編寫(分割)函數將其去除,具體操作如下):
下圖是我編寫的一個(分割)函數以及具體操作(此處方法很多,遠遠不止這一種)
本案例操作方法如下:
調用函數,處理數據(具體過程見上圖的‘函數調用方法’部分)
time=dataDF.loc[:,'銷售時間'] data=SplitSaletime(time) dataDF.loc[:,'銷售時間']=data |
處理后的數據(銷售時間)如下:
查看當前數據類型(如下圖,發現銷售時間列格式已經修改成功,接下來將其轉換為datetime類型即可):
dataDF.loc[:,'銷售時間']=pd.to_datetime(dataDF.loc[:,'銷售時間'],format='%Y-%m-%d',errors='coerce') |
此時我們再來看數據(銷售時間)類型,發現已經轉換成功:
數據排序(重置索引):
接下來我們按照時間列進行升序排序
dataDF=dataDF.sort_values(by=['銷售時間'],ascending=True) #by='填寫需要按照那一列來排序',ascending=True表示升序(False表示降序) |
然后重置索引
dataDF=dataDF.reset_index(drop=True) |
3.構建模型
數據准備就緒后,根據相關業務利用可視化工具實現圖標制作,從而挖掘出數據背后的信息。 |
需求一:月均消費次數(月均消費次數 = 總消費次數/月份數)
第一步:計算總消費次數(為了便於統計,每張社保卡在當天的所有消費記錄當做一次消費,因此首先需要對數據進行‘去重’操作,這里需要用到drop_duplicates()函數)
dataDF_qc=dataDF.drop_duplicates(subset=['銷售時間','社保卡號']) |
接着查看數據形狀,看是否有變化:
再看一下原始數據形狀:
打印重復的行數:
print(f'原始數據與去重后的數據行數相差:{dataDF.shape[0]-dataDF_qc.shape[0]}行。') |
計算總消費次數:
Total_time=dataDF_qc.shape[0] |
結果如下:
第二步:計算月份數
按照銷售時間升序排序,然后重置索引
升序排序 | dataDF_shengxu=dataDF_qc.sort_values(by=['銷售時間'],ascending=True) |
重置索引 | dataDF_qc_resrt_index=dataDF_qc.reset_index(drop=True) |
索引:
計算銷售時間范圍:
StartTime=dataDF_qc_resrt_index.loc[0,'銷售時間'] |
EndTime=dataDF_qc_resrt_index.loc[Total_time-1,'銷售時間'] |
此時發現銷售時間出現空值,因此這里我們刪除空值所在行數據:
dataDF_qc_resrt_index.dropna(subset=['銷售時間'],inplace=True) |
現在我們重復上述步驟獲取開始和結束時間:
StartTime=dataDF_qc_resrt_index.loc[0,'銷售時間'] |
EndTime=dataDF_qc_resrt_index.loc[Total_time-1,'銷售時間'] |
計算總天數:
Day_time=(EndTime-StartTime).days |
計算月份數:
Month_time=Day_time//30 #其中//為整除運算,每月按30天計 |
月均消費次數 = 總消費次數/月份數:
Ave_time=Total_time//Month_time |
需求二:月均消費金額(月均消費次數 = 總消費金額/月份數)
第一步:計算總消費金額(這里用到sum()函數求和)
Total_Money=data_new.loc[:,'實收金額'].sum() |
第二步:計算月均消費金額
print(f'每月平均消費{(Total_Money//Month_time)}元。') |
需求三:每次購葯平均消費金額(每次購葯平均消費金額 = 總消費金額/總購葯次數)
print(f'每次購葯平均消費金額為:{(Total_Money/Total_time)}元。') |
4.數據可視化
准備工作:
導入可視化包: import matplotlib.pyplot as plt 遇到數據中有中文的時候,一定要先設置中文字體 plt.rcParams['font.sans-serif']=['SimHei'] # 用黑體顯示中文 |
首先將數據復制到一個新的變量,專門用作數據可視化
Data_KSH=dataDF_qc_resrt_index |
需求一:查看每日消費金額
重置索引為‘銷售時間’列:
Data_KSH.index=Data_KSH['銷售時間'] |
繪制圖形:
總結:日均 消費金額大部分集中在500元左右,並且上下波動不大。
需求二:查看每月銷售金額
數據聚合(按照月份):
Mon=Data_KSH.groupby(Data_KSH.index.month) |
利用sum()求和,計算每月銷售金額:
Mon_Money=Mon.sum() |
繪制圖形:
總結:如圖所示:3、4、5、6月份銷售數據相對平穩均在4500元左右,其他月份波動較大。
需求三:查看銷售量前十的葯品
按照銷售數量排序:
Data_XSSL=Data_KSH.sort_values(by='銷售數量') |
按照銷售數量去重:
Data_XSSL=Data_XSSL.drop_duplicates(subset=['銷售數量']) |
提取前十行數據:
Top_10=Data_XSSL.iloc[:10,:] |
查看前十行數據:
繪制圖形:
總結:銷售量前十的葯品如圖所示。
三、附件:本案例源代碼
本案例數據集地址(百度網盤):鏈接:https://pan.baidu.com/s/1mStg3VcubipPx3EzQwMLEQ 提取碼:5ua5 (此鏈接永久有效)
或者掃描下方二維碼獲取源代碼: