前言
题目
随着国家政策的逐步开放,越来越多的药品可以在网络上购买,医药电商平台蒸蒸日上,受新冠疫情的影响,线下药店购买困难,更让医药电商进入了更多消费者的视野,各大药企也纷纷加大力度布局医药电商领域。但电商模式与线下零售有所不同,如何更好的经营医药电商成为药企急需解决的问题。本题采集了天猫维生素类的药品,请针对维生素药品进行数据的清洗、分析与挖掘,并回答下列问题。
- 对店铺进行分析,一共包含多少家店铺,各店铺的销售额占比如何?给出销售额占比最高的店铺,并分析该店铺的销售情况。
- 对所有药品进行分析,一共包含多少个药品,各药品的销售额占比如何?给出销售额占比最高的 10 个药品,并绘制这 10 个药品每月销售额曲线图。
- 对所有药品品牌进行分析,一共包含多少个品牌,各品牌的销售额占比如何?给出销售额占比最高的 10 个品牌,并分析这 10 个品牌销售较好的原因?
- 预测天猫维生素类药品未来三个月的销售总额并绘制拟合曲线,评估模型性能和误差。
- 一家药企计划将新的维生素品牌进行网络销售,聘请你当企业的顾问,请你设计一份不超过两页纸的电商经营策略。
摘 要
我们对维生素售卖的药店,维生素药品,维生素药品品牌进行了分析。
基于分析得到的信息给出了销售建议。
关键词
1 店铺分析
1.1 店铺数量
通过对数据shop_name栏的统计。
import pandas as pd
import matplotlib.pyplot as plt
import re
from matplotlib.pyplot import style
import statsmodels.api as sm
from statsmodels.graphics.tsaplots import plot_acf, plot_pacf
from statsmodels.tsa.stattools import adfuller as ADF
from scipy import stats
#qq图
from statsmodels.graphics.api import qqplot
# 加载北大分词包
import pkuseg
data = pd.read_excel('./data.xlsx'
print(data.head(
# 统计商店数量
shop = data['shop_name'].value_counts(
print(shop.head(
print(shop.tail(
print(shop.size
print(shop.index
发现共有26家店铺。分别是:
1.2 店铺销售额占比
1.2.1 数据预处理
由于数据中并没有销售额一栏,需要我们自行计算。
但是数据的折扣栏存在2884个空值。为了充分利用数据,所以我们使用折扣的众数(95折进行填充。之后为数据新增一列销售额sales。
# 空值数量
data['discount'].isnull(.sum(
# 空值处理 用众数填充
discount_mode = data['discount'].mode(
data['discount'].fillna(discount_mode[0], inplace=True
data['discount'].isnull(.sum(
# 将 9折等转化为 float 0.90
data['discount'] = data['discount'].apply(
lambda x: float(re.findall('[0-9\.]+', x[0]/10 if len(re.findall('[0-9\.]+', x!=0 else None
# 处理过后的空值数量 == 0
data['discount'].isnull(.sum(
# 创建销售额数据列
data['sales'] = data['price'] * data['sold'] * data['discount']
data['sales'].head(
经过分析发现天猫维生素品类,26家商店,两年的销售总额达到了1498551953元,即14.98亿元。
1.2.2 销售额占比柱状图
shop_name进行聚类,并对销售额sales进行逐项加和,求出每个商店两年内的销售总额,并绘制柱状图。
# 获取总的销售额
all_sales = data['sales'].sum(
# 对数据进行商店名称聚类
shop_group = data.groupby('shop_name'
# 以药店为组,进行销售额汇总
shop_sales = shop_group['sales'].agg('sum'
# 以药店销售额降序排列26个药店
shop_sales.sort_values(ascending=False
# 获取销售额占比
shop_sales_percent = (shop_sales / all_sales.sort_values(ascending=False
plt.figure(figsize=(8, 5
plt.rcParams['font.sans-serif'] = 'Simhei'
plt.bar(range(len(shop_sales_percent[:10], shop_sales_percent[:10]
plt.xticks(range(len(shop_sales_percent[:10], shop_sales_percent[:10].index, rotation=45, ha='right'
plt.title('销售额占比最多的10家商店'
plt.gcf(.subplots_adjust(bottom = 0.3
plt.grid(
plt.show(
plt.rcParams['font.sans-serif'] = 'Simhei'
plt.bar(range(len(shop_sales_percent[-10:], shop_sales_percent[-10:]
plt.xticks(range(len(shop_sales_percent[-10:], shop_sales_percent[-10:].index, rotation=45, ha='right'
plt.title('销售额占比最少的10家商店'
plt.gcf(.subplots_adjust(bottom = 0.3
plt.grid(
plt.show(
其中阿里健康大药房的销售总额以674820879元,即6.74亿,占比45.03%,位列第一。
天猫超市的销售总额以114308114元,即1.14亿,占比7.63%,位列第三。
经过分析得知电商天猫维生素类药品销量最好的是阿里系的药店,其他药店的销售份额占比非常小。
1.3 阿里健康大药房
1.3.1 年度分析
阿里健康大药房2020年有5998条数据,2021年有10960条数据。
# 阿里健康大药房
Ali = shop_group.get_group('阿里健康大药房'.copy(
# 年度分析对比
Ali_year = Ali.groupby(data.date_time.dt.year
Ali_year_sum = Ali_year['sales'].sum(
plt.rcParams['font.sans-serif'] = 'Simhei'
plt.bar(range(len(Ali_year_sum, Ali_year_sum
plt.xticks(range(len(Ali_year_sum, Ali_year_sum.index, rotation=45, ha='right'
plt.title('阿里健康大药房年度销售总额'
plt.grid(
plt.show(
growth_rate = (Ali_year_sum[2021] - Ali_year_sum[2020] / Ali_year_sum[2020]*100
1.3.2 季度分析
通过季度分析发现,第四季度购买次数最多,第一季度购买次数最少。
# 季度分析对比
Ali_qua = Ali.groupby(data.date_time.dt.quarter
Ali_qua_sum = Ali_qua['sales'].sum(
plt.rcParams['font.sans-serif'] = 'Simhei'
plt.bar(range(len(Ali_qua_sum, Ali_qua_sum
plt.xticks(range(len(Ali_qua_sum, Ali_qua_sum.index, rotation=45, ha='right'
plt.title('阿里健康大药房季度销售总额'
plt.grid(
plt.show(
1.3.3 月度分析
我们对阿里健康大药房的畅销商品进行了分析,其中维生素D滴剂,复合维生素片,多元维生素片,维生素AD滴剂,碳酸钙D3片为五大畅销产品。
# 月度分析
Ali['medicine'] = Ali['parameter'].apply(find_medi
Ali_medi = Ali.groupby('medicine'
Ali_medi_sum = Ali_medi['sales'].sum(.sort_values(ascending=False
Ali_keyMedi = Ali_medi_sum.index[:5]
print(Ali_medi_sum
Ali_medi_sum = Ali_medi['sales'].sum(.sort_values(
plt.rcParams['font.sans-serif'] = 'Simhei'
plt.barh(range(len(Ali_medi_sum[-10:], Ali_medi_sum[-10:]
plt.yticks(range(len(Ali_medi_sum[-10:], Ali_medi_sum[-10:].index
plt.title('阿里健康大药房王牌药品'
plt.gcf(.subplots_adjust(left = 0.2
plt.grid(
plt.show(
Ali_month_medi = Ali.groupby(['date_time','medicine']
num = Ali_month_medi['sales'].sum(
for i in range(5:
num1 = num[num.index.get_level_values(1 == Ali_keyMedi[i]]
plt.plot(range(len(num1, num1
plt.legend(Ali_keyMedi
plt.xticks(range(len(num1, num1.index.get_level_values(0.date, rotation=45, ha='right'
plt.gcf(.subplots_adjust(bottom = 0.2
plt.title('畅销产品月度销售额'
plt.show(
通过月度销售额分析,发现所有的畅销产品都有高频波动的迹象,存在明显的季节变动,每年6-7月,12-1月为销售量会大幅增加。
2 药品分析
2.1 数据预处理
经过对于数据的分析,药品名称在parameter里,并且有不同的形式。
药品通用名称,系列,药品名称。
系列属性存在无关信息列如,第14550行‘特价优惠’,第14628行‘其他’。
所以我们首先将阿里健康大药房的药品通用名称提取出来,制作成字典(72个品类的dict.txt。接着采用北大的Python分词包pkuseg,设置自己的字典(dict.txt,进行医学分词。
对parameter里的药品通用名称使用正则表达式提取出来,获得数据15345条。
def find_medi(x:
if type(x is str:
pattern = r"药品通用名:([\u4E00-\u9FD5 0-9 a-z A-Z ‘ \. /]+"
result = re.findall(pattern, x
if len(result >= 1:
return result[0]
else:
return None
else:
return None
def title_split(x:
x.upper(
result = segcut.cut(x
if len(result >= 1:
for i in result:
if i in dict:
return i
return None
else:
return None
dict = list(Ali_medi_sum.index
f = open("dict.txt", "w", encoding='utf-8'
for line in dict:
f.write(line + '\n'
f.close(
segcut = pkuseg.pkuseg(model_name = "medicine", user_dict = 'dict.txt', postag = False
data['medicine'] = data['title'].apply(title_split
data['medicine1'] = data['parameter'].apply(find_medi
# 以medicine1 的数据填充 medicine 的空值
data["medicine"].fillna(data["medicine1"], inplace=True
2.2 药品数量分析
通过对数据的药品通用名称统计,有112种药品。
medi_group = data.groupby('medicine'
medi_group.size(
2.3 药品销售额占比
# 以药品为组,进行销售额汇总
medi_sales = medi_group['sales'].agg('sum'
# 以药品销售额降序排列 获得销售占比
num = medi_sales.sort_values(ascending=False
num_rate = num / num.sum(
plt.rcParams['font.sans-serif'] = 'Simhei'
plt.bar(range(len(num_rate[:10], num_rate[:10]
plt.xticks(range(len(num_rate[:10], num_rate[:10].index, rotation=45, ha='right'
plt.title('销售额占比最多的10个品类'
plt.gcf(.subplots_adjust(bottom = 0.2
plt.grid(
plt.show(
2.4 10个药品每月销售额曲线图
keyMedi = list(medi_sales.sort_values(ascending=False.index[:10]
month_medi = data.groupby(['date_time','medicine']
num = month_medi['sales'].sum(
for i in range(10:
num1 = num[num.index.get_level_values(1 == keyMedi[i]]
plt.plot(range(len(num1, num1
plt.show(
plt.legend(keyMedi
plt.xticks(range(len(num1, num1.index.get_level_values(0.date, rotation=45, ha='right'
plt.gcf(.subplots_adjust(bottom = 0.2
plt.title('前10大畅销药品月度销售总额'
plt.show(
3 药品品牌分析
我们发现药品的品牌在Parameter里所以利用正则表达式进行提取。
3.1 数据预处理
# 品牌分析
pattern = "品牌:([\u4E00-\u9FD5 0-9 a-z A-Z ‘ \. \+ - /]+"
def find_brand(x:
if type(x is str:
pattern = "品牌:([\u4E00-\u9FD5 0-9 a-z A-Z ‘ \. \+ - /]+"
result = re.findall(pattern, x;
if len(result > 0:
return result[0]
else:
return None
else:
return None
data['brand'] = data['parameter'].apply(find_brand
3.2 品牌数目
分析发现总共有512个品牌。
# 对数据进行品牌名称聚类
brand_group = data.groupby('brand'
brand_group.size(
3.3 品牌销售额占比
# 以品牌为组,进行销售额汇总
brand_sales = brand_group['sales'].agg('sum'
# 以品牌销售额降序排列
num = brand_sales.sort_values(ascending=False
brand_top = list(num.index[:10]
num_rate = num / num.sum(
plt.rcParams['font.sans-serif'] = 'Simhei'
plt.bar(range(len(num_rate[:10], num_rate[:10]
plt.xticks(range(len(num_rate[:10], num_rate[:10].index, rotation=45, ha='right'
plt.title('销售额占比最多的10个品牌'
plt.gcf(.subplots_adjust(bottom = 0.2
plt.grid(
plt.show(
3.4 品牌销售好的原因分析
我们对十大品牌的药品销售情况做了分析,这些品牌之所以销量好,首先是药物销售品类与10大畅销品类高度重合,其次可能是品牌自身在这些品类的营销好,消费者认可。
# 品牌销售分析
band_medicine = data.groupby(['brand','medicine']
b_m_sum = band_medicine['sales'].sum(
num = b_m_sum
num1 = num[num.index.get_level_values(0 == brand_top[0]]
plt.rcParams['font.family'] = ['Arial Unicode MS','Microsoft YaHei','SimHei','sans-serif']
plt.rcParams['axes.unicode_minus'] = False
plt.subplots_adjust(left=None,bottom=None,right=None,top=None,wspace=0.5,hspace=1
for i in range(1,11:
# 往画布上添加子图:按五行二列,添加到下标为plt_index的位置(由于这个显示不太好,很挤,所以最后用 两行两列4个 生成3次 获得了最后的图)
plt.subplot(5, 2, i
# 绘图
num1 = num[num.index.get_level_values(0 == brand_top[i-1]]
plt.barh(range(len(num1, num1
plt.yticks(range(len(num1, num1.index.get_level_values(1
plt.title(brand_top[i-1] + '销售图'
# 显示画布
plt.show(
4 预测销售总额
这里的预测我们采取时间序列的差分整合移动平均自回归模型(ARIMA。
4.1 源数据
date = data.groupby('date_time'
date_sales = date['sales'].agg('sum'
plt.figure(figsize=(8,5
plt.plot(range(24, date_sales
plt.xticks(range(24, date_sales.index.date, rotation=45
plt.gcf(.subplots_adjust(bottom = 0.2
plt.title('销售总量'
plt.grid(
plt.show(
4.2 参数选择
平稳性检验:
采用单位根检验,对时间序列单位根的检验就是对时间序列平稳性的检验,非平稳时间序列如果存在单位根,则一般可以通过差分的方法来消除单位根,得到平稳序列。
style.use('ggplot'
plt. rcParams['font.sans-serif'] = ['SimHei']
plt. rcParams['axes.unicode_minus'] = False
sales_train = date_sales
sales_diff1 = sales_train.diff(.dropna(
for i in range(1,3:
plt.subplot(1, 2, i
if(i==1:
plt.plot(sales_train
plt.title("源数据"
else:
plt.plot(sales_diff1
plt.title("一阶差分"
print(u'原始序列的ADF检验结果为:', ADF(sales_train
print(u'一阶差分的ADF检验结果为:', ADF(sales_diff1
原始序列的ADF检验结果为: (-0.25294595330495406, 0.9319092621668796, 7, 16, {'1%': -3.9240193847656246, '5%': -3.0684982031250003, '10%': -2.67389265625}, 484.53439721589336
一阶差分的ADF检验结果为: (-9.322072363056753, 9.831298270974292e-16, 4, 18, {'1%': -3.859073285322359, '5%': -3.0420456927297668, '10%': -2.6609064197530863}, 455.9637318833934
一阶差分单位根检验p值<0.05,原始序列p值>0.05,于是ARIMA中的参数d定为1。
相关系数:
- 自相关系数(ACF):自相关系数度量的是同一事件在两个不同时期之间的相关程度,形象的讲就是度量自己过去的行为对自己现在的影响。
- 偏自相关系数(PACF):计算某一个要素对另一个要素的影响或相关程度时,把其他要素的影响视为常数,即暂不考虑其他要素的影响,而单独研究那两个要素之间的相互关系的密切程度时,称为偏相关。
acf = plot_acf(sales_diff1, lags=10
plt.title("ACF"
acf.show(
pacf = plot_pacf(sales_diff1, lags=10
plt.title("PACF"
pacf.show(
趋势序列 ACF 有 1 阶截尾,PACF 有 1 阶截尾尾。因此可以选 p=1,q=1。
4.3模形拟合预测
model = sm.tsa.arima.ARIMA(sales_train, order=(1, 1, 1
result = model.fit(
#print (result. sumary(
pred = result.predict( '20220101','20220301' ,dynamic=True, typ='levels'
print(pred
plt.figure(figsize=(12,8
plt.xticks(rotation=45
plt.plot(pred
plt.plot(sales_train
预测结果:
2022-01-01 9.497130e+07 94971300.0
2022-02-01 1.050360e+08 105036000.0
2022-03-01 1.024374e+08 102437400.0
4.4 模形评价
resid = result.resid # 求解模型残差
plt.figure(figsize=(12, 8
qqplot(resid, line='q', fit=True
stats.normaltest(resid#检验序列残差是否为正态分布
5 电商经营策略
商品经营无外乎更便宜,更丰富,更方便,提高商品周转率。
‘维生素D滴剂', '复合维生素片', '多维元素片', '维生素AD滴剂', '碳酸钙D3片', ‘维生素C咀嚼片', ‘维生素E软胶囊', ‘维生素E', ‘维生素C泡腾片', ‘维生素C片'。
'swisse':维生素C泡腾片。
'CONBA/康恩贝':维生素C咀嚼片。
'CENTRUM/善存':善存银片,多维元素片。
'星鲨':维生素D滴剂
'elevit/爱乐维':复合维生素片。
'伊可新':维生素AD滴剂,。
'养生堂':维生素E软胶囊, 维生素C咀嚼片。
'BY-HEALTH/汤臣倍健':维生素E软胶囊, 维生素C片。
'FANCL':维生素E软胶囊。
'朗迪':碳酸钙D3片。
鉴于销售旺季在每年6-7月,12-1月。所以应该提前一个月进行销售的预热。同时尽量用折扣给消费者一个便宜的低价,来拉动销量。