4 分析藥店銷售數據

課程中不明白的地方,可以參考下面學習資料進行補充學習

Numpy簡易教程https://docs.scipy.org/doc/numpy-dev/user/quickstart.html

Pandas簡易教程http://pandas.pydata.org/pandas-docs/stable/10min.html

一 接下來只記錄自己在使用過程中遇到的疑點:

numpy主要用來做數值運算,元素只能是同類型,多用來表示演算法

pandas相當於一個表,涉及到表的行和列標記,表的增刪改查等基本操作,元素可以是不同類型,主要用來做統計。

numpy和Pandas學習記錄

1. np.array是numpy這個模塊包含的一個方法,該方法傳入一個列表為參數,在方法內實例化ndarray類,並返回該實例: a = np.array([1,2,3])相當於

def array( list or tuple):

arr = ndarray(list or tuple)

return arr

Pandas在創建Series和DataFrame時和numpy一樣,Pandas的Series由list創建一個一維序列,DataFrame由array或字典創建一個二維表

2. np.arrage()方法跟python本身的方法類似,只是返回的是array,又由於np.arrage()方法不能預知生成的array的長度,所以經常使用linspace代替。

3. 在numpy中所有的算術運算都是針對array中的每個元素的。

4. numpy的axis參數的作用要注意。axis=0表示array按列運算也就是計算每一列,axis=1表示array按行運算也就是計算每一行。

5. 要區分模塊自帶的函數和array或Series和DataFrame對象的方法,下面是自帶的函數和對象方法的簡單區分。

自帶函數:np.func()

對象方法:array.func() Series.func() DataFrame.func()

6. 跨步切片和逆轉功能。

二 數據分析的基本過程

提出問題:在很多時候,提出問題比解決問題更重要,因為只有知道問題是什麼,才能夠一步步地推導出為什麼會有這樣或那樣的解法,在解決問題過程中才能始終知道自己要什麼,朝什麼目標前進。

理解數據:這是在數據處理前期一定會遇到的是,一般包括閱讀數據集的概要,讀取數據,查看前幾行數據以對數據集有個大概的了解,查看數據集的行數和列數,查看相關列的數據類型等等。

數據清洗:這一步基本上是整個數據分析過程耗時最長,最繁瑣的。但是其結果即數據清洗完後的質量直接關係到後面在建模結果的好壞。

一般包括:1)選擇子集 2)列名重命名 3)缺失數據處理 4)數據類型轉換 5)數據排序 6)異常值處理

構建模型:如果是求客戶要求的指標的話,那平時的pandas操作就可以做到,如果是要對數據集分類等處理,那就需要構建機器學習模型。

數據可視化:可視化有助對數據處理過程和結果的理解。

三 藥店銷售數據分析

案例藥店銷售數據分析第4關通過一個案例學會數據分析的基本過程數據分析的基本步驟1提出問題 2理解數據 3清洗數據 4構建模型 5結果可視化In [11]:#導入數據分析包 需要安裝一個讀取excel文件的依賴包:xlrd,安裝步驟如下:import pandas as pd1.提出問題從銷售數據中分析出以下業務指標 1月均消費次數2月均消費金額3客單價4消費趨勢2.理解數據In [3]:2.1 #2.1 讀取Ecxcel數據,統一先按照字元串讀入,之後轉換fileNameStr=rE:Jupyter第4關數據分析的基本過程朝陽醫院2018年銷售數據.xlsxxls = pd.ExcelFile(fileNameStr, dtype=object)salesDf = xls.parse(Sheet1,dtype=object)In [8]:#2.2 列印出前5行,對數據集有個大概了解,以確保數據運行正常salesDf.head()Out[8]:購葯時間 社保卡號 商品編碼 商品名稱 銷售數量 應收金額 實收金額0 2018-01-01 星期五 001616528 236701 強力VC銀翹片 6 82.8 691 2018-01-02 星期六 001616528 236701 清熱解毒口服液 1 28 24.642 2018-01-06 星期三 0012602828 236701 感康 2 16.8 153 2018-01-11 星期一 0010070343428 236701 三九感冒靈 1 28 284 2018-01-15 星期五 00101554328 236701 三九感冒靈 8 224 208In [7]:#2.3 查看有多少行,多少列salesDf.shapeOut[7]:(6578, 7)In [6]:#2.4 查看每一列的數據類型salesDf.dtypesOut[6]:購葯時間 object社保卡號 object商品編碼 object商品名稱 object銷售數量 object應收金額 object實收金額 objectdtype: object3.數據清洗In [5]:#3.1 選擇子集(本案例不需要選擇子集)#注釋掉#subSalesDf=salesDf.loc[0:4,購葯時間:銷售數量]In [12]:#3.2 列名重命名#字典:舊列名和新列名對應關係colNameDict = {購葯時間:銷售時間}salesDf.rename(columns = colNameDict,inplace=True)#inplace=True,數據框本身會改動salesDf.head()Out[12]:銷售時間 社保卡號 商品編碼 商品名稱 銷售數量 應收金額 實收金額0 2018-01-01 星期五 001616528 236701 強力VC銀翹片 6 82.8 691 2018-01-02 星期六 001616528 236701 清熱解毒口服液 1 28 24.642 2018-01-06 星期三 0012602828 236701 感康 2 16.8 153 2018-01-11 星期一 0010070343428 236701 三九感冒靈 1 28 284 2018-01-15 星期五 00101554328 236701 三九感冒靈 8 224 2083.3 缺失數據處理python缺失值有3種1Python內置的None值2在pandas中將缺失值表示為NA表示不可用not available3對於數值數據pandas使用浮點值NaNNot a Number表示缺失數據所以缺失值有3種NoneNANaNIn [13]:print(刪除缺失值前大小,salesDf.shape)#刪除列(銷售時間,社保卡號)中為空的行#how=any 在給定的任何一列中有缺失值就刪除salesDf=salesDf.dropna(subset=[銷售時間,社保卡號],how=any)print(刪除缺失後大小,salesDf.shape)刪除缺失值前大小 (6578, 7)刪除缺失後大小 (6575, 7)In [26]:.1 #3.4 數據類型轉換 #3.4.1 字元串轉換為數值(浮點型)salesDf[銷售數量] = salesDf[銷售數量].astype(float)salesDf[應收金額] = salesDf[應收金額].astype(float)salesDf[實收金額] = salesDf[實收金額].astype(float)print(轉換後的數據類型:
,salesDf.dtypes)運行後,會報警告SettingWithCopyWarning一般信息有兩列,一類是Warning警告信息,一類是Error錯誤信息。警告的信息不用管,我們只關注錯誤類型的信息轉換後的數據類型 銷售時間 object社保卡號 object商品編碼 object商品名稱 object銷售數量 float64應收金額 float64實收金額 float64dtype: objectC:installAnaconda3libsite-packagesipykernel__main__.py:2: SettingWithCopyWarning: A value is trying to be set on a copy of a slice from a DataFrame.Try using .loc[row_indexer,col_indexer] = value insteadSee the caveats in the documentation: http://pandas.pydata.org/pandas-docs/stable/indexing.html#indexing-view-versus-copy from ipykernel import kernelapp as appC:installAnaconda3libsite-packagesipykernel__main__.py:3: SettingWithCopyWarning: A value is trying to be set on a copy of a slice from a DataFrame.Try using .loc[row_indexer,col_indexer] = value insteadSee the caveats in the documentation: http://pandas.pydata.org/pandas-docs/stable/indexing.html#indexing-view-versus-copy app.launch_new_instance()C:installAnaconda3libsite-packagesipykernel__main__.py:4: SettingWithCopyWarning: A value is trying to be set on a copy of a slice from a DataFrame.Try using .loc[row_indexer,col_indexer] = value insteadSee the caveats in the documentation: http://pandas.pydata.org/pandas-docs/stable/indexing.html#indexing-view-versus-copyIn [23]:#3.4.2 字元串轉換為日期數據類型定義函數:分割銷售日期,獲取銷售日期輸入:timeColSer 銷售時間這一列,是個Series數據類型輸出:分割後的時間,返回也是個Series數據類型def splitSaletime(timeColSer): timeList=[] for value in timeColSer: #例如2018-01-01 星期五,分割後為:2018-01-01 dateStr=value.split( )[0] timeList.append(dateStr) #將列錶轉行為一維數據Series類型 timeSer=pd.Series(timeList) return timeSer#獲取「銷售時間」這一列timeColSer = salesDf.loc[:,銷售時間]#對字元串進行分割,獲取銷售日期timeSer = splitSaletime(timeColSer)In [26]:#修改銷售時間這一列的值salesDf.loc[:,銷售時間]=timeSersalesDf.head()Out[26]:銷售時間 社保卡號 商品編碼 商品名稱 銷售數量 應收金額 實收金額0 2018-01-01 001616528 236701 強力VC銀翹片 6 82.8 691 2018-01-02 001616528 236701 清熱解毒口服液 1 28 24.642 2018-01-06 0012602828 236701 感康 2 16.8 153 2018-01-11 0010070343428 236701 三九感冒靈 1 28 284 2018-01-15 00101554328 236701 三九感冒靈 8 224 208In [37]:數據類型轉換:字元串轉換為日期#errors=coerce 如果原始數據不符合日期的格式,轉換後的值為空值NaT#format 是你原始數據中日期的格式salesDf.loc[:,銷售時間]=pd.to_datetime(salesDf.loc[:,銷售時間], format=%Y-%m-%d, errors=coerce)C:installAnaconda3libsite-packagespandascoreindexing.py:517: SettingWithCopyWarning: A value is trying to be set on a copy of a slice from a DataFrame.Try using .loc[row_indexer,col_indexer] = value insteadSee the caveats in the documentation: http://pandas.pydata.org/pandas-docs/stable/indexing.html#indexing-view-versus-copy self.obj[item] = sIn [38]:salesDf.dtypessalesDf.dtypesOut[38]:銷售時間 datetime64[ns]社保卡號 object商品編碼 object商品名稱 object銷售數量 float64應收金額 float64實收金額 float64dtype: objectIn [39]:銷售時間社保卡號中為空的行轉換日期過程中不符合日期格式的數值會被轉換為空值,這裡刪除列(銷售時間,社保卡號)中為空的行salesDf=salesDf.dropna(subset=[銷售時間,社保卡號],how=any)In [27]:#3.5 數據排序print(排序前的數據集)salesDf.head()排序前的數據集Out[27]:銷售時間 社保卡號 商品編碼 商品名稱 銷售數量 應收金額 實收金額0 2018-01-01 001616528 236701 強力VC銀翹片 6 82.8 691 2018-01-02 001616528 236701 清熱解毒口服液 1 28 24.642 2018-01-06 0012602828 236701 感康 2 16.8 153 2018-01-11 0010070343428 236701 三九感冒靈 1 28 284 2018-01-15 00101554328 236701 三九感冒靈 8 224 208In [28]:by:按哪幾列排序ascending=True 表示升序排列,ascending=False表示降序排列#按銷售日期進行升序排列salesDf=salesDf.sort_values(by=銷售時間, ascending=True)In [29]:print(排序後的數據集)salesDf.head(3)排序後的數據集Out[29]:銷售時間 社保卡號 商品編碼 商品名稱 銷售數量 應收金額 實收金額0 2018-01-01 001616528 236701 強力VC銀翹片 6 82.8 696230 2018-01-01 0010015658428 861405 苯磺酸氨氯地平片(絡活喜) 2 69 62264 2018-01-01 00101470528 236709 心痛定 4 179.2 159.2In [33]:#重命名行名(index):排序後的列索引值是之前的行號,需要修改成從0到N按順序的索引值salesDf=salesDf.reset_index(drop=True)salesDf.head()Out[33]:銷售時間 社保卡號 商品編碼 商品名稱 銷售數量 應收金額 實收金額0 2018-01-01 001616528 236701 強力VC銀翹片 6 82.8 691 2018-01-01 0010015658428 861405 苯磺酸氨氯地平片(絡活喜) 2 69 622 2018-01-01 00101470528 236709 心痛定 4 179.2 159.23 2018-01-01 0013169628 861462 珍菊降壓片 1 9.5 8.54 2018-01-01 0010072612028 2367011 開博通 1 28 25In [34]:#3.6 異常值處理 #描述指標:查看出「銷售數量」值不能小於0salesDf.head()Out[34]:銷售時間 社保卡號 商品編碼 商品名稱 銷售數量 應收金額 實收金額0 2018-01-01 001616528 236701 強力VC銀翹片 6 82.8 691 2018-01-01 0010015658428 861405 苯磺酸氨氯地平片(絡活喜) 2 69 622 2018-01-01 00101470528 236709 心痛定 4 179.2 159.23 2018-01-01 0013169628 861462 珍菊降壓片 1 9.5 8.54 2018-01-01 0010072612028 2367011 開博通 1 28 25In [35]:#刪除異常值:通過條件判斷篩選出數據#查詢條件querySer=salesDf.loc[:,銷售數量]>0#應用查詢條件print(刪除異常值前:,salesDf.shape)salesDf=salesDf.loc[querySer,:]print(刪除異常值後:,salesDf.shape)刪除異常值前 (6575, 7)刪除異常值後 (6532, 7)4.構建模型業務指標1:月均消費次數=總消費次數 / 月份數In [50]:總消費次數:同一天內,同一個人發生的所有消費算作一次消費#根據列名(銷售時間,社區卡號),如果這兩個列值同時相同,只保留1條,將重複的數據刪除kpi1_Df=salesDf.drop_duplicates( subset=[銷售時間, 社保卡號])#總消費次數:有多少行totalI=kpi1_Df.shape[0]print(總消費次數=,totalI)總消費次數= 5342In [51]:計算月份數:時間範圍#第1步:按銷售時間升序排序kpi1_Df=kpi1_Df.sort_values(by=銷售時間, ascending=True)#重命名行名(index)kpi1_Df=kpi1_Df.reset_index(drop=True)In [52]:kpi1_Df.head()Out[52]:銷售時間 社保卡號 商品編碼 商品名稱 銷售數量 應收金額 實收金額0 2018-01-01 001616528 236701 強力VC銀翹片 6.0 82.8 69.01 2018-01-01 0012697828 861464 復方利血平片(復方降壓片) 4.0 10.0 9.42 2018-01-01 0010060654328 861458 復方利血平氨苯蝶啶片(北京降壓0號) 1.0 10.3 9.23 2018-01-01 0011811728 861456 酒石酸美托洛爾片(倍他樂克) 1.0 7.0 6.34 2018-01-01 0013448228 861507 苯磺酸氨氯地平片(安內真) 1.0 9.5 8.5In [54]:#第2步:獲取時間範圍#最小時間值startTime=kpi1_Df.loc[0,銷售時間]#最大時間值endTime=kpi1_Df.loc[totalI-1,銷售時間]#第3步:計算月份數#天數daysI=(endTime-startTime).days#月份數: 運算符「//」表示取整除 #返回商的整數部分,例如9//2 輸出結果是4monthsI=daysI//30print(月份數:,monthsI)月份數 6In [55]:#業務指標1:月均消費次數=總消費次數 / 月份數kpi1_I=totalI // monthsIprint(業務指標1:月均消費次數=,kpi1_I)業務指標1月均消費次數= 890指標2月均消費金額 = 總消費金額 / 月份數In [56]:#總消費金額totalMoneyF=salesDf.loc[:,實收金額].sum()#月均消費金額monthMoneyF=totalMoneyF / monthsIprint(業務指標2:月均消費金額=,monthMoneyF)業務指標2月均消費金額= 50668.351666666305指標3客單價=總消費金額 / 總消費次數客單價per customer transaction是指商場超市每一個顧客平均購買商品的金額客單價也即是平均交易金額In [57]:totalMoneyF:總消費金額totalI:總消費次數pct=totalMoneyF / totalIprint(客單價:,pct)客單價 56.9094178210404指標4消費趨勢畫圖折線圖In [ ]:指標4的計算需要用到pandas的高級功能pandas更多高級功能以及繪圖等更多高級數據分析功能,在之後的課程《分組計算和數據可視化》中詳細介紹微信公眾號:猴子聊人物,中回復「數據分析」加入社群系統學習數據分析,一起用知識改變命運,給家人帶來題目的生活In [58]:#在進行操作之前,先把數據複製到另一個數據框中,防止對之前清洗後的數據框造成影響groupDf=salesDf#第1步:重命名行名(index)為銷售時間所在列的值groupDf.index=groupDf[銷售時間]groupDf.head()Out[58]:銷售時間 社保卡號 商品編碼 商品名稱 銷售數量 應收金額 實收金額銷售時間 2018-01-01 2018-01-01 001616528 236701 強力VC銀翹片 6.0 82.8 69.02018-01-01 2018-01-01 0010616728 865099 硝苯地平片(心痛定) 2.0 3.4 3.02018-01-01 2018-01-01 0010073966328 861409 非洛地平緩釋片(波依定) 5.0 162.5 145.02018-01-01 2018-01-01 0010073966328 866634 硝苯地平控釋片(欣然) 6.0 111.0 92.52018-01-01 2018-01-01 0010014289328 866851 纈沙坦分散片(易達樂) 1.0 26.0 23.0In [59]:#第2步:分組gb=groupDf.groupby(groupDf.index.month)In [60]:gbOut[60]:<pandas.core.groupby.DataFrameGroupBy object at 0x000000000A1DA438>In [61]:#第3步:應用函數,計算每個月的消費總額mounthDf=gb.sum()In [62]:mounthDfOut[62]:銷售數量 應收金額 實收金額銷售時間 1 2527.0 53561.6 49461.192 1858.0 42028.8 38790.383 2225.0 45318.0 41597.514 3005.0 54296.3 48787.845 2225.0 51263.4 46925.276 2328.0 52300.8 48327.707 1483.0 32568.0 30120.22#分析結果的可視化(等後面課程再展示)

分析結果的可視化(等後面課程再展示)

以上是第四關的內容,希望自己再接再厲。


推薦閱讀:

新手該學SQL還是Python?
請問有哪些優秀Python課程推薦?
Pandas數據類型轉換的幾個小技巧
python基礎-split

TAG:數據分析 | Python |