以某医院销售数据为例
一 提出问题
当面对一个csv或者excel文件的时候,第一步是用python打开文件然后进行随便分析吗?不是这样的,任何的数据分析都是需要有一个过程的,首先要明白这次数据分析的目的是什么,数据分析只是手段,只是工具而已,能不能解决所要分析的问题,能不能从数据中发现问题,发现商机,才是重点。
再重复一遍,分析之前一定要明白这次分析是为了什么。
目前有一份朝阳医院2018年的销售数据,当看到这个数据的时候,我们不能随便分析,能得到什么结果算什么结果,首先要有一个分析的目标,就是我们要从数据中发现什么,针对这个数据,我们想要知道
月均消费次数
月均消费金额
客单价
消费趋势
当明白我们想要分析的问题的时候,就可以进行下一步了。
二 理解数据
理解数据是为了数据清洗做准备的,在数据清洗之前,首先肯定要对数据有一个了解,了解数据是什么类型的,有多少数据什么的。
# 首先加载数据分析常用库
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/朝阳医院2018年销售数据.xlsx')
#看看数据情况
sales.info()
再看一下数据具体长什么样
sales.head()
三 数据清洗
1 选择子集
在我们获取到的数据中,数据量十分庞大,但是不是每一列都是我们所需要分析的呢,不一定,那么这个时候就要选择整个数据中合适的子集去进行分析,这样可以使后续的分析变得更加方便,在本次案例中,不需要选择子集,所以可以先跳过这一步。
2 列名重命名
在数据的获取中,有时候会有一些列名和数据不那么符合,或者容易产生歧义,一不小心就理解错了,很不利于分析,在这个时候,就需要给列名重命名。代码如下
#把购药时间改成销售时间比较有利于理解,inplace=True,直接在原数据框内改动
sales.rename(columns = {'购药时间':'销售时间'}, inplace = True)
#看一下有没有被改动
sales.head()
3 缺失数据处理
任何一个得到的数据都很有可能会有缺失值,那么对于这些缺失值一定需要处理一下,不然会干扰后来的分析结果。删除缺失值用dropna函数,代码如下
#没有时间和社保卡号的消费数据对于本次分析是无效的,
#所以清理一下缺失值
sales = sales.dropna(subset = [ '销售时间','社保卡号'],how = 'any')
4 数据类型处理
在导入的时候为了防止有些数据导入不进来,所以强制所有数据都是object类型,但在实际分析上这样是不可能的,所以要把需要改变类型的数据类型改变了,通过观察,我们发现,销售数量,应收金额,实收金额,应该改成float类型,销售时间应该清理后改成时间类型,对于改变成float类型的几列,使用astype函数,代码如下。
sales['销售数量'] = sales['销售数量'].astype('float')
sales['应收金额'] = sales['应收金额'].astype('float')
sales['实收金额'] = sales['实收金额'].astype('float')
而销售时间那一列,则需要进行处理后才能转换为时间类型,把销售时间的日期和星期分开
sales['销售时间'], sales['销售星期'] = sales['销售时间'].str.split(' ', 1).str
切分好之后,把销售时间变为时间类型,代码如下
sales['销售时间'] = pd.to_datetime(sales['销售时间'],
format = '%Y-%m-%d',errors = 'coerce')
5 排序
但是在这个时候时间是无序排列的,所以还是需要排序一下,排序之后索引会被打乱,所以也需要重置一下索引。代码如下
#对数据按照时间排序
sales = sales.sort_values('销售时间', ascending = True)
#排序之后再重置一下index
sales = sales.reset_index(drop = True)
sales.head()
6 异常值处理
在排序结束之后简单看一下数据的整体情况
sales.describe()
从数据基本情况可以看出,销售数量和应收金额,实收金额,都有负的异常值,需要把这些值舍去,即选取销售数量和应收金额大于0的列,代码如下
#选取销售数量和应收金额大于0的列
sales = sales[(sales['销售数量'] > 0) & (sales['应收金额'] > 0)]
四 数据分析
1 月均消费次数
这里的月均消费次数定义为总次数除以月份,其中假如一个人一天买了两次药,但只算做消费了一次,即计算次数的时候需要进行去重处理。
#首先对数据进行一个去重,使用drop_duplicates函数
salesqc = sales.drop_duplicates(subset = ['销售时间', '社保卡号'])
#去重后看一下共有多少条购买数据(结果为5363)
Total = salesqc.shape[0]
#再计算月份
#用销售时间的最大值减去最小值即可得到天数,再除以(地板除)三十就可以得到月份了
month = (sales['销售时间'].max() - sales['销售时间'].min()).days//30
KPI1 = Total / month
print('月均消费次数为:', KPI1)
2 月均消费金额
同样,月均消费金额为总金额除以月份,在计算总金额的时候不能去重,需要都计算上金额。
#计算总金额
Total1 = sales['实收金额'].sum()
KPI2 = Total1 / month
print('月均消费金额为:', KPI2)
3 客单价
客单价就是总的消费金额除以总的购买次数。
kdj = Total1 / Total
print('客单价为:', kdj)
4 消费趋势
关于消费趋势,首先我们先来看一下每天的消费总金额的变化,把数据按天聚合,绘图,代码如下。
##对去重后的数据按照天进行重新采样
#首先要把索引变成时间
sales.index = pd.DatetimeIndex(sales['销售时间'])
#然后对其按照每天从新采样
salesd = sales.resample('D').count()
#画图
salesd.plot(x = salesd.index, y = '实收金额')
plt.xlabel('Time')
plt.ylabel('Money')
plt.title('xiao shou shu ju')
plt.show()
可以看出每天消费总额有高有低,其中出现几个峰值消费数据特别高,下面按月采样看一下每个月的总销售额是否有很大的差异。
#按月采样
salesm = sales.resample('M').count()
#画图
salesm.plot(x = salesm.index, y = '实收金额')
plt.xlabel('Time')
plt.ylabel('People')
plt.title('ke liu liang (month)')
plt.show()
由图我们其实可以看出,该药店的销售总额和客流量基本成正比。二月份的客流量最少,同样销售业绩也最差,同样的四月份客流量最高,销售总额也最多。
但是六月份客流量变少了,而消费总额却变多了,可能是因为人均买的药更贵了,具体原因尚且不得而知,七月份的数据如此小的原因是因为七月份只统计了半个月的数据,数据不全,不能拿来做比较。
将销售数据按星期分组,得到如下结果。
sales.groupby('销售星期')['实收金额'].sum()
通过这里,我们可以发现,周五周六的销售总额要显著的的高于其他日期,即周五周六应该前来买药的人更多,销售的药品更多。
即每周的销售趋势是周日到周四销售总额会有波动,但是幅度不大,周五周六的销售总额相对较高,按月份比较的话,四月份的销售总额显著的高,而二月份的销售总额显著的低,猜测销售总额非常低是因为春节的缘故。
大概的数据分析过程就是这样了~
数据集链接如下:
链接:https://pan.baidu.com/s/12nkhZJlwZe7FaAqZakDHLQ
提取码:5ft9