Python药店销售大数据分析
一、选题背景
数据分析作为大数据技术的重要组成部分,近年来随着大数据技术逐渐发展和成熟。数据分析技能,被认为是数据科学领域中数据从业人员需要具备的技能之一。随着计算机技术的全面发展,企业生产、收集、存储和处理数据的能力大大提高,数据量与日俱增,结合现实生活选取社会上热点数据,把这些繁多、复杂的数据通过统计分析进行提炼,以此研究出数据的发展规律,进而帮助用户做出决策。同时也让自己学习数据分析概念、分析流程和分析方法等相关知识。
二、大数据分析设计方案
1.本数据集的数据内容与数据特征分析
药店销售数据分析以表 2-1朝阳医院2018年销售数据为例,这些数据庞大,总共有6579行,分为购药时间、社保卡号、商品编号、销售数量、应收金额五列,目的是了解朝阳医院在2018年里的销售情况,通过对朝阳区医院的药品销售数据的分析,了解朝阳医院的患者的月均消费次数,月均消费金额、客单价以及消费趋势、需求量前几位的药品等。正因为数据庞大,如果通过人工统计的话,就会增加很多的时间,所以通过数据分析将会节约大量的人工成本。

表 2-1 朝阳医院部分销售数据
数据特征分析


通过这张图显示,每天消费总额差异较大,除了个别天出现比较大笔的消费,大部分人消费情况维持在1000-2000元以内。

这张图显示,7月消费金额最少,这是因为7月份的数据不完整,所以不具参考价值。
1月、4月、5月和6月的月消费金额差异不大.
2月和3月的消费金额迅速降低,这可能是2月和3月处于春节期间,大部分人都回家过年的原因。

这张图显示,每天消费金额在500以下的占绝大多数,个别天存在消费金额很大的情况。
2.数据分析的课程设计方案概述(包括实现思路与技术难点)
首先将数据进行数据清洗,第二步是构建模型,第三步是数据可视化,第四步是消费趋势分析如图 2-1所示。

图 2-1 流程图
本案例的技术难点是运用matplotlib库里的绘图函数使经过处理的数据图形可视化,让分析者直观地看到数据的特点。具体函数如表 2-2、表 2-3、表 2-4、表 2-5所示。

表 2-2 matplotlib库相关函数

表 2-3 绘制线型图函数以及相关参数

表 2-4 绘制直方图函数以及相关参数

表 2-5 绘制散点图函数以及相关参数
三、数据分析步骤(70 分)
1.数据源
请说明数据源采用的哪一个开放的数据集?如果是采集的,请说明采集来源 与方式。
社会数据
Facebook Graph
https://developers.facebook.com/docs/graph-api
通过百度将数据导入excel
2.数据清洗
列出数据清洗的主要步骤
1.缺失值处理
dataDF.rename(columns={'购药时间':'销售时间'},inplace=True)
print('删除缺失值前:', dataDF.shape)
# 使用info查看数据信息,
print(dataDF.info())
#删除缺失值
dataDF = dataDF.dropna(subset=['销售时间','社保卡号'], how='any')
print('\n删除缺失值后',dataDF.shape)
print(dataDF.info())
结果如图 2-4所示:

图 2-4 缺失值处理
2.数据类型转换
dataDF['销售数量'] = dataDF['销售数量'].astype('float')
dataDF['应收金额'] = dataDF['应收金额'].astype('float')
dataDF['实收金额'] = dataDF['实收金额'].astype('float')
print(dataDF.dtypes)
3.定义函数处理数据
'''
定义函数:分割销售日期,提取销售日期
输入:timeColSer 销售时间这一列,Series数据类型,例‘2018-01-01 星期五’
输出:分割后的时间,返回Series数据类型,例‘2018-01-01’
'''
def splitSaletime(timeColSer):
timeList=[]
for value in timeColSer:
dateStr=value.split(' ')[0] #用空格进行分割
timeList.append(dateStr)
timeSer=pd.Series(timeList) #将列表转行为一维数据Series类型
return timeSer
4.处理数据
#获取“销售时间”这一列
timeSer = dataDF.loc[:,'销售时间']
#对字符串进行分割,提取销售日期
dateSer = splitSaletime(timeSer)
#修改销售时间这一列的值
dataDF.loc[:,'销售时间'] = dateSer
dataDF.head()
'''
数据类型转换:字符串转换为日期
把切割后的日期转为时间格式,方便后面的数据统计:
'''
#errors='coerce' 如果原始数据不符合日期的格式,转换后的值为空值NaT
dataDF.loc[:,'销售时间']=pd.to_datetime(dataDF.loc[:,'销售时间'],format='%Y-%m-%d', errors='coerce')
print(dataDF.dtypes)
dataDF.isnull().sum()
'''
转换日期过程中不符合日期格式的数值会被转换为空值
删除含有NaT的空行
'''
dataDF = dataDF.dropna(subset=['销售时间','社保卡号'],how='any')
datasDF = dataDF.reset_index(drop = True)
dataDF.info()
5.数据排序
dataDF = dataDF.sort_values(by='销售时间', ascending=True)
dataDF = dataDF.reset_index(drop=True)
dataDF.head()
结果如图 2-5所示:

图 2-5 数据排序
6.查看描述统计信息
dataDF.describe()
结果如图 2-6所示:

图 2-6 统计信息
7.将'销售数量'这一列小于0的数据排除掉
pop = dataDF.loc[:,'销售数量'] > 0
dataDF = dataDF.loc[pop,:]
dataDF.describe()
3.大数据分析过程及采用的算法
1.业务指标1:月均消费次数
月均消费次数 = 总消费次数 / 月份数(同一天内,同一个人所有消费算作一次消费)
#计算总消费次数
#删除重复数据
kpil_Df = dataDF.drop_duplicates(subset=['销售时间','社保卡号'])
totalI = kpil_Df.shape[0]
print('总消费次数=',totalI)
#计算月份数
#按销售时间升序排序
kpil_Df = kpil_Df.sort_values(by='销售时间', ascending=True)
#重命名行名
kpil_Df = kpil_Df.reset_index(drop=True)
#获取时间范围
startTime = kpil_Df.loc[0,'销售时间']
endTime = kpil_Df.loc[totalI-1,'销售时间']
#计算月份
#天数
daysI = (endTime-startTime).days
mounthI = daysI//30
print('月份数=',mounthI)
#月平均消费次数
kpil_I = totalI//mounthI
print('业务指标1:月均消费次数=', kpil_I)
结果如图 2-7所示:

图 2-7 业务指标1
2.业务指标2:月均消费金额
月均消费金额 = 总消费金额 / 月份数
#消费总金额
totalMoneyF = dataDF.loc[:,'实收金额'].sum()
mounthMoney = totalMoneyF // mounthI
print('业务指标2:月均消费金额=', mounthMoney)
结果如图 2-8所示:

图 2-8 业务指标2
3.业务指标3:客单价
客单价 = 总消费金额 / 总消费次数
#客单价
pct = totalMoneyF / totalI
print('业务指标3:客单价=', pct)
结果如图 2-9所示:

图 2-9 业务指标3
4.数据可视化
1.分析每天的消费金额
import matplotlib.pyplot as plt
import matplotlib
#画图时用于显示中文字符
from pylab import mpl
mpl.rcParams['font.sans-serif'] = ['SimHei'] # SimHei是黑体的意思
#在操作之前先复制一份
#mpl.rcParams['font.sans-serif'] = ['Songti'] # Songti是宋体的意思
#font = FontProperties(fname='/Library/Fonts/Songti.ttc') #设置字体
#在操作之前先复制一份数据,防止影响清洗后的数据
groupDF = dataDF
#将'销售时间'设置为index
groupDF.index = groupDF['销售时间']
print(groupDF.head())
gb = groupDF.groupby(groupDF.index)
print(gb)
dayDF = gb.sum()
print(dayDF)
#画图
plt.plot(dayDF['实收金额'])
plt.title('按天消费金额')
plt.xlabel('时间')
plt.ylabel('实收金额')
plt.show()
结果如图 2-10所示:

图 2-10 按天销售金额
2.分析每月的消费金额
#将销售时间聚合按月分组
gb = groupDF.groupby(groupDF.index.month)
print(gb)
monthDF = gb.sum()
print(monthDF)
plt.plot(monthDF['实收金额'])
plt.title('按月消费金额')
plt.xlabel('时间')
plt.ylabel('实收金额')
plt.show()
结果如图 2-11所示:

图 2-11 按月消费金额
3.分析药品销售情况
#聚合统计各种药品数量
medicine = groupDF[['商品名称','销售数量']]
bk = medicine.groupby('商品名称')[['销售数量']]
re_medicine = bk.sum()
#对销售药品数量按降序排序
re_medicine = re_medicine.sort_values(by='销售数量', ascending=False)
top_medicine = re_medicine.iloc[:10,:]
top_medicine
# 数据可视化,用条形图展示前十的药品
top_medicine.plot(kind = 'bar')
plt.title('销售前十的药品')
plt.xlabel('药品')
plt.ylabel('数量')
plt.show()
结果如图 2-12所示:

图 2-12 销售前十的药品
4.每天的消费金额分布情况
# 每天消售金额 -- 散点图
plt.scatter(dataDF['销售时间'],dataDF['实收金额'])
plt.title('每天销售金额')
plt.xlabel('时间')
plt.ylabel('实收金额')
plt.show()
结果如图 2-13所示:

图 2-13 每天销售金额
5.附完整程序源代码(以及输出结果)
import numpy as np
from pandas import Series,DataFrame
import pandas as pd
file_name = 'C:/Users/小茂/Desktop/课程设计.zip/数据/朝阳医院2018年销售数据.xlsx'
xls = pd.ExcelFile(file_name)
dataDF = xls.parse('Sheet1',dtype='object')
dataDF.head()
结果如图 2-1所示:

图 2-2 导入原始数据
from matplotlib.pylab import style
from statsmodels.tsa.arima_model import ARIMA
from statsmodels.graphics.tsaplots import plot_acf, plot_pacf
print(dataDF.shape)
print(dataDF.index)
print(dataDF.columns)
print(dataDF.count())
结果如图 2-3所示:

图 2-3 查看数据属性
dataDF.rename(columns={'购药时间':'销售时间'},inplace=True)
print('删除缺失值前:', dataDF.shape)
print(dataDF.info())import zipfile
import os
import pandas as pd
import matplotlib.pyplot as plt
def unzip(zip_filepath, dest_path):
with zipfile.ZipFile(zip_filepath) as zf:
zf.extractall(path=dest_path)
def get_dataset_filename(zip_filepath):
with zipfile.ZipFile(zip_filepath) as zf:
return zf.namelist()[0]
dataset_path = 'C:/Users/86130/Downloads'
zip_filename = 'open-food-facts.zip'
zip_filepath = os.path.join(dataset_path, zip_filename)
dataset_filename = get_dataset_filename(zip_filepath)
dataset_filepath = os.path.join(dataset_path, dataset_filename)
unzip(zip_filepath, dataset_path)
start_date = datetime.datetime(2009, 1, 1)
import pandas as pd
import numpy as np
df = pd.read_table("C:/Users/86130/Downloads/CDNOW_master.txt",names = columns,sep = '\s+')
df.info()
print()
print(df.head())
df['order_dt'] = pd.to_datetime(df.order_dt,format ='%Y%m%d')
df['mouth'] = df.order_dt.values.astype('datetime64[M]')
print(df.head())
df.describe()
import matplotlib.pyplot as plt
columns = ['user_id','order_dt','order_products','order_amount']
end_date = datetime.datetime(2019, 4, 1)
stock_code = '600519.SS' data = pd.read_csv(dataset_filepath, usecols=['countries_en', 'additives_n'])
print(diff.head())
print(diff.dtypes)
plt.figure()
plt.plot(diff)
plt.title('总消费次数')
plt.show()
print('总消费次数=',totalI)
kpil_Df = kpil_Df.sort_values(by='销售时间', ascending=True)
kpil_Df = kpil_Df.reset_index(drop=True)
startTime = kpil_Df.loc[0,'销售时间']
endTime = kpil_Df.loc[totalI-1,'销售时间']
daysI = (endTime-startTime).days
mounthI = daysI//30
acf.show()
pacf = plot_pacf(stock_train, lags=20)
plt.title()
pacf.show()
timeList=[]
for value in timeColSer:
dateStr=value.split(' ')[0] #用空格进行分割
timeList.append(dateStr)
timeSer=pd.Series(timeList)
return timeSer
timeSer = dataDF.loc[:,'销售时间']
dateSer = splitSaletime(timeSer)
dataDF.loc[:,'销售时间'] = dateSer
dataDF.head()
dataDF.loc[:,'销售时间']=pd.to_datetime(dataDF.loc[:,'销售时间'],format='%Y-%m-%d', errors='coerce')
print(dataDF.dtypes)
dataDF.isnull().sum()
print('月份数=',mounthI)
kpil_I = totalI//mounthI
stock_df = pandas_datareader.data.DataReader(stock_code, 'yahoo', start_date, end_date)
print(stock_df.head())
dataDF = dataDF.dropna(subset=['销售时间','社保卡号'], how='any')
print('\n删除缺失值后',dataDF.shape)
print(dataDF.info())
结果如图 2-4所示:

图 2-4 缺失值处理
dataDF['销售数量'] = dataDF['销售数量'].astype('float')
dataDF['应收金额'] = dataDF['应收金额'].astype('float')
dataDF['实收金额'] = dataDF['实收金额'].astype('float')
print(dataDF.dtypes)
def splitSaletime(timeColSer):
plt.plot(stock_df['Close'])
plt.title('销售数量')
plt.show('应收金额')
stock_s = stock_df['Close'].resample('W-MON').mean()
stock_train = stock_s['2014':'2018']
plt.plot(stock_train)
plt.title('实收金额')
plt.show()
acf = plot_acf(stock_train, lags=20)
plt.title()
acf.show()
pacf = plot_pacf(stock_train, lags=20)
plt.title()
pacf.show()
timeSer = dataDF.loc[:,'销售时间']
dateSer = splitSaletime(timeSer)
dataDF.loc[:,'销售时间'] = dateSer
dataDF.head()
dataDF.loc[:,'销售时间']=pd.to_datetime(dataDF.loc[:,'销售时间'],format='%Y-%m-%d', errors='coerce')
print(dataDF.dtypes)
dataDF.isnull().sum()
dataDF = dataDF.dropna(subset=['销售时间','社保卡号'],how='any')
datasDF = dataDF.reset_index(drop = True)
dataDF.info()
dataDF = dataDF.sort_values(by='销售时间', ascending=True)
dataDF = dataDF.reset_index(drop=True)
dataDF.head()
结果如图 2-5所示:

图 2-5 数据排序
dataDF.describe()
结果如图 2-6所示:

图 2-6 统计信息
pop = dataDF.loc[:,'销售数量'] > 0
dataDF = dataDF.loc[pop,:]
dataDF.describe()
kpil_Df = dataDF.drop_duplicates(subset=['销售时间','社保卡号'])
totalI = kpil_Df.shape[0]
stock_diff = stock_train.diff()
diff = stock_diff.dropna()
from pylab import mpl
acf_diff = plot_acf(diff, lags=20)
plt.title()
acf_diff.show()
pacf_diff = plot_pacf(diff, lags=20)
plt.title('销售时间')
pacf_diff.show()
mpl.rcParams['font.sans-serif'] = ['SimHei']
groupDF = dataDF
groupDF.index = groupDF['销售时间']
print(groupDF.head())
gb = groupDF.groupby(groupDF.index)
print(gb)
dayDF = gb.sum()
cum1 = group_userID.sum().sort_values("order_amount").apply(lambda x:x.cumsum()/x.sum())
cum1.reset_index().order_amount.plot()
plt.show()
print(diff.head())
print(diff.dtypes)
plt.figure()
plt.plot(diff)
plt.title('总消费次数')
plt.show()
print('总消费次数=',totalI)
kpil_Df = kpil_Df.sort_values(by='销售时间', ascending=True)
kpil_Df = kpil_Df.reset_index(drop=True)
startTime = kpil_Df.loc[0,'销售时间']
endTime = kpil_Df.loc[totalI-1,'销售时间']
daysI = (endTime-startTime).days
mounthI = daysI//30
print('月份数=',mounthI)
kpil_I = totalI//mounthI
print('业务指标1:月均消费次数=', kpil_I)
结果如图 2-7所示:

图 2-7 业务指标1
totalMoneyF = dataDF.loc[:,'实收金额'].sum()
mounthMoney = totalMoneyF // mounthI
print('业务指标2:月均消费金额=', mounthMoney)
结果如图 2-8所示:

图 2-8 业务指标2
pct = totalMoneyF / totalI
print('业务指标3:客单价=', pct)
结果如图 2-9所示:

图 2-9 业务指标3
import matplotlib.pyplot as plt
import matplotlib
from pylab import mpl
acf_diff = plot_acf(diff, lags=20)
plt.title()
acf_diff.show()
pacf_diff = plot_pacf(diff, lags=20)
plt.title('销售时间')
pacf_diff.show()
mpl.rcParams['font.sans-serif'] = ['SimHei']
groupDF = dataDF
groupDF.index = groupDF['销售时间']
print(groupDF.head())
gb = groupDF.groupby(groupDF.index)
print(gb)
dayDF = gb.sum()
medicine = groupDF[['商品名称','销售数量']]
bk = medicine.groupby('商品名称')[['销售数量']]
re_medicine = bk.sum()
re_medicine = re_medicine.sort_values(by='销售数量', ascending=False)
top_medicine = re_medicine.iloc[:10,:]
top_medicine
top_medicine.plot(kind = 'bar')
plt.title('销售前十的药品')
print(dayDF)
plt.plot(dayDF['实收金额'])
plt.title('按天消费金额')
plt.xlabel('时间')
plt.ylabel('实收金额')
plt.show()
结果如图 2-10所示:

图 2-10 按天销售金额
gb = groupDF.groupby(groupDF.index.month)
print(gb)
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
columns = ['user_id','order_dt','order_products','order_amount']
df = pd.read_table("C:/Users/86130/Downloads/CDNOW_master.txt",names = columns,sep = '\s+')
df.info()
print()
print(df.head())
model = ARIMA(stock_train, order=(1, 1, 1), freq='W-MON')
arima_result = model.fit()
print(arima_result.summary())
monthDF=gb.sum()pred_vals=arima_result.predict(start=str('2019-01'),end=str('2019-03'),dynamic=False, typ='levels')
print(pred_vals)
stock_forcast = pd.concat([stock_s, pred_vals], axis=1, keys=['original', 'predicted'])
plt.figure()
plt.plot(stock_forcast)
plt.title('实收金额')
plt.savefig('./stock_pred.png', format='png')
plt.show()
print(monthDF)
plt.plot(monthDF['实收金额'])
plt.title('按月消费金额')
plt.xlabel('时间')
plt.ylabel('实收金额')
plt.show()
结果如图 2-11所示:

图 2-11 按月消费金额
medicine = groupDF[['商品名称','销售数量']]
bk = medicine.groupby('商品名称')[['销售数量']]
re_medicine = bk.sum()
re_medicine = re_medicine.sort_values(by='销售数量', ascending=False)
top_medicine = re_medicine.iloc[:10,:]
top_medicine
top_medicine.plot(kind = 'bar')
plt.title('销售前十的药品')
plt.xlabel('药品')
plt.ylabel('数量')
plt.show()
结果如图 2-12所示:

图 2-12 销售前十的药品
plt.scatter(dataDF['销售时间'],dataDF['实收金额'])
plt.title('每天销售金额')
plt.xlabel('时间')
plt.ylabel('实收金额')
plt.show()
四、总结(10 分)
这次的朝阳医院的销售数据分析让我将python数据分析的知识点得到了一个综合运用,对于知识点有了更深刻的理解,理解到了编程的魅力,也能够更加的熟练的运用这门语言。随着计算机技术的全面发展,企业生产、收集、存储和处理数据的能力大大提高,数据量与日俱增。现实生活中,需要把这些繁多、复杂的数据通过统计分析进行提炼,以此研究出数据的发展规律,进而帮助企业管理层做出决策,所以数据分析的重要性逐渐体现出来,学习数据分析也是提高职场竞争力的重要技能之一。
对于这次设计离自己设定的目标还有一定的距离,像对许多定义概念的不了解,通过这次设计使我明白认真做事的重要性,使我体会到完成一件事的喜悦,以后面对困难的时候,都能有直面困难并克服它的决心。在以后的学习生活中我一定会能有更好的发挥,克服自己的缺点,不断改进,不断成长!
浙公网安备 33010602011771号