1.数据源说明
1.1 数据简单说明
本数据源采用的是某餐厅8月份的销售明细表。本文会主要用到一下字段值:
- order_id, 产品订单号
- dishes_name,菜品名称
- counts, 消费数量
- amounts,消费金额
1.2 数据截图
以下是数据源的截图
1.3 数据源
数据链接:https://pan.baidu.com/s/1paqa8eA9znU7TTLLYPlIgg
提取码:vqvw
2. 实现思路
若该餐厅打算基于该年8月的订单明细数据情况,打算在当年的9-12月内推出1-2款爆款套餐,以此来吸引更多目标客户,从而增加门店的整体收入水平。为达成这一目的,现可以通过其进行TURF分析来进行解决。
- 1.选取进行组合的菜品
- 2.基于1中选取的产品进行TURF分析
- 3.基于TURF分析的结果进行组合选取
3.进行数据处理和清洗
对于拿到的数据,并非是直接能够进行使用的,因此需要一定的数据清洗
3.1 读入数据
import pandas as pd
import numpy as np
import itertools
import re
meal=pd.read_excel("餐厅销量表.xls")
meal.head()
3.2 菜单名称清洗
# 查看菜名称
meal['dishes_name'].unique()
发现菜单名称中有些不规则的符号
#进行数据清洗
meal['dishes_name']=meal['dishes_name'].map(lambda x:re.sub('(\r|\n|\t|\s)','',x))
meal['dishes_name'].unique()
3.3 选取菜品
基于销售额和销售量情况进行排名,各选取其top10,形成带选取的产品序列
#按菜品进行聚合
dishes_agg=meal.pivot_table(values=['counts','amounts'],index='dishes_name',aggfunc=sum)
#选取付款金额top10
dishes_agg_amount_top_10=dishes_agg.sort_values('amounts',ascending=False).iloc[:10,]
#选取订单数top10
dishes_agg_counts_top_10=dishes_agg.sort_values('counts',ascending=False).iloc[:10,]
concat_dishes=pd.concat([dishes_agg_amount_top_10,dishes_agg_counts_top_10])
# concat_dishes=concat_dishes.d
#进行去重
concat_dishes=concat_dishes.drop_duplicates()
#将得到的菜品进行排序组合
concat_dishes=concat_dishes.sort_values(['amounts','counts'],ascending=False)
trans_columns=concat_dishes.index.tolist()
#删除白饭大碗和小碗中的一种,由于大碗选的人数较多,此处删除小碗
trans_columns.remove('白饭/小碗')
print(trans_columns)
concat_dishes
其结果如下:
3.4 处理成符合要求的输入数据
3.4.1 构建订单和菜品组合
#构建统计矩阵
order_id=meal['order_id'].unique()
#进行笛卡尔乘积
order_dishes=list(itertools.product(order_id.tolist(),trans_columns))
order_dishes_df=pd.DataFrame(order_dishes)
order_dishes_df.columns=['order_id','dishes_name']
order_dishes_df
其结果如下:
将上述的统计矩阵与产品订单情况进行拼接,拼接代码如下:
#基于原始数据进行聚合
deal_agg=meal.pivot_table(values=['counts'],index=['order_id','dishes_name'],aggfunc=sum).reset_index()
#将统计矩阵与原始数据进行拼接,拼接方式为左连接
order_dishes_meg=pd.merge(order_dishes_df,deal_agg,on=['order_id','dishes_name'],how='left')
order_dishes_meg['counts'].fillna(0,inplace=True)
#将counts列的值大于0的都转为1
order_dishes_meg['counts']=order_dishes_meg['counts'].map(lambda x:1 if x>0 else 0)
#将矩阵变换为需要输入的格式
input_df=order_dishes_meg.pivot(index='order_id',columns='dishes_name',values='counts').rename_axis(columns=None).reset_index()
#关于是否将上述产品销量均为0的组合剔除问题,经考虑后认为无需剔除
input_df
得到的输入效果如下:
4.进行TURF分析
def TURF_tool(input_df,cols,max_cbts=10):
'''生成TURF分析结果,input_df为标准输入的dataframe,cols为需要进行组合的列名,需要为可迭代对象'''
#先生成组合方式
combinations=[]
for i in range(len(cols)):
combine=list(itertools.combinations(cols,i+1))
combinations.append(combine)
#统计以上结果,并进行汇总
#将对应数据选出,然后对所有列进行all处理,然后利用sum求和计算出符合条件的数量,如df.loc[:,list(combinations[1][0])].all(axis=1).sum()
# df.loc[:,list(combinations[1][0])]
combine_list=[]
for i in range(max_cbts):
print("正在计算第{}种组合\n".format(i+1))
temp=combinations[i]
temp_length= len(combinations[i])
for j in range(temp_length):
statis_dict={}
#提取组合方式,为可迭代对象
combine_cols=combinations[i][j]
# 按照组合形式,进行统计结果
#计算到达数
count_combine=input_df.loc[:,combine_cols].any(axis=1).sum()
#计算频数,即累计数量
acuum_combine=input_df.loc[:,combine_cols].sum().sum()
statis_dict['组合']=combine_cols
statis_dict['组合数']= i+1
statis_dict['到达数']=count_combine
statis_dict['频数']=acuum_combine
combine_list.append(statis_dict)
combine_result=pd.DataFrame(combine_list)
#得出总数
# combine_result['总数']=input_df.loc[:,cols].any(axis=1).sum()
combine_result['总数']=len(input_df)
#计算到达率
combine_result['到达率']=combine_result['到达数']/combine_result['总数']
#计算频率
combine_result['频率']=combine_result['频数']/combine_result['频数'].max()
#进行排序
combine_result=combine_result.sort_values('到达率',ascending=False)
return combine_result
t_df=TURF_tool(df,trans_cols)
t_df
进行TURF分析,运行后部分截图如下:
5.菜品搭配组合建议
由于该餐厅是为了吸引更多的用户,可以考虑设置2人餐组合和4人餐组合。此处按照2人餐进行举例进行分析,假如是两个人用餐,那么菜品的数量一般为4-5个,利用TURF分析的结果筛选组合数为4和5的菜品组合。效果如下:
组合数为4,部分截图如下
组合数为5,部分截图如下:
- 1.若选取菜品数量为4,可以考虑选用下面组合【‘麻辣小龙虾’, ‘谷稻小庄’, ‘五色糯米饭(七色)’, ‘白饭/大碗’】或【‘麻辣小龙虾’, ‘凉拌菠菜’, ‘五色糯米饭(七色)’, ‘白饭/大碗’】,这些组合形式不仅可以最大满足用户的需求,同时用户还可能会有更大概率多点套餐内的菜品;
- 2.若选取菜品数量为5,可以考虑下面组合【‘芝士烩波士顿龙虾’, ‘麻辣小龙虾’, ‘凉拌菠菜’, ‘五色糯米饭(七色)’, ‘白饭/大碗’】或【‘麻辣小龙虾’, ‘谷稻小庄’, ‘凉拌菠菜’, ‘五色糯米饭(七色)’, ‘白饭/大碗’】,理由同上。
6.写在最后
5中是基于订单本身给出的建议,但仅仅满足于此还不足够。现在有一些新的问题如下,留给读者进行思考。
- 假如菜品搭配时需要考虑价格因素,该如何搭配?
- 假如菜品搭配时要兼具一些滞销品,该如何搭配?
- 假如餐厅为追求高利润,该如何进行搭配?