针对某医院18年销售记录,做简单的数据分析,熟悉相关语法及分析过程。
一、分析目的
以某医院18年销售数据为例,了解18年的销售情况,分析几个业务指标,例如:月均消费次数,月均消费金额、客单价以及消费趋势等,可以用于了解不同季节的病情、指导医院备货等。
二、 数据分析过程
数据分析过程基本包括:数据获取、数据清洗、模型构建、数据可视化、相关分析等
1、数据获取
根据已有的18年销售单据,提取相应的数据。(本次没有数据抓取过程)首先导入相关的python包,并获取数据集。
# coding: utf-8 import xlrd import openpyxl import pandas as pd from pandas import Series, DataFrame import numpy as np #读取数据集,显示前5行 filename = r'C:\Users\Administrator\Desktop\朝阳医院2018年销售数据.xlsx' datafile = pd.ExcelFile(filename) data = datafile.parse('Sheet1')
#查看基本信息
data.shape
data.index
data.columns
data.count
显示信息如下:
总共有6578行7列数据,其中购药时间、社保卡号有6576行数据,其他的有6577行数据。所以此数据集中存在缺失值,需对缺失值进行处理。
2、数据清洗
数据清洗基本过程:选择子集、列重命名、缺失值处理、数据类型转换、数据排序、异常值处理等。
为便于分析,将其中列名:购买时间,更改为销售时间,消除歧义。
#列重命名
data.rename(columns={'购药时间':'销售时间'}, inplace = True)
print(data.head())
3、缺失值处理
从前面显示的信息中可以看出,数据集中存在缺失值。使用简单的方法,直接使用dropna函数删除缺失数据,具体如下:
#缺失值处理
print('删除缺失值前:',data.shape)
data.info()
dataDF = data.dropna(subset=['销售时间','社保卡号'], how = 'any')
print('删除缺失值后:',dataDF.shape)
dataDF.info()
4、数据类型转换
为便于数据导入,便于后续相关分析,最好对数据进行相应的转换。可以使用astype函数进行数据类型转换,并通过split函数对无用的时间信息进行分割,如下所示:
#数据类型转换
#转换各部分数据格式
dataDF['销售数量'] = dataDF['销售数量'].astype('str')#后面进行销售时间分割,不能为float类型
dataDF.dtypes#将销售时间中,星期与日期分开def split_time(timesale):
stime = sale_time.split(' ')[0]
timelist = [] for sale_time in timesale:
#将列表变成一个一维Series类型
timelist.append(stime)#分割销售时间,并提取时间部分,组成一个列表 STime = Series(timelist) return STime
dataDF.loc[:, '销售时间'] = time_data
#获取销售时间这一列,然后调用函数分割,并修改这一列saletime = dataDF.loc[:, '销售时间']time_data = split_time(saletime)
dataDF.head()
在把分割后的日期,转换为时间格式。
#把分割日期,转换为时间格式
dataDF.loc[:, '销售时间'] = pd.to_datetime(dataDF.loc[:, '销售时间'], format = '%Y-%m-%d', errors = 'coerce')
dataDF.dtypes#转换日期格式过程中,errors = 'coerce'不符合日期的格式,转换后的值为NaT#删除其中的空行
dataDF.info()
dataDF = dataDF.dropna(subset = ['销售时间','社保卡号'], how = 'any')
dataDF.shape
5、数据排序
对分割后的时间进行顺序排序,并按照此排序重置索引。
#(6)排序,排序之后,索引会被打断,需要重置索引
#(7)异常值处理
#查看描述统计信息
dataDF.describe()
#按销售时间排序sort_index报错,sort_value可行dataDF = dataDF.sort_index(by = '销售时间', ascending = True)dataDF.head()#重置索引dataDF = dataDF.reset_index(drop = True)dataDF.head()
6、异常值处理
先通过描述的统计信息,查看数据。通过min中有负数,判别出存在异常值。
#(7)异常值处理
#查看描述统计信息
dataDF.describe()
#排除异常值
pop = dataDF.loc[:,'销售数量'] > 0
dataDF = dataDF.loc[pop, :]
dataDF.describe()
7、数据可视化
#3.构建模型及可视化
#月均消费次数(总的消费次数/消费时间)
#(1)删除重复数据
data_unique = dataDF.drop_duplicates(subset=['销售时间', '社保卡号'])
total_row = data_unique.shape[0]
print('总的消费次数:', total_row)
#(2)消费时间
#按照消费时间重新排序,然后根据最大、最小时间计算月份数
data_unique = data_unique.sort_values(by = '销售时间', ascending = True)
#重置索引data_unique = data_unique.reset_index(drop = True)
endtime = data_unique.loc[total_row - 1, '销售时间']
starttime = data_unique.loc[0, '销售时间']days = (endtime - starttime).daysmonths = days // 30
print('月均消费次数:', kpil_M)
print('月份数:', months)
kpil_M = total_row // months
#月均消费金额
totalMoney = dataDF.loc[:, '实收金额'].sum()
monthMoney = totalMoney // months
print('月均消费金额:', monthMoney)
#消费趋势分析
import matplotlib.pyplot as plt
import matplotlib
mpl.rcParams['font.sans-serif'] = ['SimHei']#黑体
from pylab import mpl#用于显示中文
#复制一份数据
groupDF = dataDF
#将销售时间设置为index
groupDF.index = groupDF['销售时间']
groupDF.head()
#可视化绘图
plt.plot(groupDF['实收金额'])
plt.title('按天销售金额图')
plt.ylabel('实收金额')
plt.xlabel('时间')#保持图片
plt.savefig(r'C:\Users\Administrator\Desktop\sale_day.png')
#显示图片
plt.show()
#(4)分析药品销售情况
#聚合统计各种药品的销售数量
medicineS = groupDF[['商品名称', '销售数量']]
medicine_list = medicineS.groupby('商品名称')['销售数量']
all_medicine = medicine_list.sum()#对每种药品总量排序
all_medicine = all_medicine.sort_values()#(by = '销售数量', ascending = 'False')
all_medicine.head()#显示销售数量前十的药品top10 = all_medicine[:10]
print(top10)
#可视化前十种药品
top10.plot(kind='bar')#柱状图
plt.title('销售前十药品')
plt.ylabel('销售数量')
plt.xlabel('药品种类')plt.legend(loc=0)
plt.savefig(r'C:\Users\Administrator\Desktop\medicine.png')
plt.show()
全部代码:
# coding: utf-8 import xlrd import openpyxl import pandas as pd from pandas import Series, DataFrame import numpy as np #1.获取数据 #(1)读取数据集,显示前5行 filename = r'C:\Users\Administrator\Desktop\朝阳医院2018年销售数据.xlsx' datafile = pd.ExcelFile(filename) data = datafile.parse('Sheet1') #data.head() #查看基本信息 data.shape data.index data.columns data.count ################################################################################## #2.数据清洗 #(1)列重命名 data.rename(columns={'购药时间':'销售时间'}, inplace = True) #print(data.head()) #(2)缺失值处理 print('删除缺失值前:',data.shape) data.info() dataDF = data.dropna(subset=['销售时间','社保卡号'], how = 'any') print('删除缺失值后:',dataDF.shape) dataDF.info() #(3)数据类型转换 #转换各部分数据格式 dataDF['销售数量'] = dataDF['销售数量'].astype('str')#后面进行销售时间分割,不能为float类型 dataDF.dtypes #将销售时间中,星期与日期分开 def split_time(timesale): timelist = [] for sale_time in timesale: stime = sale_time.split(' ')[0] timelist.append(stime)#分割销售时间,并提取时间部分,组成一个列表 #将列表变成一个一维Series类型 STime = Series(timelist) return STime #获取销售时间这一列,然后调用函数分割,并修改这一列 saletime = dataDF.loc[:, '销售时间'] time_data = split_time(saletime) dataDF.loc[:, '销售时间'] = time_data dataDF.head() #把分割日期,转换为时间格式 dataDF.loc[:, '销售时间'] = pd.to_datetime(dataDF.loc[:, '销售时间'], format = '%Y-%m-%d', errors = 'coerce') dataDF.dtypes #转换日期格式过程中,errors = 'coerce'不符合日期的格式,转换后的值为NaT #删除其中的空行 dataDF = dataDF.dropna(subset = ['销售时间','社保卡号'], how = 'any') dataDF.shape dataDF.info() #(4)排序,排序之后,索引会被打断,需要重置索引 #按销售时间排序sort_index报错,sort_value可行 dataDF = dataDF.sort_index(by = '销售时间', ascending = True) dataDF.head() #重置索引 dataDF = dataDF.reset_index(drop = True) dataDF.head() #(5)异常值处理 #查看描述统计信息 dataDF.describe() #排除异常值 pop = dataDF.loc[:,'销售数量'] > 0 dataDF = dataDF.loc[pop, :] dataDF.describe() #3.构建模型及可视化 #(1)月均消费次数(总的消费次数/消费时间) #1)删除重复数据 data_unique = dataDF.drop_duplicates(subset=['销售时间', '社保卡号']) total_row = data_unique.shape[0] print('总的消费次数:', total_row) #2)消费时间 #按照消费时间重新排序,然后根据最大、最小时间计算月份数 data_unique = data_unique.sort_values(by = '销售时间', ascending = True) #重置索引 data_unique = data_unique.reset_index(drop = True) starttime = data_unique.loc[0, '销售时间'] endtime = data_unique.loc[total_row - 1, '销售时间'] days = (endtime - starttime).days months = days // 30 print('月份数:', months) kpil_M = total_row // months print('月均消费次数:', kpil_M) #(2)月均消费金额 totalMoney = dataDF.loc[:, '实收金额'].sum() monthMoney = totalMoney // months print('月均消费金额:', monthMoney) #(3)消费趋势分析 import matplotlib.pyplot as plt import matplotlib from pylab import mpl#用于显示中文 mpl.rcParams['font.sans-serif'] = ['SimHei']#黑体 #复制一份数据 groupDF = dataDF #将销售时间设置为index groupDF.index = groupDF['销售时间'] groupDF.head() #可视化绘图 plt.plot(groupDF['实收金额']) plt.title('按天销售金额图') plt.xlabel('时间') plt.ylabel('实收金额') #保持图片 plt.savefig(r'C:\Users\Administrator\Desktop\sale_day.png') #显示图片 plt.show() #(4)分析药品销售情况 #聚合统计各种药品的销售数量 medicineS = groupDF[['商品名称', '销售数量']] medicine_list = medicineS.groupby('商品名称')['销售数量'] all_medicine = medicine_list.sum() #对每种药品总量排序 all_medicine = all_medicine.sort_values()#(by = '销售数量', ascending = 'False') all_medicine.head() #显示销售数量前十的药品 top10 = all_medicine[0:10] print(top10) #可视化前十种药品 top10.plot(kind='bar')#柱状图 plt.title('销售前十药品') plt.xlabel('药品种类') plt.ylabel('销售数量') plt.legend(loc=0) plt.savefig(r'C:\Users\Administrator\Desktop\medicine.png') plt.show()