数据探索阶段——对样本数据集的结构和规律进行分析

        # 整体结构为《python数据分析与挖掘实战》第三章内容,在其代码内容及演示上有所修改及补充。

        # 具体问题具体分析,请结合实际情况食用

前言

        在收集到初步的样本数据之后,接下来该考虑的问题有:

        (1)样本数据集的数量和质量是否满足模型构建的要求。

        (2)是否出现从未设想过的数据状态。

        (3)是否有明显的规律和趋势。

        (4)各因素之间有什么样的关联性。

        解决方案:检验数据集的数据质量、绘制图表、计算某些特征量等,对样本数据集的结构和规律进行分析。

        从数据质量分析和数据特征分析两个角度出发。

3.1 数据质量分析

        数据质量分析师数据预处理的前提,是数据挖掘分析结论有效性准确性的基础。

        主要任务是检查数据中是否存在脏数据,包括以下内容:

        (1)缺失值

        (2)异常值

        (3)不一致的值

        (4)重复数据及含有特殊符号(#、¥、*等)的数据

 3.1.1 缺失值分析

        产生原因:(1)信息无法获取;(2)信息被遗漏;(3)属性值不存在(如未婚者的配偶姓名)。

        影响:(1)丢失有用信息;(2)模型不确定性更加显著;(3)建模混乱,输出不可靠。

        分析:含有缺失值属性的个数,每个属性的未缺失数、缺失数与缺失率等。

        处理:删除、对可能值进行插补或不处理(4.1.1节)

3.1.2 异常值(离群点)分析

(1)简单统计量分析

        最大值、最小值。

(2)3σ原则

         如果数据服从正态分布:异常值被定义为一组测定值中与平均值的偏差超过3倍标准差的值。

        正态分布假设下,距离平均值3σ之外的值出现的概率为P(|x-μ|>3σ)≤0.003,属于极个别的小概率事件。

        如果数据不服从正态分布,也可以用远离平均值的多少倍标准差来描述。

(3)箱型图分析

        箱型图识别异常值的结果比较客观,在识别异常值方面有一定优越性。

                

import pandas as pd

# 读取餐饮数据
file_path = r'D:\pyproject\data_analysis_mining\01-数据和代码\chapter3\demo\data\catering_sale.xls'
data = pd.read_excel(file_path, index_col=u'日期')  # 指定日期作为索引列
data_describe = data.describe()
print(data_describe)
                销量
count   200.000000
mean   2755.214700
std     751.029772
min      22.000000
25%    2451.975000
50%    2655.850000
75%    3026.125000
max    9106.440000

        其中count是非空值数,len(data)得出的数据条是201,因此缺失值为1。

import pandas as pd
import matplotlib.pyplot as plt

# 读取餐饮数据
file_path = r'D:\pyproject\data_analysis_mining\01-数据和代码\chapter3\demo\data\catering_sale.xls'
data = pd.read_excel(file_path, index_col=u'日期')  # 指定日期作为索引列
data_describe = data.describe()
print(data_describe)

# ----------------------------------------------------------------------
# 制作箱型图
plt.rcParams['font.sans-serif'] = ['SimHei']  # 正常显示中文
plt.rcParams['axes.unicode_minus'] = False  # 正常显示负号

plt.figure()    # 建立图像
p = data.boxplot(return_type='dict')  # DataFrame的方法画箱型图,返回字典格式
x = p['fliers'][0].get_xdata()  # 'fliers' 为异常值标签
y = p['fliers'][0].get_ydata()
y.sort()    # 从小到大排序

# 用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]))
plt.show()


        结合业务,将4065.2、4060.3、865.0归为正常值,其他五点归为异常值。

        最后确定过滤规则:日销量在400以下5000以上则属于异常数据,编写过滤程序(写个判断就行),进行后续处理。

3.1.3 一致性分析

        主要发生在数据集成的过程中,可能是重复存放的数据未能进行一致性更新造成的。

3.2 数据特征分析

3.2.1 分布特征

        对于定量数据:频率分布表、频率分布直方图、茎叶图。

        对于定性分类数据:饼图、条形图。

1.定量数据的分布分析

        步骤:1)求极差;2)决定组距与组数;3)决定分点;4)列出频率分布表;5)绘制频率分布直方图。

        遵循原则:1)各组之间必须互相排斥;2)各组必须将所有的数据包含在内;3)各组的组宽最好相等。

        依旧以3.1.2的数据源为实例(下载的配套数据集没找到书上的数据):

        # 注:书上这部分没有列代码,因此实现过程可能略有不同

"""
数据集为定量数据
通过以下步骤进行分布分析
1)求极差
2)决定组距与组数
3)决定分点
4)列出频率分布表
5)绘制频率分布直方图
"""
import pandas as pd
import math
import matplotlib.pyplot as plt

# 调整df列宽
pd.set_option('display.unicode.ambiguous_as_wide', True)
pd.set_option('display.unicode.east_asian_width', True)

file_path = r'D:\pyproject\data_analysis_mining\01-数据和代码\chapter3\demo\data\catering_sale.xls'
data = pd.read_excel(file_path, index_col=u'日期')
# 过滤
data = data[(data[u'销量'] > 400) & (data[u'销量'] < 5000)]
statistics = data.describe()  # 保存基本统计量
# 1)求极差
statistics.loc['range'] = statistics.loc['max'] - statistics.loc['min']  # 极差=3200.200000

print(statistics)

# 2)分组
# 根据业务,取组距为500
# 组数=(极差/组距)+1,这里书上有误
group_num = math.ceil((3200.2 / 500) + 1)
print(f'组数为:', group_num)  # 8
# 3)决定分点
# 分布区间
start, end = 0, 500
for i in range(group_num):
    if i in range(group_num)[:-2]:
        print(f'[{start}, {end})', end=',')
    else:
        print(f'[{start}, {end})')
    start += 500
    end += 500
'''
[0, 500),[500, 1000),[1000, 1500),[1500, 2000),[2000, 2500),
[2500, 3000),[3000, 3500),[3500, 4000)
'''
# 绘制频率分布表
start, end = 0, 500
fre_table = pd.DataFrame(data=None, columns=['组段', '组中值', '频数', '频率'])
for i in range(group_num + 1):
    group_segment = f'[{start}, {end})'  # 组段
    median = sum([start, end]) // 2  # 中间值
    f1 = len(data[(data[u'销量'] >= start) & (data[u'销量'] < end)])  # 频数
    f2 = f1 / len(data)
    f2 = '{:.2f}%'.format(f2 * 100)  # 频率
    fre_table.loc[i + 1] = [group_segment, median, f1, f2]
    start += 500
    end += 500
print(fre_table)
'''
           组段  组中值  频数    频率
1      [0, 500)     250     0   0.00%
2   [500, 1000)     750     1   0.51%
3  [1000, 1500)    1250     0   0.00%
4  [1500, 2000)    1750     1   0.51%
5  [2000, 2500)    2250    53  27.18%
6  [2500, 3000)    2750    87  44.62%
7  [3000, 3500)    3250    44  22.56%
8  [3500, 4000)    3750     7   3.59%
9  [4000, 4500)    4250     2   1.03%
'''

# ----------------------------------------------------------------------
# 4)制作箱频率分布直方图
plt.rcParams['font.sans-serif'] = ['SimHei']  # 正常显示中文
plt.rcParams['axes.unicode_minus'] = False  # 正常显示负号
plt.figure(figsize=(10, 6))
x = fre_table['组段'].tolist()
y = fre_table['频数'].tolist()
plt.bar(x, y)
plt.title('销售额频率分布直方图')
plt.show()

        # 为了方便这里绘制的是频数分布直方图

2.定性数据的分布特征

        采用饼图、条形图描述定性变量的分布

import pandas as pd
import matplotlib.pyplot as plt

data = pd.read_excel(r'D:\pyproject\data_analysis_mining\01-数据和代码\chapter3\demo\data\catering_sale_all.xls')
data = data.dropna()    # 去除缺失值
labels = data.columns[1:]
sizes = []
for dish in data.columns[1:]:
    size = sum(data[dish].tolist())
    sizes.append(size)
print(sizes)
plt.rcParams['font.sans-serif'] = ['SimHei']  # 正常显示中文
plt.rcParams['axes.unicode_minus'] = False  # 正常显示负号
plt.pie(
    x=sizes,
    labels=labels,
    autopct="%.0f%%",
)
plt.title('菜品销售分布(饼图)')
plt.show()
# -------------------------------------------------------------
# 条形图
plt.title('菜品销售分布(条形图))')
plt.bar(
    x=labels,
    height=sizes
)
plt.show()

3.2.2 对比分析

        适用于指标间的横纵向比较、时间序列的比较分析。

        主要有两种形式:(1)绝对数比较;(2)相对数比较

        一般为组合折线图。

3.2.3 统计量分析

1.集中趋势度量

        均值、中位数、众数。

2.离中趋势度量

        极差、标准差、变异系数、四分位数间距

# -*- coding: utf-8 -*-

import pandas as pd

catering_sale = r'D:\pyproject\data_analysis_mining\01-数据和代码\chapter3\demo\data\catering_sale.xls'
data = pd.read_excel(catering_sale, index_col=u'日期')
data = data[(data[u'销量'] > 400) & (data[u'销量'] < 5000)]
statistics = data.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%']

print(statistics)

count   195.000000
mean   2744.595385
std     424.739407
min     865.000000
25%    2460.600000
50%    2655.900000
75%    3023.200000
max    4065.200000
range  3200.200000
var       0.154755
dis     562.600000

3.2.4 周期性分析

        一般为时间序列数据,表示为折线图。

        pass

3.2.5 贡献度分析

        贡献度分析原理是帕累托法则,又称20/80定律。

        对于餐饮企业来讲,应用贡献度分析可以重点改善某菜系盈利最高的前80%的菜品,或重点发展综合影响最高的80%的部门。

# -*- coding: utf-8 -*-
import pandas as pd
import matplotlib.pyplot as plt

# 初始化plt参数
plt.rcParams['font.sans-serif'] = ['SimHei']  # 正常显示中文
plt.rcParams['axes.unicode_minus'] = False  # 正常显示负号
# -----------------------------------------------------------------------
# 准备数据源
data = pd.read_excel(
    r'D:\pyproject\data_analysis_mining\01-数据和代码\chapter3\demo\data\catering_dish_profit.xls',
    index_col='菜品名')
data = data['盈利'].copy()
# 降序排序
data.sort_values(ascending=False)
print(data)
# -----------------------------------------------------------------------
# 绘制图像
plt.figure(figsize=(10, 8))
data.plot(kind='bar')
plt.xlabel('菜品名')
plt.ylabel('盈利(元)')
# 求盈利比例=累计销售额/总销售额
p = data.cumsum() / data.sum()
p.plot(color='r', secondary_y=True, style='-o', linewidth=2)
# 增加注释
plt.annotate(
    text=format(p[6], '.4%'),   # 注释文本内容
    xy=(6, p[6]),   # 被注释的坐标点
    xytext=(6*0.9, p[6]*0.9),   # 注释文字的坐标位置
    arrowprops=dict(arrowstyle='->', connectionstyle='arc3, rad=.2')    # 箭头参数,参数类型为字典dict
)
plt.ylabel('盈利(比例)')
plt.show()

        由上图可知,菜品A1-A7占菜品种类数的70%,总盈利额占该月盈利额的85.0033%。根据帕累托法则,应该增加对菜品A1~A7的成本投入,减少A8~A10的投入以获得更高的盈利额

        # 书上的代码写的奇奇怪怪的,计算盈利比例的时候前面还乘了个1.0,不知道是为了转换成浮点数还是啥。

        # 书上的plt.annotate那段既有位置参数又有关键字参数,看的怪怪的,这里把关键字加上去了(顺便写了下注释)。

3.2.6 相关性分析

1.直接绘制散点图

2.绘制散点图矩阵

3.计算相关系数

# -*- coding: utf-8 -*-

import pandas as pd


# 调整df列宽
pd.set_option('display.unicode.ambiguous_as_wide', True)
pd.set_option('display.unicode.east_asian_width', True)

data = pd.read_excel(r'D:\pyproject\data_analysis_mining\01-数据和代码\chapter3\demo\data\catering_sale_all.xls')
# 相关系数矩阵
print(data.corr(), end='\n')
'''
                    日期  百合酱蒸凤爪  ...  香煎罗卜糕  原汁原味菜心
日期            1.000000     -0.400896  ...   -0.259884     -0.398426
百合酱蒸凤爪   -0.400896      1.000000  ...   -0.090276      0.428316
翡翠蒸香茜饺   -0.292033      0.009206  ...    0.270276      0.020462
金银蒜汁蒸排骨 -0.272744      0.016799  ...    0.077808      0.029074
乐膳真味鸡     -0.052438      0.455638  ...   -0.030222      0.421878
蜜汁焗餐包     -0.232917      0.098085  ...    0.171005      0.527844
生炒菜心        0.121191      0.308496  ...    0.049898      0.122988
铁板酸菜豆腐   -0.404750      0.204898  ...    0.157958      0.567332
香煎韭菜饺     -0.024573      0.127448  ...    0.178336      0.049689
香煎罗卜糕     -0.259884     -0.090276  ...    1.000000      0.088980
原汁原味菜心   -0.398426      0.428316  ...    0.088980      1.000000

'''
# 只显示“百合酱蒸凤爪”与其他菜品的相关关系
print(data.corr()['百合酱蒸凤爪'], end='\n')
'''
[11 rows x 11 columns]
日期             -0.400896
百合酱蒸凤爪      1.000000
翡翠蒸香茜饺      0.009206
金银蒜汁蒸排骨    0.016799
乐膳真味鸡        0.455638
蜜汁焗餐包        0.098085
生炒菜心          0.308496
铁板酸菜豆腐      0.204898
香煎韭菜饺        0.127448
香煎罗卜糕       -0.090276
原汁原味菜心      0.428316
Name: 百合酱蒸凤爪, dtype: float64
'''
# 计算“百合酱蒸凤爪”与“翡翠蒸香茜饺”的相关关系
print(data['百合酱蒸凤爪'].corr(data['翡翠蒸香茜饺']))
'''
0.009205803051836475
'''

        从结果得,如果顾客点了百合酱蒸凤爪,则和点乐膳真味鸡、生炒菜心、原汁原味菜心的相关性比较高,和点其他的相关性较低。

        补充下不同程度线性相关的说明:

        |r|<=0.3不存在线性相关

        0.3<|r|<=0.5为低度线性相关

        0.5<|r|<=0.8为显著线性相关

        |r|>0.8为高度线性相关

        (r>0为正相关,r<0为负相关)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值