Python數據分析流程(以藥店銷售數據為例)
一、一維數據分析
#導入numpy包和pandas包import numpy as npimport pandas as pd
1.1 numpy一維數據結構:array
#定義一個一維數組,參數傳入的是一個列表a=np.array([2,3,4,5])#查詢:方括弧a[0]#切片訪問:獲取指定序號範圍的元素a[1:3]#查看數據類型a.dtype#描述統計#平均值a.mean()#標準差a.std()
#向量化運行:乘以標量b=np.array([1,2,3])c=b*4
1.2 pandas一維數據結構:Series
#pandas一維數據結構Series:用pd.Series()定義數組,用index()定義索引#存放六家公司某日的股價stockS=pd.Series([54.74,190.9,173.14,1050.3,181.86,1139.49], index=[騰訊, 阿里巴巴, 蘋果, 谷歌, Facebook, 亞馬遜])
stock騰訊 54.74阿里巴巴 190.90蘋果 173.14谷歌 1050.30Facebook 181.86亞馬遜 1139.49dtype: float64
stockS.describe()count 6.000000mean 465.071667std 491.183757min 54.74000025% 175.32000050% 186.38000075% 835.450000max 1139.490000dtype: float64
#iloc屬性用於根據索引獲取值stockS.iloc[0]#loc屬性用於根據索引獲取值stockS.loc[騰訊]#向量化運算:向量相加s1=pd.Series([1,2,3,4],index=[a,b,c,d])s2=pd.Series([10,20,30,40],index=[a,b,e,f])s3=s1+s2
s3a 11.0b 22.0c NaNd NaNe NaNf NaNdtype: float64
#缺失值處理#方法1:刪除缺失值s3.dropna()a 11.0b 22.0dtype: float64
#方法2:將缺失值進行填充s3=s1.add(s2,fill_value=0)s3a 11.0b 22.0c 3.0d 4.0e 30.0f 40.0dtype: float64
二、二維數據分析
2.1 numpy二維數組:array
#用numpy定義二維數組:np.array()a=np.array([ [1,2,3,4], [5,6,7,8], [9,10,11,12]])
#獲取行號是0,列號是2的元素a[0,2]#獲取第一列a[:,0]#獲取第一行a[0,:]
#numpy數軸參數:axis#如果沒有指定數軸參數,會計算整個數組的相應值a.mean()#按軸計算:axis=1按行計算,axis=0按列計算a.mean(axis=1)
array([ 2.5, 6.5, 10.5])
2.2 pandas二維數組:數據框DataFrames
#定義一個字典,映射列名與對應列的值salesDict={ 購葯時間:[2018-01-01 星期五,2018-01-02 星期六,2018-01-06 星期三], 社保卡號:[001616528,001616528,0012602828], 商品編碼:[236701,236701,236701], 商品名稱:[強力VC銀翹片,清熱解毒口服液,感康], 銷售數量:[6,1,2], 應收金額:[82.8,28,16.8], 實收金額:[69,24.64,15]}#導入有序字典from collections import OrderedDict#定義一個有序字典salesOrderDict=OrderedDict(salesDict)#定義數據框:傳入字典、列名salesDf=pd.DataFrame(salesOrderDict)
salesDf#平均值:是按照列來求平均值salesDf.mean()
商品編碼 236701.000000銷售數量 3.000000應收金額 42.533333實收金額 36.213333dtype: float64
2.3 pandas中的數據查詢:根據位置獲取值iloc[],根據索引獲取值loc[]
salesDf.iloc[0,1]
001616528
#獲取第一行所有列的數據salesDf.iloc[0,:]
購葯時間 2018-01-01 星期五社保卡號 001616528商品編碼 236701商品名稱 強力VC銀翹片銷售數量 6應收金額 82.8實收金額 69Name: 0, dtype: object
#獲取第一列所有行的數據salesDf.iloc[:,0]
0 2018-01-01 星期五1 2018-01-02 星期六2 2018-01-06 星期三Name: 購葯時間, dtype: object
#loc[]用於根據索引獲取值#獲取第一行salesDf.loc[0,:]
購葯時間 2018-01-01 星期五社保卡號 001616528商品編碼 236701商品名稱 強力VC銀翹片銷售數量 6應收金額 82.8實收金額 69Name: 0, dtype: object
#獲取第一行第一列的元素salesDf.loc[:,購葯時間]
0 2018-01-01 星期五1 2018-01-02 星期六2 2018-01-06 星期三Name: 購葯時間, dtype: object
#簡單方法:獲取「商品名稱」這一列salesDf[商品名稱]
0 強力VC銀翹片1 清熱解毒口服液2 感康Name: 商品名稱, dtype: object
2.4.1 數據框複雜查詢:切片功能
#通過列表來選擇某幾列數據salesDf[[商品名稱,銷售數量]]

#通過切片功能,獲取指定範圍的salesDf.loc[:,購葯時間:銷售數量]

2.4.2 數據框複雜查詢:條件判斷
#通過條件判斷篩選#第一步:構建查詢條件querySer=salesDf.loc[:,銷售數量]>1type(querySer)
pandas.core.series.Series
querySer0 True1 False2 TrueName: 銷售數量, dtype: bool
2.5 查看數據集描述統計信息
#讀取Excel數據fileNameStr=./朝陽醫院2018年銷售數據.xlsxxls=pd.ExcelFile(fileNameStr)salesDf=xls.parse(Sheet1)#列印前三行salesDf.head(3)

#有多少行,多少列salesDf.shape
#查看每一列的數據類型salesDf.loc[:,銷售數量].dtype
#查看每一列的統計數值salesDf.describe()

三、藥店銷售數據分析
3.1 提出問題
從銷售數據中分析以下業務指標:1)月均消費次數 2)月均消費金額 3)客單價 4)消費趨勢
#讀取Excel數據,統一先按照字元串讀入,之後轉換fileNameStr=./朝陽醫院2018年銷售數據.xlsxxls=pd.ExcelFile(fileNameStr,dtype=object)salesDf=xls.parse(Sheet1,dtype=object)
查看數據基本信息#列印前五行salesDf.head()

salesDf.shape
(6578, 7)
salesDf.dtypes
購葯時間 object社保卡號 object商品編碼 object商品名稱 object銷售數量 object應收金額 object實收金額 objectdtype: object
3.2 數據清洗
1)選擇子集
如:subSalesDf=salesDf.loc[0:4,購葯時間:銷售數量]
2) 列名重命名
#字典:舊列名和新列名對應關係colNameDict={購葯時間:銷售時間}inplace=False,數據框本身不會變,而會創建一個改動後新的數據框,默認的inplace是Falseinplace=True,數據框本身會改動salesDf.rename(columns=colNameDict)

salesDf.rename(columns=colNameDict,inplace=True)salesDf.head()

3.3 缺失值處理
print(刪除缺失值前大小,salesDf.shape)
刪除缺失值前大小 (6578, 7)
#刪除列(銷售時間,社保卡號)中為空的行#how=any 在給定的任何一列中有缺失值就刪除salesDf=salesDf.dropna(subset=[銷售時間,社保卡號],how=any)
print(刪除缺失後大小,salesDf.shape)
刪除缺失後大小 (6575, 7)
3.4 數據類型轉換
#字元串轉換為數值(浮點型)salesDf[銷售數量] = salesDf[銷售數量].astype(float)salesDf[應收金額] = salesDf[應收金額].astype(float)salesDf[實收金額] = salesDf[實收金額].astype(float)print(轉換後的數據類型:
,salesDf.dtypes)
轉換後的數據類型: 銷售時間 object社保卡號 object商品編碼 object商品名稱 object銷售數量 float64應收金額 float64實收金額 float64dtype: object
#測試:字元串分割testList=2018-06-03 星期五.split( )
testList
[2018-06-03, 星期五]
testList[0]
2018-06-03
定義函數:分割銷售日期,獲取銷售時間輸入:timeColSer 銷售時間這一列是Series數據類型輸出:分割後的時間,返回也是Series數據類型def SplitSaletime(timeColSer): timeList=[] for value in timeColSer: #分割後取第一個元素(年月日) dateStr=value.split( )[0] timeList.append(dateStr) #將列錶轉行為一維數據Series類型 timeSer=pd.Series(timeList) return timeSer
#獲取「銷售時間」這一列timeSer=salesDf.loc[:,銷售時間]#對字元串進行分割,獲取銷售時間dateSer=SplitSaletime(timeSer)
是因為Excel中的空的cell讀入pandas中是空值(NaN),這個NaN是個浮點類型,一般當作空值處理。所以要先去除NaN再進行分隔字元串#None和NaN的區別print(None的數據類型,type(None))from numpy import NaNprint(NaN的數據類型,type(NaN))
None的數據類型 <class NoneType>NaN的數據類型 <class float>
dateSer[0:3]
0 2018-01-011 2018-01-022 2018-01-06dtype: object
#修改銷售時間這一列的值salesDf.loc[:,銷售時間]=dateSersalesDf.head()

數據類型轉換:字元串轉換為日期#errors=coerce 如果原始數據不符合日期的格式,轉換後的值為空值#format 是原始數據中日期的格式salesDf.loc[:,銷售時間]=pd.to_datetime(salesDf.loc[:,銷售時間], format=%Y-%m-%d, errors=coerce)
salesDf.dtypes
銷售時間 datetime64[ns]社保卡號 object商品編碼 object商品名稱 object銷售數量 float64應收金額 float64實收金額 float64dtype: object
轉換日期過程中不符合日期格式的數值會被轉換為空值,這裡刪除列(銷售時間,社保卡號)中為空的行salesDf=salesDf.dropna(subset=[銷售時間,社保卡號],how=any)
3.5 數據排序
print(排序前的數據集)salesDf.head()

#按銷售日期進行升序排列salesDf=salesDf.sort_values(by=銷售時間, ascending=True)print(排序後的數據集)salesDf.head(3)

#重命名行名(index):排序後的列索引值是之前的行號,需要修改為從0到N的索引值salesDf=salesDf.reset_index(drop=True)salesDf.head()

3.6 異常值處理
#描述指標:查看出「銷售數量」值不能小於0salesDf.describe()

#刪除異常值:通過條件判斷篩選出數據#查詢條件querySer=salesDf.loc[:,銷售數量]>0#應用查詢條件print(刪除異常值前:,salesDf.shape)salesDf=salesDf.loc[querySer,:]print(刪除異常值後:,salesDf.shape)
刪除異常值前: (6549, 7)刪除異常值後: (6506, 7)
四、構建模型
4.1 業務指標1:月均消費次數=總消費次數/月份數
總消費次數:同一天內,同一個人發生的所有消費算作一次消費#根據列名(銷售時間,社區卡號),如果這兩個列值同時相同,只保留1條,將重複的數據刪除kpil_Df=salesDf.drop_duplicates( subset=[銷售時間,社保卡號]) #總消費次數:有多少行totalI=kpi1_Df.shape[0]print(總消費次數=,totalI)
總消費次數= 5342
計算月份數:時間範圍#第1步:按銷售時間升序排序kpi1_Df=kpi1_Df.sort_values(by=銷售時間, ascending=True)#重命名行名(index)kpi1_Df=kpi1_Df.reset_index(drop=True)
kpil_Df.head()

#第二步:獲取時間範圍#最小時間值startTime=kpil_Df.loc[0,銷售時間]#最大時間值endTime=kpil_Df.loc[totalI-1,銷售時間]#第三步:計算月份數#天數daysI=(endTime-startTime).days#月分數:運算符「//」表示取整monthsI=daysI//30print(月份數:,monthsI)
月份數: 5
#業務指標1:月均消費次數=總消費次數/月份數kpil_I=totalI//monthsIprint(業務指標1:月均消費次數=,kpil_I)
業務指標1:月均消費次數= 1068
4.2 指標2:月均消費金額= 總消費金額/月份數
#總消費金額totalMoneyF=salesDf.loc[:,實收金額].sum()#月均消費金額monthMoneyF=totalMoneyF/monthsIprint(業務指標2:月均消費金額=,monthMoneyF)
業務指標2:月均消費金額= 60802.022
4.3 指標3:客單價=總消費金額/總消費次數
客單價(per customer transaction)也即是平均交易金額
pct=totalMoneyF/totalIprint(業務指標3:客單價=,pct)
業務指標3:客單價= 56.909417821040805
推薦閱讀:
※Python 數據分析(五):數據的處理
※推薦相關梳理
※用數據挖一挖豆瓣5.3的《長城》,水軍力量到底有多強大
※《Python數據挖掘》筆記(七) 自動化文本摘要
※介紹一位可能過時的咖狗神器XGBoost
