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数据分析的知识点得到了一个综合运用,对于知识点有了更深刻的理解,理解到了编程的魅力,也能够更加的熟练的运用这门语言。随着计算机技术的全面发展,企业生产、收集、存储和处理数据的能力大大提高,数据量与日俱增。现实生活中,需要把这些繁多、复杂的数据通过统计分析进行提炼,以此研究出数据的发展规律,进而帮助企业管理层做出决策,所以数据分析的重要性逐渐体现出来,学习数据分析也是提高职场竞争力的重要技能之一。

对于这次设计离自己设定的目标还有一定的距离,像对许多定义概念的不了解,通过这次设计使我明白认真做事的重要性,使我体会到完成一件事的喜悦,以后面对困难的时候,都能有直面困难并克服它的决心。在以后的学习生活中我一定会能有更好的发挥,克服自己的缺点,不断改进,不断成长!

 

posted @ 2021-12-25 17:35  1111FAN  阅读(482)  评论(1)    收藏  举报