数据挖掘实战—餐饮行业的数据挖掘之数据探索(EDA)
文章目录
-
- 引言
- 一、前期准备
-
- 1.目标定义与任务理解
-
第二章 数据采集与抽样
-
第三章 数据探索
-
第1节 数据质量分析
- 第2节 缺失值分析
-
第3小节 缺失值可视化
-
第4小节 描述性统计
-
第5小节 统计缺失数与缺失率
-
1.2异常值分析
-
- 1.2.1 3σ原则
- 1.2.2箱型图分析
-
1.3一致性分析
-
1.4重复数据处理
- 2.数据特征分析
-
- 2.1分布分析
-
- 2.1.1定量数据的分布分析
- 2.1.1定性数据的分布分析
-
2.2 对比分析
-
- 2.2.1 绝对数比较
- 2.2.2 相对数比较
-
2.3统计量分析
-
- 2.3.1 集中趋势
- 2.3.2 离中趋势
-
- 第2节 缺失值分析
-
2.4 周期特性的考察
- 2.5 重要性的评估
- 2.6 关联性研究
-
* 2.6.1 散点图的生成-
* 2.6.2 散点图矩阵的构建 -
* 2.6.3 相关性指标的计算
-
- 本文主要参考了《Python数据分析与挖掘实战》这本书。
- [数据集下载链接, 密码为1234]可访问该资源。
- [《Python数据分析与挖掘实战》电子书下载链接, 密码为1234]可供查阅。
引言
数据挖掘的主要涉及分类与预测、聚类分析、关联规则、时序模式识别、偏差检测以及智能推荐等多种方法的应用,旨在帮助企业深入挖掘存在于数据中的潜在商业价值,并有效提升企业的核心竞争力。对于餐饮行业而言,其核心任务则是从企业内部获取各类菜品销量、单位成本、会员消费水平以及促销活动等内部信息,并结合外部环境要素如天气、节假日、竞争对手及周边商业氛围等外部数据信息,在应用数据分析技术的基础上实现精准推荐菜品种类、深入分析促销效果并评估客户的购买价值。同时通过系统化的分析手段优化新店选址策略,并对热销与滞销菜品的分析与预测提供决策支持。这些结果将被传递给企业管理人员作为制定精准营销策略的重要依据。本文将以餐饮行业的实际案例为例介绍数据分析探索(EDA)的一般工作流程。
一、前期准备
这一部分主要包括:
- 目标设定
- 深入理解
- 制定指标
制定指标的过程则需基于既定的目标设定和对任务的深入分析。
1.目标定义与任务理解
为了满足数据 mining 应用的需求,在确定 mining 目标时(即明确你的目的),你需要了解系统完成后将产生什么样的作用或价值。在餐饮行业中的 data mining 中,则可以设定以下具体的目标:
开发智能化的动态菜品推荐系统,并非仅仅会根据顾客的兴趣来推荐菜肴;同时这些菜肴能够帮助餐厅实现最大的收益。将不同级别的客户群体进行分类处理,并为每个群体制定差异化的营销方案;提升整体精准营销水平。通过分析销售数据以及其他相关因素;建立预测模型以预估各菜品的需求量;从而有助于合理备货。利用餐饮行业的大数据资源;科学地选择新店铺位置;并找出客户的饮食偏好;以便及时调整菜单内容以满足市场需求。
二、数据采集与抽样
在设定明确的挖掘目标后
- 数据系统性完整且全面满足各项指标的要求。
- 数据真实可靠,并严格区分正常状态与异常状态的表现。
注意: 特别强调,在从运行中的系统中进行数据采集时,请确保采集到的数据具有高度的完整性与合理性。
抽样的方式有以下几种:
-
随机取样
-
系统取样
-
分层 抽取
首先将样本总体划分为若干个层级,并确保每个层级中的调查对象具有相等的被抽取概率;然而,在不同层级之间可设定不同的抽取比例。 -
按起始顺序抽样
-
分类 抽样
依据某种属性的取值来选择数据子集
三、数据探索
通过对样本数据集的质量评估、进行可视化呈现以及计算关键指标等手段实施操作的行为称为数据分析中的探索过程。这一过程能够帮助我们选择适合的数据预处理方案以及建立合适的模型。其主要目的是为了弄清楚以下问题:
- 是否样本数据集的规模与标准能否满足模型构建的需求?
- 数据序列是否存在明显的规律性和发展趋势?
- 数据序列是否会呈现超出预期的异常状态?
- 属性间是否存在关联性?
- 数据序列可能划分为哪些类别?
接下来将从数据质量分析与数据特征分析两方面来对数据进行探索
1.数据质量分析
数据质量分析的核心职责在于识别并评估原始数据中的质量问题。具体而言,在这份数据分析任务中,我们需要重点识别并评估以下几类质量问题:首先是对字段中的完整性和准确性进行核查(包括但不限于缺失记录数量、数值偏差及格式不符情况);其次是对字段间的逻辑一致性进行考察(包括但不限于前后不匹配的数据点以及异常逻辑关系);最后是对字段间的一致性特征进行比较(包括但不限于单位统一性及表现形式的一致性)。本章将分别对上述三类问题展开深入探究。
1.1缺失值分析
数据中的缺省问题主要涉及记录层面和字段信息层面的具体表现。在进行初步的数据清理时通常会关注各属性是否存在缺省情况及其程度。
对于处理数据中的缺省问题而言,在进行初步的数据清理时通常会关注各属性是否存在缺省情况及其程度。
原因:
- 部分数据难以及时采集,并且其收集成本较高从而限制了信息获取的效率
- 部分关键数据未能完整呈现
- 对于某些特定的对象而言,在数据存储过程中可能会出现属性缺失的情况;值得注意的是,在这些情况下缺失值并非表示数据存在错误
- 对于某些对象而言,其属性在存储过程中可能并未被记录,这种情况下的缺失并不意味着数据有误,而是反映了对象本身的属性不存在这一事实,即属性缺失本身就是一种状态
1.1.1缺失值可视化
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
import missingno as mg
cat_sale = pd.read_csv('data/catering_sale.csv',header=0,index_col=0,encoding='gbk') # 餐饮数据
代码解读
# 缺失可视化
mg.matrix(cat_sale)
代码解读
1.1.2描述性统计
# 描述性统计
cat_sale.describe()
代码解读

len(cat_sale)
# 201
代码解读
其中count是非空值的个数,与len相比少1,则缺失数目为1。
# 给出样本数据的相关信息概览 :行数,列数,列索引,列非空值个数,列类型,内存占用
cat_sale.info()
代码解读

201行200个非空值,则有1个空值。
1.1.3统计缺失数与缺失率
# 一个函数,统计每一列的缺失个数及缺失比例
def missing_percentage(df):
total = df.isnull().sum().sort_values(ascending=False)[df.isnull().sum().sort_values(ascending=False) != 0]
percent = round(total * 100 / len(df),2)
return pd.concat([total,percent],axis=1,keys=['Total','Percentage'])
missing_percentage(cat_sale)
代码解读

缺失率为0.5%
1.2异常值分析
离群数据点是指样本中少数几个数值上存在显著差异的数据点。关注出现的异常数据点,并探讨其产生潜在原因的过程,在模型构建过程中需采取相应的措施。异常数据点分析主要有以下三种方法:
a) 统计检验法:通过计算Z得分或IQR识别离群数据;
b) 可视化诊断:利用箱线图或散点图直观发现离群数据;
c) 模型拟合法:通过逐步回归等方法筛选出对模型影响较大的变量。
基本的统计分析中
- 3σ原则
如果数据符合正态分布,在3\sigma原则下(即按照3σ原则),异常值被视为一组测定结果中与均值偏差超过3个标准差的数据点。
当数据不遵循正态分布时,则通常采用偏离均值的标准差数量作为描述依据
箱型图采用了一种判别异常值的标准方法:将数值划分为低于下四分位数1.5倍四分位距(IQR)或高于上四分位数加1.5倍IQR的范围视为异常值。具体而言,在此方法中:
- Q_L= 下四分位数
- Q_U= 上四分位数
- IQR= Q_U - Q_L, 其涵盖了全部观测数据的一半范围
1.2.1 3σ原则

据图发现,数据不服从正态分布,不建议使用3σ原则
1.2.2箱型图分析
# 箱型图分析
# 解决中文字体
plt.rcParams['font.sans-serif'] = ['SimHei']
# 解决负号问题
plt.rcParams['axes.unicode_minus'] = False
p = cat_sale.boxplot(return_type='dict')
# 获得异常点的x,y
x = p['fliers'][0].get_xdata()
y = p['fliers'][0].get_ydata()
y.sort() # 处理异常点接近的情况
print(x)
# 对异常点进行注释-annotate,某些相近的点注释会出现重叠,需要来控制位置
for i in range(len(x)):
# 发现有异常点接近的情况,分情况讨论
if i > 0:
plt.annotate(y[i],xy=(x[i],y[i]),xytext=(x[i] +0.05 - 0.8 /(y[i]-y[i-1]),y[i]))
else:
plt.annotate(y[i],xy=(x[i],y[i]),xytext=(x[i] +0.08,y[i]))
代码解读

通过异常值分析,可以确定过滤规则,在数据预处理当中,编写过滤程序。
1.3一致性分析
在进行数据挖掘时,在数据集成阶段容易出现不一致的数据问题。这通常是因为来自不同来源的数据被整合在一起后,并未对重复存储的数据进行一致性更新而导致的。
1.4重复数据处理
在获取的数据中可能存在重复项,在这种情况下通常的做法是进行删除处理。在pandas库中对应实现这一功能的方法是drop_duplicates()函数,在其中调用的函数名称为duplicated()的方法可用于检测数据中的重复项。

注意到存在两个重复值。然而,在这里仅是销量相等。尽管如此,在此情境下仅是销量相等。按照常识判断,在这种情况下不应删除
2.数据特征分析
通过绘制图表,计算某些特征量等进行数据特征分析
2.1分布分析
通过开展分布分析,可以揭示数据所呈现的具体特征及其类型。在处理定量数据时,我们可以通过制作频数分布表、绘制直方图以及茎叶图来进行详细观察;而对于定性数据,则可通过制作饼图和条形图来直观展示其分布在不同类别中的表现。
2.1.1定量数据的分布分析
在分析定量数据时,确定合适的频率分布直方图的分组数量与宽度被视为核心问题。通常遵循以下步骤完成:
- 第一步: 计算极差
- 第二步:确定组距及组数
- 第三步:选定分界点
- 第四步:制作频率分布表
- 第五步:绘制频率分布直方图
以“捞起生鱼片”在2014年第二个季度的销售数据为例,
cat_fish_sale = pd.read_excel('data/catering_fish_congee.xls',index_col=0,header=None,names=['date','sale'],encoding='gbk')
代码解读

- 求极差与确定组距与组数

- 列出频率分布表与绘制频率分布直方图
# 对数据进行分箱
bins = [0,500,1000,1500,2000,2500,3000,3500,4000] # 分位点
labels = ['[0,500)','[500,1000)','[1000,1500)','[1500,2000)','[2000,2500)','[2500,3000)','[3000,3500)','[3500,4000)'] # 箱名
cat_fish_sale['sale分箱']=pd.cut(cat_fish_sale.sale,bins,labels=labels)
# 聚合统计每一个箱的数量
aggResult = cat_fish_sale.groupby(by='sale分箱')['sale'].size()
# aggResult = cat_fish_sale.groupby(by='sale分箱')['sale'].agg(np.size) # agg函数常与groupby一起使用,传入自己的聚合函数
paggResult = round(aggResult / aggResult.sum(),2)
代码解读

plt.figure(figsize=(10,8))
paggResult.plot(label='sale',color='k',alpha=0.5,kind='bar',grid=True)
plt.title('季度销售频率直方图',fontsize=20)
plt.legend(loc='upper right')
代码解读

2.1.1定性数据的分布分析
对于定性变量来说,
它们的主要特征在于有限且明确的不同取值。
为了更好地理解这些数据,
我们通常会按照这些数值之间的关系进行分类和整理。
这种分类有助于我们识别出数据中的潜在模式和趋势。
饼图中的每个扇区代表不同类别的占比或出现频率;按照定性变量的不同类别划分各个扇区,并使各个扇区的大小与其对应的类别出现频率呈正相关
cat_dish_profit = pd.read_excel('data/catering_dish_profit.xls',header=0,index_col=0)
cat_dish_profit
代码解读

# 饼图
x = cat_dish_profit['盈利']
labels = cat_dish_profit['菜品名']
plt.figure(figsize=(8,6))
plt.pie(x, # 数据
labels=labels, # 标签
startangle=90 # 旋转角度
)
plt.title('菜品销量分布饼图',fontsize=20)
plt.axis('equal') # 通过改变轴的限制来设置相等的缩放(例如,让圆变成圆)
# https://matplotlib.org/stable/api/_as_gen/matplotlib.pyplot.axis.html?highlight=axis#matplotlib.pyplot.axis
代码解读

- 条形图
条形图的高度 代表每一类型的百分比或频数,宽度没有意义
# 条形图
x = cat_dish_profit['菜品名']
y = cat_dish_profit['盈利']
plt.figure(figsize=(8,8))
plt.bar(x,y)
plt.xlabel('菜品',fontsize=20)
plt.ylabel('销售量',fontsize=20)
plt.title('菜品的销量分布(条形图)',fontsize=20)
代码解读

2.2 对比分析
对比分析主要是通过将两个相互关联的指标进行对比,并从数量上加以展示和说明的一种方法。这种方法主要应用于指标间的横向与纵向对比以及时间序列上的详细分析。在实施对比分析时,选择合适的对比标准至关重要。
2.2.1 绝对数比较
利用绝对数进行对比,从而寻找差异

如上图,它们之间的大小关系就是通过绝对数来表现的。
2.2.2 相对数比较
它是通过两个相关指标之间的对比计算得出的,并用于衡量客观现象之间相互关联的程度 的综合指标。根据研究目标以及对比的基础不同,相对数可以分为若干种类。
结构相对指标是将同一现象中各组总量与其全部总量对比计算出的比重指标,在统计学中用于描述总体内部构成情况
用于同一统计总体内部不同组成部分的数值进行比较分析, 以反映各组成部分所占比例关系, 如人口性别比
比较相对指标 用于在同一时空范围内对属性一致的两个指标数值进行对比分析,以反映同类现象在不同空间条件下的数量变化情况。例如,在不同地区间的商品价格水平对比分析
-
强度相对指标
强度相对指标是用来衡量同一时期内不同性质但存在一定关联性的总量指标之间的对比关系的一种统计指标。它被用来反映现象间的强度水平、密度程度以及普遍状况。例如,在经济分析中经常使用的如人均GDP就是一个典型的强度相对指标。 -
计划完成程度指标 将某一时段的实际完成数量与计划数量进行对比,并通过该比值来衡量或评估计划的执行效果
-
动态比较指标
用于比较同一现象在不同时期的指标数值之间的差异,并衡量其发展轨迹及其变动程度。例如:发展速度
根据各部室的销售额数据进行分析,在这段时间内通过计算比较相对指标和动态相对指标来研究各个部门之间的差异变化情况。
cat_dish_sale = pd.read_excel('data/dish_sale.xls',index_col=0) # 各部门的销售数据
代码解读

# 比较相对数与动态相对数
plt.figure(figsize=(8,8))
plt.plot(cat_dish_sale.index,cat_dish_sale['A部门'],'ko-',label='A部门')
plt.plot(cat_dish_sale.index,cat_dish_sale['B部门'],'r*--',label='B部门')
plt.plot(cat_dish_sale.index,cat_dish_sale['C部门'],'bx-.',label='C部门')
plt.legend(loc='best')
plt.ylabel('销售额(万元)',fontsize=15)
plt.title('各部门销售额对比分析',fontsize=20)
代码解读

以B部门各年份的销售数据为例,
plt.figure(figsize=(8,8))
plt.plot(cat_dish_b_sale.index,cat_dish_b_sale['2014年'],'ko-',label='2014年')
plt.plot(cat_dish_b_sale.index,cat_dish_b_sale['2013年'],'r*-',label='2013年')
plt.plot(cat_dish_b_sale.index,cat_dish_b_sale['2012年'],'bx-',label='2012年')
plt.legend(loc='best')
plt.xlabel('月份',fontsize=15)
plt.ylabel('销售额(万元)',fontsize=15)
plt.title('B部门不同年份销售额变化',fontsize=20)
代码解读

经过深入分析后发现:三个部门的销售额均呈现下降趋势;其中A部门和C部门的变化较小……B部门则表现出较为显著的下降趋势。
2.3统计量分析
基于统计指标对定量数据进行描述分析,通常会围绕集中趋势和离散程度两大维度展开分析
2.3.1 集中趋势
平均水平指标是对个体集中趋势的度量,使用最广泛的是均值、中位数
- 用于体现各组成部分在均值中的重要权重, 加权均质是一个合适的选择。
- 然而由于其高度敏感性, 在实际应用中通常采用中位数或截断平均作为集中趋势的度量指标。
- 截断平均 是剔除高、低极端数值后的平均计算结果。
2.3.2 离中趋势
离中趋势是指衡量单个数据点偏离平均值的程度。主要采用的标准差(方差)和四分位间距作为常用的衡量工具。
- 极差 对极端值非常敏感的同时未考虑数据分布情况
- 标准差 用于衡量数据与均值之间的偏离程度
- 变异系数 作为标准差与均值比率反映了数据离散程度,在比较不同度量单位或波动幅度的数据集时具有特殊用途
- 四分位数间距 即IQR=Q_U-Q_L代表了数据中间一半观测值的范围,Q_L为下四分位数,Q_U为上四分位数.该指标数值越大则表明数据分布越分散
以餐饮销量统计量为例,
cat_sale = cat_sale[(cat_sale > 400) & (cat_sale < 5000)] # 过滤异常数据
statistics = cat_sale.describe()
statistics.loc['range'] = statistics.loc['max'] - statistics.loc['min'] # 极差
statistics.loc['var'] = statistics.loc['std'] / statistics.loc['mean'] # 变异系数
statistics.loc['dis'] = statistics.loc['75%'] - statistics.loc['25%'] # 四分位距
代码解读

2.4 周期性分析
周期性分析旨在考察某个变量是否随着时间的变化呈现出特定的周期性变化特征。
长时距的时间序列呈现明显的年度循环和季节循环特征;短时距的时间序列则主要表现出月度循环、周度循环以及每日甚至小时级别的循环特性。
以单日用电量数据为样本进行分析,
研究对象为正常用户的用电行为特征。
df_normal = pd.read_csv('data/user.csv',index_col=0) # 日用电量
df_normal.head()
代码解读

plt.figure(figsize=(8,8))
plt.plot(df_normal.index,df_normal['Eletricity'])
plt.xlabel("日期",fontsize=15)
# 设置x轴刻度间隔
x_major_locator = plt.MultipleLocator(7) # 每隔7个数设置
ax = plt.gca() # 获得当前轴
ax.xaxis.set_major_locator(x_major_locator)
plt.ylabel('每日电量',fontsize=15)
plt.title('正常用户电量趋势',fontsize=20)
代码解读

窃电用户
df_steal = pd.read_csv('data/Steal user.csv',index_col=0)
代码解读

plt.figure(figsize=(8,8))
plt.plot(df_steal.index,df_steal['Eletricity'])
plt.ylabel('电量',fontsize=15)
# 设置x轴间隔
x_major_locator = plt.MultipleLocator(7)
ax = plt.gca()
ax.xaxis.set_major_locator(x_major_locator)
plt.xlabel('月份',fontsize=15)
plt.title('窃电用户的电量趋势',fontsize=20)
代码解读

正常用户与窃电用户的用电量呈现出一定的周期性规律,并且其周期长度为一周;窃电用户的日均用电量逐步减少的趋势逐渐显现。
2.5 贡献度分析
贡献度分析又被认为是帕累托分析,在其核心则是帕累托法则这一理论基础之上形成了系统的分析框架相同的资源投入放置于不同位置会产生差异明显的效益
同样的情况下将相同的食物原料投入厨房与后方的配菜区域将会导致产出层次的巨大差异相同的资源投入放置于不同位置会产生差异明显的效益


cat_dish_profit['盈利占比'] = round(cat_dish_profit['盈利'] / cat_dish_profit['盈利'].sum(),2)
cat_dish_profit['累计占比'] = cat_dish_profit['盈利占比'].cumsum()
代码解读

plt.figure(figsize=(8,8))
cat_dish_profit['盈利'].plot(kind='bar')
plt.xlabel('菜品名',fontsize=15)
plt.ylabel('盈利(元)',fontsize=15)
cat_dish_profit['累计占比'].plot(style='ro-.',secondary_y=True,linewidth=2) # secondary_y=True设置双索引
plt.ylabel('盈利(比例)',fontsize=15)
# 添加注释
plt.annotate(format(cat_dish_profit['累计占比'][6],'.2%'), # 注释字符
xy=(6,cat_dish_profit['累计占比'][6]), # 要注释的位置
xytext=(6,cat_dish_profit['累计占比'][6] * 0.9), # 注释的位置
arrowprops =dict(arrowstyle="->", connectionstyle="arc3,rad=.2") # 指定箭头样式
)
代码解读

2.6 相关性分析
考察连续变量之间线性相关程度 的强度和变化趋势,并采用合适的统计指标来表示这一过程的过程被称为相关性分析
2.6.1 绘制散点图
识别两个变量之间是否存在线性相关关系最为直接的方式是绘制散点图。 seaborn中绘制散点图
2.6.2 绘制散点图矩阵
当需要评估多个变量之间的关联性时(原文:"需要同时考察" → "当需要评估"),借助散点图矩阵scatter_matrix生成多变量之间的散点图矩阵(原文:"利用...来同时绘制" → "借助...生成"),能够直观地识别各变量之间的相关性(原文:"从而快速发现" → "能够直观地识别")。
# 导入模块,注意第二个和第三个都需要
import pandas as pd
from pandas.plotting import scatter_matrix
import matplotlib.pyplot as plt
from sklearn.datasets import load_iris
X, y = load_iris(return_X_y=True)
iris_df = pd.DataFrame(X, columns=load_iris().feature_names)
# 下面这句是关键,scatter_matrix()方法
scatter_matrix(iris_df, c=y, figsize=(15, 15),
marker='o', hist_kwds={'bins': 20},
s=60, alpha=.8)
plt.show()
代码解读

这里只展示了散点图矩阵的画法,在回归问题中容易发现相关关系。
2.6.3 计算相关系数
可以使用度量工具来定量评估变量间的直线型关联程度;在统计分析中广泛采用的方法包括皮尔逊(Pearson)相关系数、斯皮尔曼(Spearman)等方法以及回归模型中的决定系数。
Pearson相关系数要求研究对象的连续变量数据需遵循正态分布规律,并要求两个变量间必须具备明确的线性关系才能达到完全的相关程度。对于不服从正态分布的数据、分类数据或有序类别型数据等非连续型数据而言,则应采用Spearman秩相关系数进行分析;只要两个研究指标间存在明确的严格单调递增或递减函数对应关系,则可判定其存在完全程度上的Spearman相关关联。其中度量指标是反映变量间关联程度的重要统计量指标,在回归分析中通常以符号r表示其强度;而衡量这种关系强弱程度的具体数值指标则是r^2值。观察发现,在回归模型中r^2值越接近于1,则表明自变量x对因变量y的变化所做出的解释力度越大;相反地,在回归模型中若r^2值接近于0,则说明自变量x对因变量y的变化所做出的影响解释力度则较弱。
通过分析不同菜品的日销售情况...可得各组别间的显著关联性。主要涉及替补和互补类的配餐组合以及相互独立的搭配方式。
cat_sale_all = pd.read_excel('data/catering_sale_all.xls',index_col=0) # 不同菜品的日销售量数据
cat_sale_all.head()
代码解读

cat_sale_all.corr() # 相关系数矩阵
代码解读

# 显示百合酱蒸凤爪与其他菜品的相关关系
cat_sale_all.corr()['百合酱蒸凤爪']
代码解读

通过查看相关系数数据可知:一部分菜肴彼此间具有互补性特征,而另一部分菜肴则彼此间没有任何关联
如果您觉得我的回答对您有帮助,请感谢您的支持与鼓励!您的认可对我来说意义重大。如果您愿意 mutual follow,请在下方评论区留下您的足迹!

