數(shù)據(jù)分析的步驟:提出問題→理解數(shù)據(jù)→數(shù)據(jù)清洗→構建模型→數(shù)據(jù)可視化
目標數(shù)據(jù):2018年朝陽醫(yī)院銷售數(shù)據(jù).xlsx
業(yè)務部門下發(fā)了一項業(yè)務分析目標赶站,把數(shù)據(jù)發(fā)給我的時候就在思考該怎么分析狡蝶,接下來一起探討怎么進行簡單的數(shù)據(jù)分析
一域仇、提出業(yè)務指標問題
從銷售數(shù)據(jù)中分析下面的業(yè)務指標問題:
(1)月均消費次數(shù)
(2)月均消費金額
(3)客單價
(4)消費趨勢
導入所需要的包
import matplotlib.pyplot as plt
from pandas import Series,DataFrame
import pandas as pd
import numpy as np
將銷售Ecxcel數(shù)據(jù)導入到python中
fileNameStr='E:\\2018python\朝陽醫(yī)院2018年銷售數(shù)據(jù).xlsx'
xls=pd.ExcelFile(fileNameStr,dtype='object')
salesDf = xls.parse('Sheet1',dtype='object')
查看前五行數(shù)據(jù)
salesDf.head()
查看表格數(shù)據(jù)的行數(shù)和列數(shù)
salesDf.shape
(6578, 7)
可以查看到數(shù)據(jù)有6578行嵌削,7列。
查看列的數(shù)據(jù)類型
salesDf.dtypes
購藥時間 object
社迸璧ⅲ卡號 object
商品編碼 object
商品名稱 object
銷售數(shù)量 object
應收金額 object
實收金額 object
dtype: object
二轰绵、數(shù)據(jù)清洗(數(shù)據(jù)預處理)
數(shù)據(jù)預處理主要有以下步驟:
(1)選擇子集
(2)列名重命名
(3)刪除缺失數(shù)據(jù)
(4)數(shù)據(jù)類型轉換
(5)數(shù)據(jù)排序
(6)異常值處理
1.選擇子集
本案例子集不用選擇子集,需要的子集已經存在
2.列名重命名
salesDf.rename(columns ={'購藥時間':'銷售時間'},inplace=True) #inplace=True昌执,數(shù)據(jù)框本身會改動
salesDf.head()
3. 刪除缺失數(shù)據(jù)
刪除列(銷售時間烛亦,社保卡號)中為空的行懂拾,使用dropna刪除缺失數(shù)據(jù)
print('刪除缺失值前大小',salesDf.shape)
#how='any' 給定的任何一列中有缺失值就刪除
salesDf=salesDf.dropna(subset=['銷售時間','社泵呵荩卡號'],how='any')
print('刪除缺失后大小',salesDf.shape)
刪除缺失值前大小 (6578, 7)
刪除缺失后大小 (6575, 7)
在刪除缺失數(shù)據(jù)之前有6578行,刪除缺失的數(shù)據(jù)之后是6575行
4. 數(shù)據(jù)類型轉換
將字符串轉換為浮點型數(shù)值
salesDf['銷售數(shù)量']=salesDf['銷售數(shù)量'].astype('float')
salesDf['應收金額']=salesDf['應收金額'].astype('float')
salesDf['實收金額']=salesDf['實收金額'].astype('float')
print('轉換后的數(shù)據(jù)類型:\n',salesDf.dtypes)
轉換后的數(shù)據(jù)類型:
銷售時間 object
社贬常卡號 object
商品編碼 object
商品名稱 object
銷售數(shù)量 float64
應收金額 float64
實收金額 float64
dtype: object
日期列字符串轉換為日期數(shù)據(jù)類型
#測試:字符串分割
testList='2018-06-03 星期五'.split(' ')
testList
['2018-06-03', '星期五']
testList[0]
'2018-06-03'
分割時間列檬果,定義函數(shù):分割銷售日期,獲取銷售日期
def splitSaletime(timeColSer):
timeList=[]
for value in timeColSer:
#例如2018-01-01 星期五唐断,分割后為:2018-01-01
dateStr=value.split(' ')[0]
timeList.append(dateStr)
timeSer=pd.Series(timeList)
return timeSer
獲取“銷售時間”這一列选脊,對字符串進行分割,獲取銷售日期
timeSer=salesDf.loc[:,'銷售時間']
dateSer=splitSaletime(timeSer)
修改銷售時間這一列的值
dateSer[0:3]
0 2018-01-01
1 2018-01-02
2 2018-01-06
dtype: object
獲取分割之后的銷售日期脸甘,少了星期時間字符
salesDf.loc[:,'銷售時間']=dateSer
salesDf.head()
數(shù)據(jù)類型轉換:字符串轉換為日期
salesDf.loc[:,'銷售時間']=pd.to_datetime(salesDf.loc[:,'銷售時間'],
format='%Y-%m-%d', errors='coerce')
salesDf.dtypes
銷售時間 datetime64[ns]
社笨疑叮卡號 object
商品編碼 object
商品名稱 object
銷售數(shù)量 float64
應收金額 float64
實收金額 float64
dtype: object
轉換日期過程中不符合日期格式的數(shù)值會被轉換為空值,
這里刪除列(銷售時間丹诀,社倍鄣模卡號)中為空的行
salesDf=salesDf.dropna(subset=['銷售時間','社保卡號'],how='any')
5. 數(shù)據(jù)排序
使用sort_values進行排序铆遭,by:按哪幾列排序硝桩,ascending=True 表示升序排列,ascending=False表示降序排列
#按銷售時間進行升序排列
salesDf=salesDf.sort_values(by='銷售時間',ascending=True)
#查看排序后的前10行
salesDf.head(10)
重命名行名(index)枚荣,使用reset_index修改成從0到N按順序排序的索引值index
salesDf=salesDf.reset_index(drop=True)
salesDf.head(6)
6. 異常值處理
查看匯總數(shù)據(jù)描述碗脊,其中銷售數(shù)量值不能小于0
salesDf.describe()
通過條件判斷來刪除異常值
querySer=salesDf.loc[:,'銷售數(shù)量']>0
print('刪除異常值前:',salesDf.shape)
salesDf=salesDf.loc[querySer,:]
print('刪除異常值后:',salesDf.shape)
刪除異常值前: (6549, 7)
刪除異常值后: (6506, 7)
數(shù)據(jù)的預處理工作完成,接下來分析業(yè)務的各個指標
三棍弄、構建模型
1.月均消費次數(shù)
業(yè)務指標1:月均消費次數(shù)=總消費次數(shù) / 月份數(shù)
在計算總的消費次數(shù)當中將每個人每天的不同消費記錄作為消費一次,用drop_duplicates去掉同一天同一個人的重復消費記錄
根據(jù)列名(銷售時間望薄,社區(qū)卡號),如果這兩個列值同時相同呼畸,只保留1條痕支,將重復的數(shù)據(jù)刪除
kpi1_Df=salesDf.drop_duplicates(subset=['銷售時間', '社保卡號'])
#總消費次數(shù)
totalI=kpi1_Df.shape[0]
print('總消費次數(shù)=',totalI)
總消費次數(shù)= 5342
計算月份數(shù)
#按銷售時間升序排序
kpi1_Df=kpi1_Df.sort_values(by='銷售時間',ascending=True)
#重命名行名,索引排序
kpi1_Df=kpi1_Df.reset_index(drop=True)
kpi1_Df.head()
計算總月份數(shù)蛮原,第一行時間與結尾時間之差除以30取整
startTime=kpi1_Df.loc[0,'銷售時間']
#最大時間值
endTime=kpi1_Df.loc[totalI-1,'銷售時間']
#天數(shù)
daysI=(endTime-startTime).days
#月份數(shù): 運算符“//”表示取整除
#返回商的整數(shù)部分卧须,例如9//2 輸出結果是4
monthsI=daysI//30
print('月份數(shù):',monthsI)
月份數(shù): 6
2.月均消費次數(shù)
業(yè)務指標2:月均消費次數(shù)=總消費次數(shù) / 月份數(shù)
計算月均消費次數(shù)
kpi1_I=totalI // monthsI
print('業(yè)務指標2:月均消費次數(shù)=',kpi1_I)
業(yè)務指標2:月均消費次數(shù)= 890
3.月均消費金額
指標3:月均消費金額 = 總消費金額 / 月份數(shù)
#總消費金額
totalMoneyF=salesDf.loc[:,'實收金額'].sum()
#月均消費金額
monthMoneyF=totalMoneyF / monthsI
print('業(yè)務指標3:月均消費金額=',monthMoneyF)
業(yè)務指標3:月均消費金額= 50668.35166666666
4.客單價
指標4:客單價=總消費金額 / 總消費次數(shù)
客單價(per customer transaction)是指商場(超市)每一個顧客平均購買商品的金額,客單價也即是平均交易金額。
'''
totalMoneyF:總消費金額
totalI:總消費次數(shù)
'''
pct=totalMoneyF / totalI
print('客單價:',pct)
客單價: 56.909417821040805
5.消費趨勢圖
指標5:消費趨勢畫圖
#在進行操作之前花嘶,先把數(shù)據(jù)復制到另一個數(shù)據(jù)框中笋籽,防止對之前清洗后的數(shù)據(jù)框造成影響
groupDf=salesDf
#第1步:重命名行名(index)為銷售時間所在列的值
groupDf.index=groupDf['銷售時間']
groupDf.head()
分組
gb=groupDf.groupby(groupDf.index.month)
gb
<pandas.core.groupby.DataFrameGroupBy object at 0x000000000ED4CC18>
#第3步:應用函數(shù),計算每個月的消費總額
mounthDf=gb.sum()
mounthDf
選取每個月的應收金額和實收金額的消費總額
mounthDf=DataFrame(mounthDf,columns=['應收金額','實收金額'])
mounthDf
6.數(shù)據(jù)可視化
from pylab import *
mpl.rcParams['font.sans-serif'] = ['SimHei'] #防止中文亂碼
mounthDf.plot(title='2018年朝陽醫(yī)院數(shù)據(jù)消費金額趨勢圖',figsize=(15,8),fontsize=20)
以上可以看出第1月和第七月消費總金額是最高的车海,在第七月消費金額最低。
醫(yī)藥銷售量和天氣變化有一定的影響侍芝,尤其在冬季天氣寒冷和初春季節(jié),容易受到天氣影響州叠,氣溫變化大,市民容易感冒凶赁,從而在醫(yī)藥行業(yè)銷售更多了醫(yī)藥,銷售量上升虱肄,在氣溫平穩(wěn)時期銷售量下降。
總之浩峡,醫(yī)藥銷售金額會受到當?shù)靥鞖夂铜h(huán)境等因素的影響错敢。
dropna函數(shù)詳細使用地址:https://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.dropna.html
本次練習學習基本知識翰灾,了解到簡單的數(shù)據(jù)分析過程。