数据分析-73-快餐店热销分析与未来销售预测(包含数据和代码)

算法学习4对1辅导论文辅导核心期刊
项目的代码和数据下载可以通过公众号滴滴我


一、项目背景

本项目主要针对快餐店订单数据进行分析,有助于帮助快餐店分析哪类产品畅销,以及通过时间序列对未来一个月的销售额、销售量进行了预测,有助于餐厅进行资源规划。

二、数据说明

该数据共1000行,字段共10个

字段说明
order_id每个订单的唯一标识符
date交易日期
item_name食物名称
item_type物品类别(快餐或饮料)
item_price每个物品的单价
Quantity客户订购的数量
transaction_amount客户支付的总金额
transaction_type支付方式(现金、在线支付、其他)
received_by处理订单的人的性别
time_of_sale订单交易时间(早上、晚上、下午、夜间、午夜)

三、数据分析

a、Python库导入及数据读取

导入包

# 导入需要的库
import pandas as pd
import numpy as np
import seaborn as sns
import matplotlib.pyplot as plt
from statsmodels.tsa.seasonal import seasonal_decompose
from statsmodels.tsa.statespace.sarimax import SARIMAX
from pmdarima import auto_arima # 自动选择参数
import statsmodels.api as sm
import warnings
warnings.filterwarnings('ignore')

from pylab import mpl    
mpl.rcParams["font.sans-serif"] = ["SimHei"] # 设置显示中文字体 宋体    
mpl.rcParams["axes.unicode_minus"] = False #字体更改后,会导致坐标轴中的部分字符无法正常显示,此时需要设置正常显示负号

数据读取

# 读取数据
data = pd.read_csv("Balaji Fast Food Sales.csv")

b、数据预览及数据处理

i、数据预览
# 查看数据维度
data.shape

(1000, 10)

# 查看数据信息
data.info()

在这里插入图片描述

# 查看各列缺失值
data.isna().sum()

在这里插入图片描述

# 查看重复值
data.duplicated().sum()

0

ii、数据预处理
# 处理数据之前,先查看一下数据
data.head()

在这里插入图片描述

# 修改order_id格式
data['order_id'] = data['order_id'].astype(str)
# 将date列转换为日期格式
data['date'] = pd.to_datetime(data['date'])
# 用'Others'填充transaction_type列的缺失值
data['transaction_type'].fillna('Others', inplace=True)

c、数据探索

i、描述性统计
data.describe(include=[np.number])  # 只包括数值型字段

在这里插入图片描述

总结:

  1. 单价在20到60美元之间,平均单价约33.315美元,标准差约为14.92。
  2. 客户订购数量的平均值约为8.16,中位数为8,最小值为1,最大值为15,四分位数范围表明大多数订单的数量在4到12之间。
  3. 客户支付的总金额平均为275.23美元,中位数为240美元,最小值为20美元,最大值为900美元,标准差为204.4,表明交易金额的分布范围较广。
ii、可视化分析
sns.set_style("darkgrid")
# 调整画布大小和子图排列
fig = plt.figure(figsize=(15,15))

# 创建2x2的图布局
# 添加前四个小图
ax1 = fig.add_subplot(3, 2, 1)
ax2 = fig.add_subplot(3, 2, 2)
ax3 = fig.add_subplot(3, 2, 3)
ax4 = fig.add_subplot(3, 2, 4)
# 添加第三行的大图,这个大图跨越了两列
ax5 = fig.add_subplot(3, 1, 3)

# Item_type分布图
sns.countplot(x='item_type', data=data, ax=ax1)
ax1.set_title('Item Type Distribution')
ax1.set_xlabel('Item Type')
ax1.set_ylabel('Count')

# Transaction_type分布图
sns.countplot(x='transaction_type', data=data, ax=ax2)
ax2.set_title('Transaction Type Distribution')
ax2.set_xlabel('Transaction Type')
ax2.set_ylabel('Count')

# Received_by分布图
sns.countplot(x='received_by', data=data, ax=ax3)
ax3.set_title('Received By Gender Distribution')
ax3.set_xlabel('Received By')
ax3.set_ylabel('Count')

# Time_of_sale分布图
sns.countplot(x='time_of_sale', data=data, ax=ax4, order=['Morning', 'Afternoon', 'Evening', 'Night', 'Midnight'])
ax4.set_title('Time of Sale Distribution')
ax4.set_xlabel('Time of Sale')
ax4.set_ylabel('Count')

# Item_name的分布图
item_name_counts = data['item_name'].value_counts()
sns.barplot(y=item_name_counts.index, x=item_name_counts, ax=ax5)
ax5.set_title('Item Name Distribution')
ax5.set_xlabel('Frequency')
ax5.set_ylabel('Item Name')
plt.tight_layout()
plt.show()

在这里插入图片描述

总结:

  1. 快餐是交易量最大的类别,表明快餐可能是该餐厅的主打产品。
  2. 现金和在线支付是最常见的两种交易方式,其中现金比在线支付更多一点,其他支付方式的使用频率较低。
  3. 男性和女性接待顾客的订单数量可能大致相等,显示出性别在工作分配上的均衡。
  4. 下午和晚上的销售量高于其他时段,这可能与顾客的生活习惯或该餐厅的营业高峰时段有关。
  5. 销售最多的商品是冷咖啡,最少的是三明治。
# 创建一个新的大图,用于展示3个数值型特征的分布情况
fig, axes = plt.subplots(1, 3, figsize=(20, 5))

# item_price的分布情况
sns.distplot(data["item_price"], bins=30, kde=True, ax=axes[0])
axes[0].set_title('Item Price Distribution')
axes[0].set_xlabel('Item Price')
axes[0].set_ylabel('Count')

# Quantity的分布情况
sns.distplot(data["quantity"], bins=30, kde=True, ax=axes[1])
axes[1].set_title('Quantity Distribution')
axes[1].set_xlabel('Quantity')
axes[1].set_ylabel('Count')

# transaction_amount的分布情况
sns.distplot(data["transaction_amount"], bins=30, kde=True, ax=axes[2])
axes[2].set_title('Transaction Amount Distribution')
axes[2].set_xlabel('Transaction Amount')
axes[2].set_ylabel('Count')

plt.tight_layout()  # 调整子图布局
plt.show()

在这里插入图片描述

d、销售情况分析

i、销售量分析
time_category_sales = data.groupby(['time_of_sale', 'item_name'])['quantity'].sum().unstack().fillna(0)
# 获取每个时间段销售的总数量,以计算占比
time_sales_totals = time_category_sales.sum(axis=1)
time_category_sales_percentage = time_category_sales.divide(time_sales_totals, axis=0) * 100

# 绘制堆叠条形图,并在条形图中添加标签显示占比
fig, ax = plt.subplots(figsize=(14, 8))  # 设置图表大小

# 绘制堆叠条形图
time_category_sales.plot(kind='bar', stacked=True, colormap='viridis', ax=ax)

# 为了将标签放在条形中,我们计算每个条形的位置和高度
for i, (time_idx, item_row) in enumerate(time_category_sales.iterrows()):
    cum_height = 0  # 累积高度,用于定位条形中的标签位置
    for item_idx, value in item_row.iteritems():
        # 计算占比
        percentage = value / item_row.sum() * 100
        if value > 0:  # 仅为非零值添加标签
            ax.text(i, cum_height + value/2, f'{item_idx}: {percentage:.1f}%', 
                    ha='center', va='center', color='white', fontsize=10, fontweight='bold')
        cum_height += value

# 移除图例
ax.legend().set_visible(False)

# 设置图表标题和轴标签
ax.set_title('Consumer Preferences by Time of Sale')
ax.set_xlabel('Time of Sale')
ax.set_ylabel('Quantity Sold')

ax.set_xticklabels(time_category_sales.index, rotation=0)

# 显示图表
plt.tight_layout()
plt.show()

在这里插入图片描述

time_item_name_pivot = pd.pivot_table(data, values='quantity', 
                                      index='time_of_sale', 
                                      columns='item_name', 
                                      aggfunc=np.sum, 
                                      fill_value=0)

# 创建不同时间段和菜品的消费组合的热图
plt.figure(figsize=(14, 8))
sns.heatmap(time_item_name_pivot, annot=True, fmt=".0f", linewidths=.5, cmap="YlGnBu")
plt.title("Sales Quantity Heatmap by Time of Sale and Item Name")
plt.ylabel("Time of Sale")
plt.xlabel("Item Name")
plt.show()

在这里插入图片描述

总结

  1. 冷咖啡是一整天都相对比较受欢迎的饮品,尤其是在早上、下午和晚上销量较高,这可能与人们早晚需要提神的习惯有关。
  2. 三明治在早上和晚上的销售量很好,可以考虑将它作为早餐和晚餐的主推商品。
  3. 甘蔗汁在下午的销售量好,这可能与下午天气较热,人们需要解渴有关,但到了晚上,销量有所下降。
  4. Vadapav和Panipuri在午夜时段非常受欢迎,这可能是因为它们作为小吃在夜晚比较适合食用。
  5. Aalopuri的销售在晚上和午夜比较好,而在傍晚销售量最低。

建议

  1. 早上应该准备充足的冷咖啡和三明治,因为它们是早餐时间的热销商品。
  2. 下午可以多备一些甘蔗汁,因为它在热天时是顾客的热门选择。
  3. 晚上到午夜时间段,应该重点准备好Vadapav和Panipuri,以满足夜晚消费者对小食的需求。
  4. Aalopuri作为一个在晚上和午夜销售良好的商品,也需要适量准备。
  5. 考虑到冷咖啡全天都有稳定的销量,应该确保全天都有充足的供应。
ii、销售额分析
# 计算每个时间段的平均交易金额
average_transaction_by_time = data.groupby('time_of_sale')['transaction_amount'].mean().sort_values()

# 绘制每个时间段的平均交易金额的条形图
plt.figure(figsize=(14, 8))
sns.barplot(x=average_transaction_by_time.index, y=average_transaction_by_time.values, palette="coolwarm")
plt.title("Average Transaction Amount by Time of Sale")
plt.ylabel("Average Transaction Amount")
plt.xlabel("Time of Sale")
plt.xticks(rotation=0)  
plt.tight_layout()
plt.show()

在这里插入图片描述

time_item_sales = data.groupby(['time_of_sale', 'item_name'])['transaction_amount'].sum().unstack().fillna(0)
plt.figure(figsize=(14, 8))
sns.heatmap(time_item_sales, annot=True, fmt=".0f", linewidths=.5, cmap="BuPu")
plt.title('Sales Amount Heatmap by Time of Sale and Item Name')
plt.xlabel('Item Name')
plt.ylabel('Time of Sale')
plt.show()

在这里插入图片描述
总结:

  1. 晚上和早上的销售平均销售金额比较高,夜间和午夜的平均交易金额相对较低。
  2. 三明治、冷咖啡和Frankie这三类商品的总体带来的销售额比较高,Panipuri和Vadapav只有在午夜带来的销售额才比较高。
  3. Aalopuri销售额在夜间的时候最低。
  4. 甘蔗汁在下午的时候销售额最高。

e、时间序列分析

i、根据销售额分析
# 聚合数据以获取每天的总销售额
daily_sales = data.groupby('date')['transaction_amount'].sum()

# 创建时间序列图表
plt.figure(figsize=(20, 10))
daily_sales.plot(title='Daily Sales Amount Over Time', color='royalblue')
plt.xlabel('Date')
plt.ylabel('Total Sales Amount')
plt.show()

在这里插入图片描述

# 设置图表大小
plt.rcParams['figure.figsize'] = (20,15)

# 由于时间序列分解需要没有缺失值的完整序列,我们需要确保所有日期都有数据
# 为此,我们对缺失的日期进行填充,使用前一天的数据填充
daily_sales_complete = daily_sales.asfreq('D', method='ffill')

# 应用时间序列分解
result = seasonal_decompose(daily_sales_complete, model='additive')

# 绘制时间序列分解的结果
result.plot()
plt.show()

在这里插入图片描述
总结:
销售额数据确实表现出一定的季节性,尽管这个季节性模式在不同时间的影响程度不同。趋势部分显示了销售额随时间的整体变化,而残差则表现为随机波动,这些波动可能是由不规则因素如节假日促销、突发事件等引起的。

model = auto_arima(daily_sales_complete, seasonal=True, m=7, trace=True,error_action='ignore', suppress_warnings=True)

在这里插入图片描述

model.summary()

在这里插入图片描述

总结:
通过自动选择参数,这里选择了SARIMAX(2, 1, 2)模型,具有两个自回归项、一次差分和两个移动平均项。AIC:5599.808,BIC:5623.175。模型的结果显示一些参数在统计上显著,但残差分布的偏度和峰度表明分布可能偏离正态分布,模型没有表现出异方差性,这是积极的一面。

# 拟合模型
model.fit(daily_sales_complete)
forecast = model.predict(n_periods=30)
forecast

在这里插入图片描述

# 创建一个与预测值相对应的日期范围。这将取决于你的数据集的最后一个日期。
last_date = daily_sales_complete.index[-1]
forecast_dates = pd.date_range(start=last_date, periods=31, closed='right')  # 获取30天的预测,不包括最后一个已知数据点的日期

# 将预测值转换为Pandas Series,并设置索引为未来日期
forecast_series = pd.Series(forecast, index=forecast_dates)

# 绘制原始数据
plt.figure(figsize=(20,10))
plt.plot(daily_sales_complete, label='Observed', color='blue')

# 绘制预测数据
plt.plot(forecast_series, label='Forecast', color='red')

# 设置图例和标签
plt.legend()
plt.title('Daily Sales Forecast')
plt.xlabel('Date')
plt.ylabel('Sales')

# 显示图形
plt.show()

在这里插入图片描述

ii、根据销售量分析
# 对数据进行按日期聚合,计算每天的总销售量
daily_quantities = data.groupby('date')['quantity'].sum()
plt.figure(figsize=(20, 10))
daily_quantities.plot(title='Daily Sales Quantity Over Time', color='seagreen')
plt.xlabel('Date')
plt.ylabel('Total Sales Quantity')
plt.show()

在这里插入图片描述

# 保时间序列中没有缺失值。如果有缺失的日期,我们使用前一天的销售量数据进行填充
daily_quantities_complete = daily_quantities.asfreq('D', method='ffill')
result_quantities = seasonal_decompose(daily_quantities_complete, model='additive')
result_quantities.plot()
plt.show()

在这里插入图片描述
总结:
我们可以看到销售量的趋势在不同时间点有所变化,这可能暗示了消费者行为的变化或市场环境的变化,销售量有明显的季节性,表明销售量受周期性因素的影响,残差主要在0周围波动,但是也存在一些特别的异常值,可能是一些特殊事件导致的销售量突增或减少。

model = auto_arima(daily_quantities_complete, seasonal=True, m=7, trace=True,error_action='ignore', suppress_warnings=True)

在这里插入图片描述

model.summary()

在这里插入图片描述

总结:
通过自动选择参数,这里选择了SARIMAX(2, 1, 2)x(0, 0, [1], 7)模型,其中AR部分为2,差分为1,MA部分为2;季节性模型部分(S)的参数为0,没有季节性差分(D),季节性MA为1,周期为7天,此时AIC:2951.906,BIC:2979.167,有些参数在统计上显著,而有些则不显著。模型的残差分布不符合正态分布的假设,可能是因为偏度或数据中的异常值导致的。然而,残差的自相关性检验表明,时间序列的自相关已被模型适当地捕捉。

# 拟合模型
model.fit(daily_quantities_complete)
forecast = model.predict(n_periods=30)
forecast

在这里插入图片描述

# 创建一个与预测值相对应的日期范围。这将取决于你的数据集的最后一个日期。
last_date = daily_quantities_complete.index[-1]
forecast_dates = pd.date_range(start=last_date, periods=31, closed='right')  # 获取30天的预测,不包括最后一个已知数据点的日期

# 将预测值转换为Pandas Series,并设置索引为未来日期
forecast_series = pd.Series(forecast, index=forecast_dates)

# 绘制原始数据
plt.figure(figsize=(20,10))
plt.plot(daily_quantities_complete, label='Observed', color='blue')

# 绘制预测数据
plt.plot(forecast_series, label='Forecast', color='red')

# 设置图例和标签
plt.legend()
plt.title('Daily Quantity Forecast')
plt.xlabel('Date')
plt.ylabel('Quantity')

# 显示图形
plt.show()

在这里插入图片描述

f、总结

  1. 本项目主要采用了可视化分析,快餐是交易量最大的类别,表明快餐可能是该餐厅的主打产品,现金和在线支付是最常见的两种交易方式,其中现金比在线支付更多一点,其他支付方式的使用频率较低,男性服务员和女性服务员接待顾客的订单数量可能大致相等,显示出性别在工作分配上的均衡,下午和晚上的销售量高于其他时段,这可能与顾客的生活习惯或该餐厅的营业高峰时段有关,销售最多的商品是冷咖啡,最少的是三明治。
  2. 通过销售分析得出了冷咖啡是一整天都相对比较受欢迎的饮品,三明治在早上和晚上的销售量很好,甘蔗汁在下午的销售量好,到了晚上,销量有所下降,Vadapav和Panipuri在午夜时段非常受欢迎,Aalopuri的销售在晚上和午夜比较好。
    • 晚上和早上的销售平均销售金额比较高,夜间和午夜的平均交易金额相对较低,三明治、冷咖啡和Frankie这三类商品的总体带来的销售额比较高,Panipuri和Vadapav只有在午夜带来的销售额才比较高,Aalopuri销售额在夜间的时候最低,甘蔗汁在下午的时候销售额最高。
    • 最后进行时间序列分析,得出了销售额以及销售量均存在季节性(周期性),通过auto_arima构建了SARIMAX模型,预测了未来30天的销量以及销售额,有助于餐厅进行资源规划。
    • 建议:早上应该准备充足的冷咖啡和三明治,因为它们是早餐时间的热销商品。下午可以多备一些甘蔗汁,因为它在热天时是顾客的热门选择。晚上到午夜时间段,应该重点准备好Vadapav和Panipuri,以满足夜晚消费者对小食的需求,Aalopuri作为一个在晚上和午夜销售良好的商品,也需要适量准备,考虑到冷咖啡全天都有稳定的销量,应该确保全天都有充足的供应,可以推出一些组合套餐,拉动一些低销量,但是高销售额的商品。

算法学习4对1辅导论文辅导核心期刊
项目的代码和数据下载可以通过公众号滴滴我

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

AI研习星球

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值