返回顶部

数据分析项目补充:医院药品销售数据分析

北京朝阳医院2018年销售数据分析项目

import pandas as pd
import numpy  as np
import matplotlib.pyplot as plt
import datetime
import calendar
# 在matplotlib模块绘图时如果是中文标题的话可能会出现显示不正常的情况,这种问题可以通过添加下面两行代码来解决这种问题
plt.rcParams['font.family'] = ['sans-serif']
plt.rcParams['font.sans-serif'] = ['SimHei']
#利用pandas库的read_excel读取xlsx文件
data = pd.read_excel(r'C:\Users\Administrator\Documents\Tencent Files\3189374495\FileRecv\朝阳医院2018年销售数据.xlsx')
data.head()#查看开头的数据,括号中可以输入显示几行也可以不写
运行结果:

购药时间	社保卡号	商品编码	商品名称	销售数量	应收金额	实收金额
0	2018-01-01 星期五	1.616528e+06	236701.0	强力VC银翘片	6.0	82.8	69.00
1	2018-01-02 星期六	1.616528e+06	236701.0	清热解毒口服液	1.0	28.0	24.64
2	2018-01-06 星期三	1.260283e+07	236701.0	感康	2.0	16.8	15.00
3	2018-01-11 星期一	1.007034e+10	236701.0	三九感冒灵	1.0	28.0	28.00
4	2018-01-15 星期五	1.015543e+08	236701.0	三九感冒灵	8.0	224.0	208.00
data.info()#info查看数据类型
运行结果:
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 6578 entries, 0 to 6577
Data columns (total 7 columns):
 #   Column  Non-Null Count  Dtype  
---  ------  --------------  -----  
 0   购药时间    6576 non-null   object 
 1   社保卡号    6576 non-null   float64
 2   商品编码    6577 non-null   float64
 3   商品名称    6577 non-null   object 
 4   销售数量    6577 non-null   float64
 5   应收金额    6577 non-null   float64
 6   实收金额    6577 non-null   float64
dtypes: float64(5), object(2)
memory usage: 359.9+ KB
data.shape#shape查看有多少行多少列,前面是行数,后者是列数
运行结果:
(6578,7)
data.isnull().sum()#isnull()查看是否有空值,加sum()求空值数量
运行结果:
购药时间    2
社保卡号    2
商品编码    1
商品名称    1
销售数量    1
应收金额    1
实收金额    1
dtype: int64
data = data.dropna(subset=['社保卡号'],how='any')#dropna用于删除空值操作,一般不会这么使用除非数据量很大不在乎这么一点,一般用填充解决
data.info()
运行结果:
<class 'pandas.core.frame.DataFrame'>
Int64Index: 6576 entries, 0 to 6577
Data columns (total 7 columns):
 #   Column  Non-Null Count  Dtype  
---  ------  --------------  -----  
 0   购药时间    6575 non-null   object 
 1   社保卡号    6576 non-null   float64
 2   商品编码    6576 non-null   float64
 3   商品名称    6576 non-null   object 
 4   销售数量    6576 non-null   float64
 5   应收金额    6576 non-null   float64
 6   实收金额    6576 non-null   float64
dtypes: float64(5), object(2)
memory usage: 411.0+ KB
data=data.drop(data[data['购药时间'].str[:10]=='2018-02-29'].index)#这里有2018-02-29号的数据,要知道18年是没有29日的,属于异常数据删除
data[data['购药时间'].isnull()]#查看2018年2月29日对应的数据
运行结果:
	购药时间	社保卡号	商品编码	商品名称	销售数量	应收金额	实收金额
6570	NaN	11778628.0	2367011.0	高特灵	10.0	56.0	56.0
data=data.loc[data['购药时间'].dropna().index]#删除该行异常数据
data['Date']=pd.to_datetime(data['购药时间'].str[:10],format='%Y-%m-%d')#利用datetime转换购药时间列为datetime数据类型
data.Date#查看
运行结果:
0      2018-01-01
1      2018-01-02
2      2018-01-06
3      2018-01-11
4      2018-01-15
          ...    
6572   2018-04-27
6573   2018-04-27
6575   2018-04-27
6576   2018-04-27
6577   2018-04-28
Name: Date, Length: 6552, dtype: datetime64[ns]
data.rename(columns={'购药时间':'销售时间'},inplace=True)#命名列名购药时间为销售时间,inplace参数如果为true就是修改原数据,如果为false就是不修改原数据
data=data.sort_values('Date')#按照日期排序
data=data.reset_index(drop=True)
data.describe()#describe快速统计数据
运行结果:
社保卡号	商品编码	销售数量	应收金额	实收金额
count	6.552000e+03	6.552000e+03	6552.000000	6552.00000	6552.000000
mean	6.095150e+09	1.015031e+06	2.384158	50.43025	46.266972
std	4.888430e+09	5.119572e+05	2.374754	87.68075	81.043956
min	1.616528e+06	2.367010e+05	-10.000000	-374.00000	-374.000000
25%	1.014290e+08	8.614560e+05	1.000000	14.00000	12.320000
50%	1.001650e+10	8.615070e+05	2.000000	28.00000	26.500000
75%	1.004898e+10	8.687840e+05	2.000000	59.60000	53.000000
max	1.283612e+10	2.367012e+06	50.000000	2950.00000	2650.000000
data=data.drop(data[(data['销售数量']<=0) | (data['应收金额']<=0)].index)#根据上表的数据我们发现销售数量和应收金额的min出现了负数,我们要知道金额和数量不可能是负数,所以这是异常值需要我们删除
data.duplicated().sum() #查找重复的数据

数据分析环节

# 月均消费次数
data_month_count=data.drop_duplicates(subset=['销售时间','社保卡号'])
day_number=(max(data_month_count.Date)-min(data_month_count.Date)).days
print('月均消费次数:%.2f' %(len(data_month_count)/(day_number//30)))
运行结果:
月均消费次数:890.83
# 月均消费金额
money_sum=data['实收金额'].sum()
print('月均实收金额: %.2f' %(money_sum/(day_number//30)))
运行结果:
月均实收金额: 50672.49
# 客单价
print('客单价: %.2f' %(money_sum/data_month_count.shape[0]))
运行结果:
客单价: 56.88
# 消费趋势
dd=data.set_index('Date',drop=True)# 将索引index编成日期,方便之后进行重采样
# 按天采样 #fontsize是字体大小
dd_day=dd.resample('D').sum()
plt.figure(figsize=(30,10),dpi=50)
plt.plot(dd_day.index,dd_day['实收金额'])
plt.title('平均每天销售金额',fontsize=20)
plt.legend(['money'],fontsize=20)
plt.xlabel('time',fontsize=20)
plt.ylabel('money_sum',fontsize=20)
运行结果:

1

# 按月采样
dd_month=dd.resample('M').sum()
plt.figure(figsize=(30,10),dpi=50)
plt.plot(dd_month.index,dd_month['实收金额'])
plt.title('平均每月销售金额',fontsize=20)
plt.legend(['money'],fontsize=20)
plt.xlabel('time',fontsize=20)
plt.ylabel('money_sum',fontsize=20)

#按星期采样
#对星期进行自定义排序
data['销售星期']=data['销售时间'].str[11:]
week=['星期一','星期二','星期三','星期四','星期五','星期六','星期日']
data['销售星期']=data['销售星期'].astype('category').cat.set_categories(week)
data=data.sort_values(by=['销售星期'])
#销售星期分析
data= data.sort_values('销售星期')
money_week=data.groupby(['销售星期'])['实收金额'].sum()
#绘图
plt.figure(figsize=(30,10),dpi=50)
plt.plot(money_week.index,money_week)
plt.xticks(money_week.index,fontsize=20)
plt.title('按星期划分的销售情况',fontsize=20)
plt.legend(['money'],fontsize=20)

分析结论

#根据以上图表和分析,我们可以发现周五和周六的销售总额要显著高于其他日期 即周五周六前来买药的客户人数更多,销售的药品数量更多
#根据每周的销售趋势是周日到周四销售总额会有波动,但是幅度不大,周五周六的销售总额相对较高,按月份比较的话,四月份的销售总额显著的高,而二月份的销售总额显著的低,猜测销售总额非常低是因为春节的缘故
posted @ 2021-01-21 17:53  Satan—yuan  阅读(223)  评论(0编辑  收藏  举报