以某醫(yī)院銷售數(shù)據(jù)為例
一 提出問題
當(dāng)面對一個csv或者excel文件的時候,第一步是用python打開文件然后進(jìn)行隨便分析嗎?不是這樣的,任何的數(shù)據(jù)分析都是需要有一個過程的,首先要明白這次數(shù)據(jù)分析的目的是什么,數(shù)據(jù)分析只是手段,只是工具而已,能不能解決所要分析的問題,能不能從數(shù)據(jù)中發(fā)現(xiàn)問題,發(fā)現(xiàn)商機(jī),才是重點(diǎn)。
再重復(fù)一遍,分析之前一定要明白這次分析是為了什么。
目前有一份朝陽醫(yī)院2018年的銷售數(shù)據(jù),當(dāng)看到這個數(shù)據(jù)的時候,我們不能隨便分析,能得到什么結(jié)果算什么結(jié)果,首先要有一個分析的目標(biāo),就是我們要從數(shù)據(jù)中發(fā)現(xiàn)什么,針對這個數(shù)據(jù),我們想要知道
月均消費(fèi)次數(shù)
月均消費(fèi)金額
客單價(jià)
消費(fèi)趨勢
當(dāng)明白我們想要分析的問題的時候,就可以進(jìn)行下一步了。
二 理解數(shù)據(jù)
理解數(shù)據(jù)是為了數(shù)據(jù)清洗做準(zhǔn)備的,在數(shù)據(jù)清洗之前,首先肯定要對數(shù)據(jù)有一個了解,了解數(shù)據(jù)是什么類型的,有多少數(shù)據(jù)什么的。
# 首先加載數(shù)據(jù)分析常用庫
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
#% matplotlib inline
import pandas as pd
import matplotlib.pyplot as plt
#然后讀取文件,在讀取文件前,需要安裝xlrd包,
sales= pd.read_excel('../input/chaoyangyiyuan9062/朝陽醫(yī)院2018年銷售數(shù)據(jù).xlsx')
#看看數(shù)據(jù)情況
sales.info()
再看一下數(shù)據(jù)具體長什么樣
sales.head()
三 數(shù)據(jù)清洗
1 選擇子集
在我們獲取到的數(shù)據(jù)中,數(shù)據(jù)量十分龐大,但是不是每一列都是我們所需要分析的呢,不一定,那么這個時候就要選擇整個數(shù)據(jù)中合適的子集去進(jìn)行分析,這樣可以使后續(xù)的分析變得更加方便,在本次案例中,不需要選擇子集,所以可以先跳過這一步。
2 列名重命名
在數(shù)據(jù)的獲取中,有時候會有一些列名和數(shù)據(jù)不那么符合,或者容易產(chǎn)生歧義,一不小心就理解錯了,很不利于分析,在這個時候,就需要給列名重命名。代碼如下
#把購藥時間改成銷售時間比較有利于理解,inplace=True,直接在原數(shù)據(jù)框內(nèi)改動
sales.rename(columns = {'購藥時間':'銷售時間'}, inplace = True)
#看一下有沒有被改動
sales.head()
3 缺失數(shù)據(jù)處理
任何一個得到的數(shù)據(jù)都很有可能會有缺失值,那么對于這些缺失值一定需要處理一下,不然會干擾后來的分析結(jié)果。刪除缺失值用dropna函數(shù),代碼如下
#沒有時間和社??ㄌ柕南M(fèi)數(shù)據(jù)對于本次分析是無效的,
#所以清理一下缺失值
sales = sales.dropna(subset = [ '銷售時間','社??ㄌ?],how = 'any')
4 數(shù)據(jù)類型處理
在導(dǎo)入的時候?yàn)榱朔乐褂行?shù)據(jù)導(dǎo)入不進(jìn)來,所以強(qiáng)制所有數(shù)據(jù)都是object類型,但在實(shí)際分析上這樣是不可能的,所以要把需要改變類型的數(shù)據(jù)類型改變了,通過觀察,我們發(fā)現(xiàn),銷售數(shù)量,應(yīng)收金額,實(shí)收金額,應(yīng)該改成float類型,銷售時間應(yīng)該清理后改成時間類型,對于改變成float類型的幾列,使用astype函數(shù),代碼如下。
sales['銷售數(shù)量'] = sales['銷售數(shù)量'].astype('float')
sales['應(yīng)收金額'] = sales['應(yīng)收金額'].astype('float')
sales['實(shí)收金額'] = sales['實(shí)收金額'].astype('float')
而銷售時間那一列,則需要進(jìn)行處理后才能轉(zhuǎn)換為時間類型,把銷售時間的日期和星期分開
sales['銷售時間'], sales['銷售星期'] = sales['銷售時間'].str.split(' ', 1).str
切分好之后,把銷售時間變?yōu)闀r間類型,代碼如下
sales['銷售時間'] = pd.to_datetime(sales['銷售時間'],
format = '%Y-%m-%d',errors = 'coerce')
5 排序
但是在這個時候時間是無序排列的,所以還是需要排序一下,排序之后索引會被打亂,所以也需要重置一下索引。代碼如下
#對數(shù)據(jù)按照時間排序
sales = sales.sort_values('銷售時間', ascending = True)
#排序之后再重置一下index
sales = sales.reset_index(drop = True)
sales.head()
6 異常值處理
在排序結(jié)束之后簡單看一下數(shù)據(jù)的整體情況
sales.describe()
從數(shù)據(jù)基本情況可以看出,銷售數(shù)量和應(yīng)收金額,實(shí)收金額,都有負(fù)的異常值,需要把這些值舍去,即選取銷售數(shù)量和應(yīng)收金額大于0的列,代碼如下
#選取銷售數(shù)量和應(yīng)收金額大于0的列
sales = sales[(sales['銷售數(shù)量'] > 0) & (sales['應(yīng)收金額'] > 0)]
四 數(shù)據(jù)分析
1 月均消費(fèi)次數(shù)
這里的月均消費(fèi)次數(shù)定義為總次數(shù)除以月份,其中假如一個人一天買了兩次藥,但只算做消費(fèi)了一次,即計(jì)算次數(shù)的時候需要進(jìn)行去重處理。
#首先對數(shù)據(jù)進(jìn)行一個去重,使用drop_duplicates函數(shù)
salesqc = sales.drop_duplicates(subset = ['銷售時間', '社??ㄌ?])
#去重后看一下共有多少條購買數(shù)據(jù)(結(jié)果為5363)
Total = salesqc.shape[0]
#再計(jì)算月份
#用銷售時間的最大值減去最小值即可得到天數(shù),再除以(地板除)三十就可以得到月份了
month = (sales['銷售時間'].max() - sales['銷售時間'].min()).days//30
KPI1 = Total / month
print('月均消費(fèi)次數(shù)為:', KPI1)
2 月均消費(fèi)金額
同樣,月均消費(fèi)金額為總金額除以月份,在計(jì)算總金額的時候不能去重,需要都計(jì)算上金額。
#計(jì)算總金額
Total1 = sales['實(shí)收金額'].sum()
KPI2 = Total1 / month
print('月均消費(fèi)金額為:', KPI2)
3 客單價(jià)
客單價(jià)就是總的消費(fèi)金額除以總的購買次數(shù)。
kdj = Total1 / Total
print('客單價(jià)為:', kdj)
4 消費(fèi)趨勢
關(guān)于消費(fèi)趨勢,首先我們先來看一下每天的消費(fèi)總金額的變化,把數(shù)據(jù)按天聚合,繪圖,代碼如下。
##對去重后的數(shù)據(jù)按照天進(jìn)行重新采樣
#首先要把索引變成時間
sales.index = pd.DatetimeIndex(sales['銷售時間'])
#然后對其按照每天從新采樣
salesd = sales.resample('D').count()
#畫圖
salesd.plot(x = salesd.index, y = '實(shí)收金額')
plt.xlabel('Time')
plt.ylabel('Money')
plt.title('xiao shou shu ju')
plt.show()
可以看出每天消費(fèi)總額有高有低,其中出現(xiàn)幾個峰值消費(fèi)數(shù)據(jù)特別高,下面按月采樣看一下每個月的總銷售額是否有很大的差異。
#按月采樣
salesm = sales.resample('M').count()
#畫圖
salesm.plot(x = salesm.index, y = '實(shí)收金額')
plt.xlabel('Time')
plt.ylabel('People')
plt.title('ke liu liang (month)')
plt.show()
由圖我們其實(shí)可以看出,該藥店的銷售總額和客流量基本成正比。二月份的客流量最少,同樣銷售業(yè)績也最差,同樣的四月份客流量最高,銷售總額也最多。
但是六月份客流量變少了,而消費(fèi)總額卻變多了,可能是因?yàn)槿司I的藥更貴了,具體原因尚且不得而知,七月份的數(shù)據(jù)如此小的原因是因?yàn)槠咴路葜唤y(tǒng)計(jì)了半個月的數(shù)據(jù),數(shù)據(jù)不全,不能拿來做比較。
將銷售數(shù)據(jù)按星期分組,得到如下結(jié)果。
sales.groupby('銷售星期')['實(shí)收金額'].sum()
通過這里,我們可以發(fā)現(xiàn),周五周六的銷售總額要顯著的的高于其他日期,即周五周六應(yīng)該前來買藥的人更多,銷售的藥品更多。
即每周的銷售趨勢是周日到周四銷售總額會有波動,但是幅度不大,周五周六的銷售總額相對較高,按月份比較的話,四月份的銷售總額顯著的高,而二月份的銷售總額顯著的低,猜測銷售總額非常低是因?yàn)榇汗?jié)的緣故。
大概的數(shù)據(jù)分析過程就是這樣了~
數(shù)據(jù)集鏈接如下:
鏈接:https://pan.baidu.com/s/12nkhZJlwZe7FaAqZakDHLQ
提取碼:5ft9