精华内容
下载资源
问答
  • 数据挖掘实战
    千次阅读 多人点赞
    2021-04-03 14:09:50


    传送门:


    引言

      本文运用数据挖掘技术对市财政收入进行分析,挖掘其中的隐藏的运行模式,并对未来两年的财政收入进行预测,希望能够帮助政府合理地控制财政收支,优化财政建设,为制定相关决策提供依据。定义数据挖掘目标如下:

    • 分析、识别影响地方财政收入的关键属性
    • 预测2014年和2015年的财政收入

    本文数据挖掘主要包括以下步骤:

    1. 对原始数据进行探索性分析,了解原始属性之间的相关性
    2. 利用Lasso特征选择模型提取关键属性
    3. 建立单个属性的灰色预测模型以及支持向量模回归预测模型
    4. 使用支持向量回归预测模型得出2014年至2015年财政收入的预测值
    5. 模型评价
      在这里插入图片描述

    一、数据探索

    data.csv数据,提取码:1234
    表中各属性名称及属性说明:
    在这里插入图片描述
    在这里插入图片描述

    1.数据质量分析

    %matplotlib inline
    import pandas as pd
    import numpy as np
    import matplotlib.pyplot as plt
    import seaborn as sns
    

    在这里插入图片描述

    1.1 缺失值分析

    在这里插入图片描述
    在这里插入图片描述

    1.2 异常点分析—箱型图分析

    for column in data.columns:
        fig,ax = plt.subplots(figsize=(4,4))
        sns.boxplot(data.loc[:,column],orient='v')
        ax.set_xlabel(column)
    

    在这里插入图片描述
    会展示出每一个变量的箱型图,可直观看到有无异常点

    1.3 重复数据分析

    在这里插入图片描述

    2.数据特征分析

    2.1 描述性统计分析

    在这里插入图片描述
    可通过均值、方差、最大值、最小值看出有些数据存在较大变化。

    2.2 分布分析

      表格里面都是连续型数据,可以通过distplot来展示连续变量的直方图与连续概率密度估计

    # 画直方图与连续概率密度估计
    for column in data.columns:
        fig,ax = plt.subplots(figsize=(6,6))
        sns.distplot(data.loc[:,column],norm_hist=True,bins=20)
    

    在这里插入图片描述

    2.3 相关性分析

    在这里插入图片描述
    可以发现上述变量除了x11外均与y有强相关性,并且这些属性间存在多重共线性,考虑使用Lasso特征选择模型进行特征选择
      绘制相关性热力图,直观显示相关性

    # 绘制热力图
    plt.style.use('ggplot')
    sns.set_style('whitegrid')
    plt.subplots(figsize=(10,10))
    sns.heatmap(data.corr(method='pearson'),
                cmap='Reds',
                annot=True,   # 诸如数据
                square=True,  # 正方形网格
               fmt='.2f',   # 字符串格式代码
               yticklabels=corr.columns,  # 列标签
                xticklabels=corr.columns   # 行标签
               )
    

    在这里插入图片描述
    很明显可以看出除了x11外均与y有强相关性,并且这些属性间存在多重共线性。

    二、数据预处理

      通过上面分析,我们知道数据中没有缺失值、重复值、异常值(数据来源可靠),发现有多重共线性,我们能做的是:利用Lasso特征选择,去除特征间的多重共线性

    import pandas as pd
    import numpy as np
    from sklearn.linear_model import Lasso
    
    data = pd.read_csv('data/data.csv', header=0)
    x, y = data.iloc[:, :-1], data.iloc[:, -1]
    
    # 取alpha=1000进行特征提取
    lasso = Lasso(alpha=1000, random_state=1)  
    lasso.fit(x, y)
    # 相关系数
    print('相关系数为', np.round(lasso.coef_, 5))
    coef = pd.DataFrame(lasso.coef_, index=x.columns)
    print('相关系数数组为\n', coef)
    # 返回相关系数是否为0的布尔数组
    mask = lasso.coef_ != 0.0
    # 对特征进行选择
    x = x.loc[:, mask]
    new_reg_data = pd.concat([x, y], axis=1)
    new_reg_data.to_csv('new_reg_data.csv')
    

    三、模型构建

    1.灰色预测模型

      灰色预测算法是一种对含有不确定因素的系统进行预测的方法。在建立灰色预测模型之前,需先对原始时间序列进行数据处理,经过数据处理后的时间序列即成为生成列。灰色系统常用的数据处理方式有累加和累减两种。灰色预测以灰色模型为基础,在众多灰色模型中,GM(1,1)模型最为常用。下面展示灰色预测算法的过程及代码实现
      设特征 X ( 0 ) = { X ( 0 ) ( i ) , i = 1 , 2... , n } X^{(0)}=\{X^{(0)}(i),i=1,2...,n\} X(0)={X(0)(i),i=1,2...,n}为一非负单调原始数据序列,建立灰色预测模型如下:

    1. 首先对 X ( 0 ) X^{(0)} X(0)进行一次累加,得到一次累加序列 X ( 1 ) = { X ( 1 ) ( k ) , k = 0 , 1 , 2... , n } X^{(1)}=\{X^{(1)}(k),k=0,1,2...,n\} X(1)={X(1)(k),k=0,1,2...,n}
    2. X ( 1 ) X^{(1)} X(1)可建立下述一阶线性微分方程,即 G M ( 1 , 1 ) GM(1,1) GM1,1模型
      在这里插入图片描述
    3. 求解微分方程,即可得到预测模型
      在这里插入图片描述
    4. 由于 G M ( 1 , 1 ) GM(1,1) GM1,1模型得到的是一次累加量,将 G M ( 1 , 1 ) GM(1,1) GM1,1模型所得的数据 X ^ ( 1 ) ( k + 1 ) \hat{X}^{(1)}(k+1) X^(1)(k+1)经过累减还原 X ^ ( 0 ) ( k + 1 ) \hat{X}^{(0)}(k+1) X^(0)(k+1),即 X ( 0 ) X^{(0)} X(0)的灰色预测模型
      在这里插入图片描述
    5. 后验差检验模型精度
      在这里插入图片描述

      灰色预测法的通用性强,一般的时间序列场合都适用,尤其适合那些规律性差且不清楚数据产生机理的情况。灰色预测模型的优点是预测精度高,模型可检验、参数估计方法简单、对小数据集有很好的的预测效果;缺点是对原始数据序列的光滑度要求很高,在原始数据列光滑性较差的情况下灰色预测模型的预测精度不高,甚至通不过检验,结果只能放弃使用灰色模型进行预测。
      利用GM(1,1)灰色预测方法得到关键影响因素在2014和2015年的预测值

    # 自定义灰色预测函数
    def GM11(x0):
        # 数据处理
        x1 = x0.cumsum()  # 1-AGO序列
        z1 = (x1[:len(x1) - 1] + x1[1:]) / 2.0  # 紧邻均值(MEAN)生成序列
        z1 = z1.reshape((len(z1), 1))
        # 计算参数
        B = np.append(-z1, np.ones_like(z1), axis=1)
        Yn = x0[1:].reshape((len(x0) - 1, 1))
        [[a], [b]] = np.dot(np.dot(np.linalg.inv(np.dot(B.T, B)), B.T), Yn)
        # 还原值
        f = lambda k: (x0[0] - b / a) * np.exp(-a * (k - 1)) - (x0[0] - b / a) * np.exp(-a * (k - 2))
        # 后验差检验
        delta = np.abs(x0 - np.array([f(i) for i in range(1, len(x0) + 1)]))
        C = delta.std() / x0.std()
        P = 1.0 * (np.abs(delta - delta.mean()) < 0.6745 * x0.std()).sum() / len(x0)
        return f, a, b, x0[0], C, P  # 返回灰色预测函数、a、b、首项、方差比、小残差概率
    
    
    new_reg_data = pd.read_csv('new_reg_data.csv', header=0, index_col=0)  # 读取经过特征选择后的数据
    data = pd.read_csv('data/data.csv', header=0)  # 读取总的数据
    new_reg_data.index = range(1994, 2014)
    new_reg_data.loc[2014] = None
    new_reg_data.loc[2015] = None
    cols = ['x1', 'x3', 'x4', 'x5', 'x6', 'x7', 'x8', 'x13']
    for i in cols:
        f = GM11(new_reg_data.loc[range(1994, 2014), i].values)[0]
        new_reg_data.loc[2014, i] = f(len(new_reg_data) - 1)  # 2014年预测结果
        new_reg_data.loc[2015, i] = f(len(new_reg_data))  # 2015年预测结果
        new_reg_data[i] = new_reg_data[i].round(2)  # 保留两位小数
    
    y = list(data['y'].values)  # 提取财政收入列,合并至新数据框中
    y.extend([np.nan, np.nan])
    new_reg_data['y'] = y
    new_reg_data.to_excel('new_reg_data_GM11.xls')  # 结果输出
    print('预测结果为:\n', new_reg_data.loc[2014:2015, :])  # 预测结果展示
    

    预测完后利用GM11函数中的C、P值进行检验,衡量灰色预测模型的精度

    2.构建支持向量机回归模型

      使用支持向量回归模型对财政收入进行预测,由于数据量小,就没有设置测试集

    from sklearn.svm import LinearSVR
    import matplotlib.pyplot as plt
    
    data = pd.read_excel('new_reg_data_GM11.xls',index_col=0,header=0)  # 读取数据
    feature = ['x1', 'x3', 'x4', 'x5', 'x6', 'x7', 'x8', 'x13']  # 属性所在列
    data_train = data.loc[range(1994, 2014)].copy()  # 取2014年前的数据建模
    # 数据标准化
    data_mean = data_train.mean()
    data_std = data_train.std()
    data_train = (data_train - data_mean) / data_std  
    x_train = data_train[feature].values  # 属性数据
    y_train = data_train['y'].values  # 标签数据
    
    # 调用LinearSVR()函数
    linearsvr = LinearSVR()  
    linearsvr.fit(x_train, y_train)
    x = ((data[feature] - data_mean[feature]) / data_std[feature]).values  # 预测,并还原结果。
    data[u'y_pred'] = linearsvr.predict(x) * data_std['y'] + data_mean['y']
    # SVR预测后保存的结果
    data.to_excel('new_reg_data_GM11_revenue.xls')
    
    print('真实值与预测值分别为:\n', data[['y', 'y_pred']])
    
    fig = data[['y', 'y_pred']].plot(subplots=True, style=['b-o', 'r-*'])  # 画出预测结果图
    plt.show()
    
    
    真实值与预测值分别为:
                 y       y_pred
    1994    64.87    39.178714
    1995    99.75    85.572845
    1996    88.11    96.280182
    1997   106.07   107.925220
    1998   137.32   152.320388
    1999   188.14   189.199850
    2000   219.91   220.381728
    2001   271.91   231.055736
    2002   269.10   220.501519
    2003   300.55   301.152180
    2004   338.45   383.844627
    2005   408.86   463.423139
    2006   476.72   554.914429
    2007   838.99   691.053569
    2008   843.14   842.424578
    2009  1107.67  1086.676160
    2010  1399.16  1377.737429
    2011  1535.14  1535.140000
    2012  1579.68  1737.264098
    2013  2088.14  2083.231695
    2014      NaN  2185.297088
    2015      NaN  2535.939620
    

    在这里插入图片描述


    如果对您有帮助,麻烦点赞关注,这真的对我很重要!!!如果需要互关,请评论或者私信!
    在这里插入图片描述


    更多相关内容
  • Python数据挖掘实战课件.zip
  • MATLAB数据分析与挖掘实战完整版2015
  • 数据挖掘实战案例 总结:商业智能的巨大潜力 互联网行业 – 门户网站 传统的网站流量分析工具 简单的静态报表 后台处理,大量信息丢失 无法针对业务层面深入分析 OLAP 解决方案 18 个角度随心所欲的分析 瞬间...
  • SAS数据挖掘实战1

    2022-08-04 14:55:22
    第一章数据挖掘概述 41 数据挖掘简介 41.1 数据挖掘的产生 41.2 数据挖掘概念 52 数据挖掘原理 52.1 数据挖掘技术 52.2 数据挖掘过程 6
  • 租房数据挖掘实战代码与数据,其中数据条数为2700多条,值得初学者学习和参考。
  • 2.1 R安装10 2.2 R使用入门11 2.2.1 R操作界面11 2.2.2 RStudio窗口介绍12 2.2.3 R常用操作13 2.3 R数据分析包16
  • 数据分析与数据挖掘资料 R语言实战code 程序源代码资料 共16个章节.rar
  • python数据挖掘实战之主成分分析.pdfpython数据挖掘实战之主成分分析.pdfpython数据挖掘实战之主成分分析.pdfpython数据挖掘实战之主成分分析.pdfpython数据挖掘实战之主成分分析.pdfpython数据挖掘实战之主成分分析...
  • 一个利用机器学习做数据挖掘实战的小项目,参考书为《Python数据分析与挖掘实战》。 项目诞生的原因 本身自己就算菜鸟,熟悉github也算目的 《Python数据分析与挖掘实战》是一本很适合有一定的机器学习理论的人尝试...
  • python数据挖掘实战之主成分分析.docxpython数据挖掘实战之主成分分析.docxpython数据挖掘实战之主成分分析.docxpython数据挖掘实战之主成分分析.docxpython数据挖掘实战之主成分分析.docxpython数据挖掘实战之...
  • 数据挖掘实战—电商产品评论数据情感分析

    万次阅读 多人点赞 2021-04-10 16:24:58
    文章目录引言一、评论预处理1.评论去重2.数据清洗二、评论分词1.分词、词性标注、去除停用词2.提取含名词的评论3.绘制词云查看分词效果三、构建模型1.评论数据情感倾向分析1.1 匹配情感词...定义如下挖掘目标: 对京东


    案例数据及notebook提取码:1234


    传送门:

    引言

      本文主要针对用户在电商平台上留下的评论数据,对其进行分词、词性标注和去除停用词等文本预处理。基于预处理后的数据进行情感分析,并使用LDA主题模型提取评论关键信息,以了解用户的需求、意见、购买原因及产品的优缺点等,最终提出改善产品的建议。
    定义如下挖掘目标

    1. 对京东商城中美的电热水器的评论进行情感分析
    2. 从评论文本中挖掘用户的需求、意见、购买原因及产品的优缺点
    3. 根据模型结果给出改善产品的建议

    定义如下挖掘步骤

    1. 利用Python对京东商城中美的电热水器的评论进行爬取。
    2. 利用Python爬取的京东商城中美的电热水器的评论数据,对评论文本数据进行数据清洗、分词、停用词过滤等操作。
    3. 对预处理后的数据进行情感分析,将评论文本数据按照情感倾向分为正面评论数据(好评)和负面评论数据(差评)。
    4. 分别对正、负面评论数据进行LDA 主题分析,从对应的结果分析文本评论数据中有价值的内容。
      在这里插入图片描述

    一、评论预处理

    1.评论去重

      由语言的特点可知,在大多数情况下,不同购买者之间的有价值的评论是不会出现完全重复的,如果不同购物者的评论完全重复,那么这些评论一般都是毫无意义的。显然这种评论中只有最早的评论才有意义(即只有第一条有作用)。有的部分评论相似程度极高,可是在某些词语的运用上存在差异。此类评论即可归为重复评论,若是删除文字相近评论,则会出现误删的情况。由于相近的评论也存在不少有用的信息,去除这类评论显然不合适。因此,为了存留更多的有用语料,本节针对完全重复的语料下手,仅删除完全重复部分,以确保保留有用的文本评论信息。

    %matplotlib inline
    import pandas as pd
    import numpy as np
    import re
    import jieba.posseg as psg
    
    # 加载评论数据
    reviews = pd.read_csv('data/reviews.csv')
    

    在这里插入图片描述

    # 统计重复数据
    reviews[['content', 'content_type']].duplicated().sum()
    

    在这里插入图片描述

    # 评论去重
    reviews = reviews[['content', 'content_type']].drop_duplicates()
    # 重置索引
    reviews.reset_index(drop=True,inplace=True)
    

    在这里插入图片描述

    2.数据清洗

      通过人工观察数据发现,评论中夹杂着许多数字与字母,对于本案例的挖掘目标而言,这类数据本身并没有实质性帮助。另外,由于该评论文本数据主要是围绕京东商城中美的电热水器进行评价的,其中“京东”“京东商城”“美的”“热水器”“电热水器"等词出现的频数很大,但是对分析目标并没有什么作用,因此可以在分词之前将这些词去除,对数据进行清洗

    # 去掉评论中的数字、字母,以及“京东”“京东商城”“美的”“热水器”“电热水器"
    content = reviews['content']
    # 编译匹配模式
    pattern = re.compile('[a-zA-Z0-9]|京东|美的|电热水器|热水器|京东商城')
    # re.sub用于替换字符串中的匹配项
    content = content.apply(lambda x : pattern.sub('',x))
    

    在这里插入图片描述

    二、评论分词

    1.分词、词性标注、去除停用词

    jieba的几个分词接口:cut、lcut、posseg.cut、posseg.lcut

    # 自定义简单的分词函数
    worker = lambda s : [[x.word,x.flag] for x in psg.cut(s)]   # 单词与词性
    seg_word = content.apply(worker)
    

    在这里插入图片描述

    # 将词语转化为数据框形式,一列是词,一列是词语所在的句子id,最后一列是词语在该句子中的位置
     # 每一评论中词的个数
    n_word = seg_word.apply(lambda x: len(x)) 
    # 构造词语所在的句子id
    n_content = [[x+1]*y for x,y in zip(list(seg_word.index), list(n_word))]
    # 将嵌套的列表展开,作为词所在评论的id
    index_content = sum(n_content, [])  
    
    seg_word = sum(seg_word,[])
    # 词
    word = [x[0] for x in seg_word]
    # 词性
    nature = [x[1] for x in seg_word]
    # content_type评论类型
    content_type = [[x]*y for x,y in zip(list(reviews['content_type']),list(n_word))]
    content_type = sum(content_type,[])
    
    # 构造数据框
    result = pd.DataFrame({'index_content': index_content,
                          'word' : word,
                          'nature': nature,
                          'content_type' : content_type})
    

    在这里插入图片描述
    观察nature列得,x表示标点符号
    删除标点符号

    # 删除标点符号
    result = result[result['nature'] != 'x']
    

    在这里插入图片描述
    删除停用词

    # 删除停用词
    # 加载停用词
    stop_path = open('data/stoplist.txt','r',encoding='utf-8')
    stop = [x.replace('\n','') for x in stop_path.readlines()]
    # 得到非停用词序列
    word = list(set(word) - set(stop))
    # 判断表格中的单词列是否在非停用词列中
    result = result[result['word'].isin(word)]
    

    在这里插入图片描述

    # 构造各词在评论中的位置列
    n_word = list(result.groupby(by=['index_content'])['index_content'].count())
    index_word = [list(np.arange(0,x)) for x in n_word]
    index_word = sum(index_word,[])
    result['index_word'] = index_word
    result.reset_index(drop=True,inplace=True)
    

    在这里插入图片描述

    2.提取含名词的评论

      由于本案例的目标是对产品特征的优缺点进行分析,类似“不错,很好的产品”“很不错,继续支持”等评论虽然表达了对产品的情感倾向,但是实际上无法根据这些评论提取出哪些产品特征是用户满意的。评论中只有出现明确的名词,如机构团体及其他专有名词时,才有意义,因此需要对分词后的词语进行词性标注。之后再根据词性将含有名词类的评论提取出来
      根据得出的词性,提取评论中词性含有“n”的评论

    # 提取含名词的评论的句子id
    ind = result[[x == 'n' for x in result['nature']]]['index_content'].unique()
    # 提取评论
    result = result[result['index_content'].isin(ind)]
    # 重置索引
    result.reset_index(drop=True,inplace=True)
    

    在这里插入图片描述

    3.绘制词云查看分词效果

      进行数据预处理后,可绘制词云查看分词效果,词云会将文本中出现频率较高的‘关键词”予以视觉上的突出。首先需要对词语进行词频统计,将词频按照降序排序,选择前100个词,使用wordcloud模块中的WordCloud绘制词云,查看分词效果

    from wordcloud import WordCloud
    import matplotlib.pyplot as plt
    
    # 按word分组统计数目
    frequencies = result.groupby(by = ['word'])['word'].count()
    # 按数目降序排序
    frequencies = frequencies.sort_values(ascending = False)
    # 从文件中将图像读取为数组
    backgroud_Image=plt.imread('data/pl.jpg')
    wordcloud = WordCloud(font_path="C:\Windows\Fonts\STZHONGS.ttf",# 这里的字体要与自己电脑中的对应
                          max_words=100,            # 选择前100词
                          background_color='white',  # 背景颜色为白色
                          mask=backgroud_Image)
    my_wordcloud = wordcloud.fit_words(frequencies)
    # 将数据展示到二维图像上
    plt.imshow(my_wordcloud)
    # 关掉x,y轴
    plt.axis('off') 
    plt.show()
    
    # 将结果写出
    result.to_csv("word.csv", index = False, encoding = 'utf-8')
    

    在这里插入图片描述
    对评论数据进行预处理后,分词效果较为符合预期。其中“安装”“师傅”“售后”“物流”“服务”等词出现频率较高,因此可以初步判断用户对产品的这几个方面比较重视。

    三、构建模型

    1.评论数据情感倾向分析

    1.1 匹配情感词

      情感倾向也称为情感极性。在某商品评论中,可以理解为用户对该商品表达自身观点所持的态度是支持、反对还是中立,即通常所指的正面情感、负面情感、中性情感。由于本案例主要是对产品的优缺点进行分析,因此只要确定用户评论信息中的情感倾向方向分析即可,不需要分析每一评论的情感程度。对评论情感倾向进行分析首先要对情感词进行匹配,主要采用词典匹配的方法,本案例使用的情感词表是2007年10月22日知网发布的“情感分析用词语集 ( beta版)”,主要使用“中文正面评价”词表、“中文负面评价”“中文正面情感”“中文负面情感"词表等。将“中文正面评价”“中文正面情感”两个词表合并,并给每个词语赋予初始权重1,作为本案例的正面评论情感词表。将“中文负面评价”“中文负面情感”两个词表合并,并给每个词语赋予初始权重-1,作为本案例的负面评论情感词表。
      一般基于词表的情感分析方法,分析的效果往往与情感词表内的词语有较强的相关性,如果情感词表内的词语足够全面,并且词语符合该案例场景下所表达的情感,那么情感分析的效果会更好。针对本案例场景,需要在知网提供的词表基础上进行优化.例如“好评”“超值”“差评”“五分”等词只有在网络购物评论上出现,就可以根据词语的情感倾向添加至对应的情感词表内。将“满意”“好评”“很快”“还好”“还行”“超值”“给力”“支持”“超好”“感谢”“太棒了”“厉害”“挺舒服”“辛苦”“完美”“喜欢”“值得”“省心”等词添加进正面情感词表。将“差评”“贵”“高”“漏水”等词加入负面情感词表。
    读入正负面评论情感词表,正面词语赋予初始权重1,负面词语赋予初始权重-1。

    # 读入评论词表
    word = pd.read_csv('word.csv',header=0)
    # 读入正面、负面情感评价词
    pos_comment = pd.read_csv("data/正面评价词语(中文).txt", header=None,sep="\n", 
                              encoding = 'utf-8', engine='python')
    neg_comment = pd.read_csv("data/负面评价词语(中文).txt", header=None,sep="\n", 
                              encoding = 'utf-8', engine='python')
    pos_emotion = pd.read_csv("data/正面情感词语(中文).txt", header=None,sep="\n", 
                              encoding = 'utf-8', engine='python')
    neg_emotion = pd.read_csv("data/负面情感词语(中文).txt", header=None,sep="\n", 
                              encoding = 'utf-8', engine='python')
    
    # 合并情感词与评价词
    positive = set(pos_comment.iloc[:,0])|set(pos_emotion.iloc[:,0])
    negative = set(neg_comment.iloc[:,0])|set(neg_emotion.iloc[:,0])
    # 正负面情感词表中相同的词语
    intersection = positive & negative  
    # 去掉相同的词
    positive = list(positive - intersection)
    negative = list(negative - intersection)
    
    # 正面词语赋予初始权重1,负面词语赋予初始权重-1
    positive = pd.DataFrame({"word":positive,
                             "weight":[1]*len(positive)})
    negative = pd.DataFrame({"word":negative,
                             "weight":[-1]*len(negative)})
    posneg = positive.append(negative)
    # 将分词结果与正负面情感词表合并,定位情感词
    data_posneg = pd.merge(left=word,right=posneg,on='word',how='left')
    # 先按评论id排序,再按在评论中的位置排序
    data_posneg = data_posneg.sort_values(by = ['index_content','index_word'])
    

    在这里插入图片描述

    1.2 修正情感倾向

      情感倾向修正主要根据情感词前面两个位置的词语是否存在否定词而去判断情感值的正确与否,由于汉语中存在多重否定现象,即当否定词出现奇数次时,表示否定意思;当否定词出现偶数次时,表示肯定意思。按照汉语习惯,搜索每个情感词前两个词语,若出现奇数否定词,则调整为相反的情感极性。本案例使用的否定词表共有19个否定词,分别为:不、没、无、非、莫、弗、毋、未、否、别、六、休、不是、不能、不可、没有、不用、不要、从没、不太。读入否定词表,对情感值的方向进行修正。计算每条评论的情感得分,将评论分为正面评论和负面评论,并计算情感分析的准确率。

    # 根据情感词前面两个位置的词语是否存在否定词或双层否定词对情感值进行修正
    # 载入否定词表
    notdict = pd.read_csv("data/not.csv")
    # 处理否定修饰词
    # 构造新列,作为经过否定词修正后的情感值
    data_posneg['amend_weight'] = data_posneg['weight'] 
    data_posneg['id'] = np.arange(0, len(data_posneg))
    # 只保留有情感值的词语
    only_inclination = data_posneg.dropna()  
    # 修改索引
    only_inclination.index = np.arange(0, len(only_inclination))
    

    在这里插入图片描述

    index = only_inclination['id']
    for i in np.arange(0, len(only_inclination)):
        # 提取第i个情感词所在的评论
        review = data_posneg[data_posneg['index_content'] == only_inclination['index_content'][i]]  
        # 修改索引
        review.index = np.arange(0, len(review))
        # 第i个情感值在该文档的位置
        affective = only_inclination['index_word'][i]  
        if affective == 1:
            # 情感词前面的单词是否在否定词表
            ne = sum([i in notdict['term'] for i in review['word'][affective - 1]])
            if ne == 1:
                data_posneg['amend_weight'][index[i]] = -data_posneg['weight'][index[i]]          
        elif affective > 1:
            # 情感词前面两个位置的词语是否在否定词,存在一个调整成相反的情感权重,存在两个就不调整
            ne = sum([i in notdict['term'] for i in review['word'][[affective - 1, affective - 2]]])
            if ne == 1:
                data_posneg['amend_weight'][index[i]] = -data_posneg['weight'][index[i]]
    

    在这里插入图片描述

    # 计算每条评论的情感值
    emotional_value = only_inclination.groupby(['index_content'],as_index=False)['amend_weight'].sum()
    # 去除情感值为0的评论
    emotional_value = emotional_value[emotional_value['amend_weight'] != 0]
    emotional_value.reset_index(drop=True,inplace=True)
    

    在这里插入图片描述

    1.3 查看情感分析效果

      提取正面评论与负面评论,然后分别绘制词云,来查看情感分析效果

    # 给情感值大于0的赋予评论类型pos,小于0的赋予neg
    emotional_value['a_type'] = ''
    emotional_value['a_type'][emotional_value['amend_weight'] > 0] = 'pos'
    emotional_value['a_type'][emotional_value['amend_weight'] < 0] = 'neg'
    # 查看情感分析的结果
    result = pd.merge(left=word,right=emotional_value,on='index_content',how='right')
    

    在这里插入图片描述

    # 去重
    result = result[['index_content','content_type', 'a_type']].drop_duplicates() 
    

    在这里插入图片描述

    # 混淆矩阵-交叉表
    confusion_matrix = pd.crosstab(result['content_type'],result['a_type'],margins=True)
    

    在这里插入图片描述

    # 准确率
    (confusion_matrix.iloc[0,0] + confusion_matrix.iloc[1,1])/confusion_matrix.iloc[2,2]
    

    在这里插入图片描述

    # 提取正负面评论信息
    # 得到正面评论与负面评论对应的索引
    ind_pos = list(emotional_value[emotional_value['a_type'] == 'pos']['index_content'])
    ind_neg = list(emotional_value[emotional_value['a_type'] == 'neg']['index_content'])
    # 得到正面评论与负面评论
    posdata = word[[i in ind_pos for i in word['index_content']]]
    negdata = word[[i in ind_neg for i in word['index_content']]]
    
    # 绘制正面情感词云
    # 正面情感词词云
    freq_pos = posdata.groupby(by = ['word'])['word'].count()
    freq_pos = freq_pos.sort_values(ascending = False)
    backgroud_Image=plt.imread('data/pl.jpg')
    wordcloud = WordCloud(font_path="C:/Windows/Fonts/STZHONGS.ttf",
                          max_words=100,
                          background_color='white',
                          mask=backgroud_Image)
    pos_wordcloud = wordcloud.fit_words(freq_pos)
    plt.imshow(pos_wordcloud)
    plt.axis('off') 
    plt.show()
    

    在这里插入图片描述
    由正面情感评论词云可知,“不错”“满意”“好评”等正面情感词出现的频数较高,并且没有掺杂负面情感词语,可以看出情感分析能较好地将正面情感评论抽取出来。

    # 绘制负面评论词云
    freq_neg = negdata.groupby(by = ['word'])['word'].count()
    freq_neg = freq_neg.sort_values(ascending = False)
    neg_wordcloud = wordcloud.fit_words(freq_neg)
    plt.imshow(neg_wordcloud)
    plt.axis('off') 
    plt.show()
    

    在这里插入图片描述
    由负面情感评论词云可知,“贵”“垃圾”“不好”“太坑人”等负面情感词出现的频数较高,并且没有掺杂正面情感词语,可以看出情感分析能较好地将负面情感评论抽取出来。

    # 将结果写出,每条评论作为一行
    posdata.to_csv("posdata.csv", index = False, encoding = 'utf-8')
    negdata.to_csv("negdata.csv", index = False, encoding = 'utf-8')
    

      为了进一步查看情感分析效果,假定用户在评论时不存在“选了好评的标签,而写了差评内容”的情况,比较原评论的评论类型与情感分析得出的评论类型,绘制情感倾向分析混淆矩阵,查看词表的情感分析的准确率

    在这里插入图片描述
    通过比较原评论的评论类型与情感分析得出的评论类型,基于词表的情感分析的准确率达到了89.34%,证明通过词表的情感分析去判断某文本的情感程度是有效的。

    2.使用LDA主题模型进行主题分析

    2.1 建立词典及语料库

    import pandas as pd
    import numpy as np
    import re
    import itertools
    import matplotlib.pyplot as plt
    
    # 载入情感分析后的数据
    posdata = pd.read_csv("../data/posdata.csv", encoding = 'utf-8')
    negdata = pd.read_csv("../data/negdata.csv", encoding = 'utf-8')
    
    from gensim import corpora, models
    # 建立词典
    pos_dict = corpora.Dictionary([[i] for i in posdata['word']])  # 正面
    neg_dict = corpora.Dictionary([[i] for i in negdata['word']])  # 负面
    
    # 建立语料库
    pos_corpus = [pos_dict.doc2bow(j) for j in [[i] for i in posdata['word']]]  # 正面
    neg_corpus = [neg_dict.doc2bow(j) for j in [[i] for i in negdata['word']]]   # 负面
    

    2.2 寻找最优主题数

      基于相似度的自适应最优LDA模型选择方法,确定主题数并进行主题分析。实验证明该方法可以在不需要人工调试主题数目的情况下,用相对少的迭代找到最优的主题结构。具体步骤如下:

    1. 取初始主题数k值,得到初始模型,计算各主题之间的相似度(平均余弦距离)
    2. 增加或减少k值,重新训练模型,再次计算各主题之间的相似度。
    3. 重复步骤2,直到得到最优k值。

      利用各主题间的余弦相似度来度量主题间的相似程度。从词频入手,计算它们的相似度,用词越相似,则内容越相近。
    在这里插入图片描述
    使用LDA主题模型,找出不同主题数下的主题词,每个模型各取出若干个主题词(比如前100个),合并成一个集合。生成任何两个主题间的词频向量,计算两个向量的余弦相似度,值越大就表示越相似;计算各个主题数的平均余弦相似度,寻找最优主题数。

    def cos(vector1, vector2):
        """
        计算两个向量的余弦相似度函数
        :param vector1:
        :param vector2:
        :return: 返回两个向量的余弦相似度
        """
        dot_product = 0.0
        normA = 0.0
        normB = 0.0
        for a, b in zip(vector1, vector2):
            dot_product += a * b
            normA += a ** 2
            normB += b ** 2
        if normA == 0.0 or normB == 0.0:
            return (None)
        else:
            return (dot_product / ((normA * normB) ** 0.5))
    
    
    
    def lda_k(x_corpus, x_dict):
        """
        主题数寻优
        :param x_corpus: 语料库
        :param x_dict: 词典
        :return:
        """
        # 初始化平均余弦相似度
        mean_similarity = []
        mean_similarity.append(1)
    
        # 循环生成主题并计算主题间相似度
        for i in np.arange(2, 11):
            lda = models.LdaModel(x_corpus, num_topics=i, id2word=x_dict)  # LDA模型训练
            for j in np.arange(i):
                term = lda.show_topics(num_words=50)
    
            # 提取各主题词
            top_word = []
            for k in np.arange(i):
                top_word.append([''.join(re.findall('"(.*)"', i)) for i in term[k][1].split('+')])  # 列出所有词
    
            # 构造词频向量
            word = sum(top_word, [])  # 列出所有的词
            unique_word = set(word)  # 去除重复的词
    
            # 构造主题词列表,行表示主题号,列表示各主题词
            mat = []
            for j in np.arange(i):
                top_w = top_word[j]
                mat.append(tuple([top_w.count(k) for k in unique_word]))
    
            p = list(itertools.permutations(list(np.arange(i)), 2))
            l = len(p)
            top_similarity = [0]
            for w in np.arange(l):
                vector1 = mat[p[w][0]]
                vector2 = mat[p[w][1]]
                top_similarity.append(cos(vector1, vector2))
    
            # 计算平均余弦相似度
            mean_similarity.append(sum(top_similarity) / l)
        return (mean_similarity)
    
    # 计算主题平均余弦相似度
    pos_k = lda_k(pos_corpus, pos_dict)
    neg_k = lda_k(neg_corpus, neg_dict)        
    print('正面评论主题的平均相似度',pos_k)
    print('负面评论主题的平均相似度',neg_k)
    
    # 绘制主题平均余弦相似度图形
    # 解决中文显示问题
    plt.rcParams['font.sans-serif']=['SimHei']
    # 解决负号显示问题
    plt.rcParams['axes.unicode_minus'] = False  
    fig = plt.figure(figsize=(10,8))
    ax1 = fig.add_subplot(211)
    ax1.plot(pos_k)
    ax1.set_xlabel('正面评论LDA主题数寻优',fontsize=14)
    
    ax2 = fig.add_subplot(212)
    ax2.plot(neg_k)
    ax2.set_xlabel('负面评论LDA主题数寻优', fontsize=14)
    
    正面评论主题的平均相似度 [1, 0.06, 0.0, 0.013333333333333334, 0.024, 0.013333333333333334, 0.013333333333333334, 0.02642857142857144, 0.03888888888888891, 0.0631111111111111]
    负面评论主题的平均相似度 [1, 0.06, 0.0, 0.0033333333333333335, 0.0, 0.0, 0.0038095238095238095, 0.011428571428571432, 0.012777777777777784, 0.021777777777777788]
    

    在这里插入图片描述
    由图可知,对于正面评论数据,当主题数为2或3时,主题间的平均余弦相似度就达到了最低。因此,对正面评论数据做LDA,可以选择主题数为3;对于负面评论数据,当主题数为3时,主题间的平均余弦相似度也达到了最低。因此,对负面评论数据做LDA,也可以选择主题数为3。

    2.3 评价主题分析结果

      根据主题数寻优结果,使用Python的 Gensim模块对正面评论数据和负面评论数据分别构建LDA 主题模型,设置主题数为3,经过LDA主题分析后,每个主题下生成10个最有可能出现的词语以及相应的概率。

    pos_lda = models.LdaModel(pos_corpus, num_topics = 3, id2word = pos_dict)  
    neg_lda = models.LdaModel(neg_corpus, num_topics = 3, id2word = neg_dict)  
    pos_lda.print_topics(num_words = 10)
    
    [(0,
      '0.028*"送货" + 0.024*"服务" + 0.020*"好评" + 0.016*"太" + 0.012*"速度" + 0.011*"告诉" + 0.011*"质量" + 0.011*"活动" + 0.010*"收到" + 0.010*"服务态度"'),
     (1,
      '0.128*"安装" + 0.060*"满意" + 0.045*"师傅" + 0.027*"客服" + 0.026*"不错" + 0.016*"购物" + 0.016*"人员" + 0.011*"真心" + 0.011*"态度" + 0.010*"装"'),
     (2,
      '0.029*"值得" + 0.028*"很快" + 0.023*"东西" + 0.022*"售后" + 0.021*"差" + 0.020*"信赖" + 0.016*"电话" + 0.016*"物流" + 0.015*"真的" + 0.014*"品牌"')]
    

    结果反映了美的电热水器正面评价文本中的潜在主题,主题1中的高频特征词,关注点主要是质量、服务态度、送货速度等,主要反映美的电热水器质量好,服务好等;主题2中的高频特征词,即关注点主要是师傅、安装等,主要反映美的电热水器的安装师傅服务好等;主题3中的高频特征词,即物流、很快等,主要反映京东美的电热水器产品物流快

    neg_lda.print_topics(num_words = 10)
    
    [(0,
      '0.032*"垃圾" + 0.031*"售后" + 0.030*"太" + 0.025*"安装费" + 0.022*"东西" + 0.019*"装" + 0.019*"小时" + 0.018*"收" + 0.018*"打电话" + 0.016*"烧水"'),
     (1,
      '0.142*"安装" + 0.034*"师傅" + 0.021*"客服" + 0.019*"收费" + 0.019*"不好" + 0.018*"贵" + 0.017*"慢" + 0.017*"太慢" + 0.014*"人员" + 0.012*"坑"'),
     (2,
      '0.026*"差" + 0.016*"加热" + 0.014*"漏水" + 0.011*"材料" + 0.009*"材料费" + 0.008*"只能" + 0.007*"做" + 0.007*"找" + 0.006*"实体店" + 0.006*"度"')]
    

    结果反映了美的电热水器负面评价文本中的潜在主题,主题1中的高频特征词主要关注点在安装、安装费、收费这几方面,说明可能存在安装师傅收费过高等问题;主题2中的高频特征词主要与售后、服务这几方面有关,主要反映该产品售后服务差等问题;主题3中的高频特征词主要与加热功能有关,主要反映的是美的电热水器加热性能存在问题等。
      综合以上对主题及其中的高频特征词的分析得出,美的电热水器有价格实惠、性价比高、外观好看、服务好等优势。相对而言,用户对美的电热水器的抱怨点主要体现在安装的费用高及售后服务差等方面。
    总结
    根据对京东平台上美的电热水器的用户评价情况进行LDA主题模型分析,对美的品牌提出以下两点建议:
    ①在保持热水器使用方便、价格实惠等优点的基础上,对热水器进行加热功能上的改进,从整体上提升热水器的质量。
    ②提升安装人员及客服人员的整体素质,提高服务质量,注重售后服务。建立安装费用收取的明文细则,并进行公布,以减少安装过程中乱收费的现象。适度降低安装费用和材料费用,以此在大品牌的竞争中凸显优势。

    参考于《python数据分析与挖掘实战》


    如果对您有帮助,麻烦点赞关注,这真的对我很重要!!!如果需要互关,请评论或者私信!
    在这里插入图片描述


    展开全文
  • 基础篇介绍了数据挖掘的基本原理,实战篇介绍了一个个真实案例,通过对案例深入浅出的剖析,使读者在不知不觉中通过案例实践获得数据挖掘项目经验,同时快速领悟看似难懂的数据挖掘理论。读者在阅读过程中,应充分...
  • Jupyter Notebook现在已迅速成为数据分析,机器学习的必备工具。因为它可以让数据分析师集中精力向用户解释整个分析过程。而在课程中以 Jupyter Notebook的亮相而开头,帮助同学们不断深入的进行数据分析教学,同学...
  • 数据挖掘实战—餐饮行业的数据挖掘之挖掘建模

    千次阅读 热门讨论 2021-03-31 15:02:01
    文章目录引言一、分类与预测1.常用的分类与预测算法2....数据挖掘实战—餐饮行业的数据挖掘之数据探索(EDA) 数据挖掘实战—餐饮行业的数据挖掘之数据预处理 引言   经过数据探索与数据预处理,我们得



    引言

      经过数据探索与数据预处理,我们得到了可以直接建模的数据,根据挖掘目标与数据形式我们可以建立分类与预测、聚类分析、关联规则、时序模式、离群点检测等模型,帮助企业提取数据中蕴含的商业价值。

    一、分类与预测

      对于餐饮行业,常遇到如下问题:
    在这里插入图片描述

    1.常用的分类与预测算法

    在这里插入图片描述

    2. 回归分析

      在数据挖掘环境下。自变量与因变量具有相关关系,自变量是已知的,因变量是要预测的。常见的回归模型如下:
    在这里插入图片描述
    当自变量之间出现多重共线性时,用最小二乘法估计回归系数将不准确,消除多重共线性的参数改进方法主要有岭回归和主成分回归

    3.决策树

      决策树是一种树状结构,它的每一个叶结点对应着一个分类,非叶结点对应着在某个属性上的划分。根据样本在该属性上的不同取值将划分成若干子集。对于非纯叶节点,多数类的标号给出到达这个节点的样本所属的类。构造决策树的核心问题是在每一步如何选择适当的属性对样本进行拆分。
    在这里插入图片描述

    #!usr/bin/env python
    # -*- coding:utf-8 -*-
    """
    @author: admin
    @file: ID3决策树.py
    @time: 2021/03/31
    @desc:
    """
    import pandas as pd
    from sklearn.tree import DecisionTreeClassifier, export_graphviz
    from sklearn.preprocessing import LabelEncoder
    import graphviz
    import matplotlib as mpl
    
    data = pd.read_excel('data/sales_data.xls', index_col='序号')
    
    data[data == '好'] = 1
    data[data == '高'] = 1
    data[data == '是'] = 1
    data[data != 1] = -1
    x = data.iloc[:, :3].values.astype(int)
    y = data.iloc[:, 3].values.astype(int)
    dtc = DecisionTreeClassifier(criterion='entropy')
    dtc.fit(x, y)
    
    dot_data = export_graphviz(dtc, out_file='tree.dot',
                               feature_names=['天气', '是否周末', '是否有促销'],
                               class_names=['高', '低'], filled=True,
                               rounded=True, special_characters=True)
    
    with open('tree.dot', encoding='utf-8') as f:
        dot_grapth = f.read()
    dot = graphviz.Source(dot_grapth.replace("helvetica", "MicrosoftYaHei"))   # 解决中文乱码replace("helvetica", "MicrosoftYaHei")
    dot.view()
    
    

    在这里插入图片描述

    4.人工神经网络

      使用人工神经网络模型需要确定网络连接的拓扑结构、神经元的特征和学习规则。常用来实现分类与预测的人工神经网络算法有:
    在这里插入图片描述

    import pandas as pd
    import tensorflow as tf
    from tensorflow import keras
    from tensorflow.keras import layers, Model, optimizers, losses, metrics, activations
    from tensorflow.keras.layers import Dense, Dropout, Input, Lambda
    import matplotlib as mpl
    
    data = pd.read_excel('data/sales_data.xls', index_col='序号')
    
    data[data == '好'] = 1
    data[data == '高'] = 1
    data[data == '是'] = 1
    data[data != 1] = 0
    x = data.iloc[:, :3].values.astype(int)
    y = data.iloc[:, 3].values.astype(int)
    
    
    def bpModel():
        input = Input(shape=(3,))
        x = Dense(10, activation=tf.nn.relu)(input)
        x = Dense(10, activation=tf.nn.relu)(x)
        output = Dense(1, activation='sigmoid')(x)
    
        model = Model(inputs=input, outputs=output)
        model.compile(optimizer=optimizers.Adam(learning_rate=0.01),
                      loss='binary_crossentropy',
                      metrics=['accuracy'])
        return model
    
    
    def cm_plot(y, yp):
        """
        混淆矩阵可视化
        :param y:
        :param yp:
        :return:
        """
        from sklearn.metrics import confusion_matrix
    
        cm = confusion_matrix(y, yp)
        print(cm)
        import matplotlib.pyplot as plt
        plt.matshow(cm, cmap=plt.cm.Greens)
        plt.colorbar()
    
        for x in range(len(cm)):
            for y in range(len(cm)):
                plt.annotate(cm[x, y], xy=(x, y), horizontalalignment='center', verticalalignment='center')
    
        plt.ylabel('True label')
        plt.xlabel('Predicted label')
        return plt
    
    
    bp = bpModel()
    bp.fit(x, y, epochs=1000, batch_size=10)
    y_pred = bp.predict(x)
    y_pred[y_pred >= 0.5] = 1
    y_pred[y_pred < 0.5] = 0
    
    # 可视化
    cm_plot(y, y_pred).show()
    

    在这里插入图片描述

    二、聚类分析

      在当前市场环境下,消费者需求显现出日益差异化和个性化的趋势。针对餐饮行业,常碰到以下问题:
    在这里插入图片描述
    这些问题都可以通过聚类分析来实现。

    1.常用的聚类分析算法

      聚类方法是一种无监督的学习方法。在一组未被标记的样本上,聚类根据数据自身的距离或相似度将它们划分为若干组。划分的原则是组内样本最小化而组间样本距离最大化。
    常用聚类方法:
    在这里插入图片描述
    常用聚类分析方法:
    在这里插入图片描述

    2.K-Means聚类算法

      K-Means聚类算法是典型的基于距离非层次聚类算法,在最小化误差函数的基础上将数据划分为预定的类数 K K K,采用距离作为相似性的评价指标,即认为两个对象距离越近,其相似度越大。

    2.1 算法过程

    在这里插入图片描述
      聚类的结果依赖于初始聚类中心的随机选择,有可能使得结果严重偏离全局最优分类。实际中,多次运行K-Means算法,选择误差平方和最小的聚类结果。

    2.2 数据类型与相似性的度量

      对于连续属性,要先对各属性值进行标准化,再进行距离计算。
    在这里插入图片描述
      对于文档数据,可使用余弦相似性。可先将文档数据转换成文档—词矩阵
    在这里插入图片描述

    3. 目标函数

    在这里插入图片描述
    在这里插入图片描述

    4.消费行为特征分析

      以部分餐饮客户消费行为特征数据为例,聚类分析得

    import pandas as pd
    import numpy as np
    from sklearn.cluster import KMeans
    from sklearn.preprocessing import StandardScaler
    
    # 加载数据
    data = pd.read_excel('data/consumption_data.xls', index_col='Id')
    # 连续属性标准化
    ss = StandardScaler()
    x = ss.fit_transform(data)
    
    k = 3  # 聚类中心数
    n_iterations = 500  # 聚类的最大循环次数
    kmeans = KMeans(n_clusters=k, max_iter=n_iterations, n_jobs=-1, random_state=1234)
    kmeans.fit(data)  # 训练
    
    # 统计各类别的数目
    r1 = pd.Series(kmeans.labels_).value_counts()
    # 找出聚类中心
    r2 = pd.DataFrame(kmeans.cluster_centers_)
    # 拼接,得到各聚类中心下类别的数目
    r = pd.concat([r2, r1], axis=1)
    # 重命名表头
    r.columns = list(data.columns) + ['类别数目']
    
    # 将聚类类别保存到数据中
    data = pd.concat([data, pd.Series(kmeans.labels_, index=data.index)], axis=1)
    data.to_excel('data/data_type.xls')
    

    在这里插入图片描述
      绘制聚类后的概率密度图

    import pandas as pd
    import numpy as np
    from sklearn.cluster import KMeans
    from sklearn.preprocessing import StandardScaler
    import matplotlib.pyplot as plt
    
    # 加载数据
    data = pd.read_excel('data/consumption_data.xls', index_col='Id')
    # 连续属性标准化
    ss = StandardScaler()
    x = ss.fit_transform(data)
    
    k = 3  # 聚类中心数
    n_iterations = 500  # 聚类的最大循环次数
    kmeans = KMeans(n_clusters=k, max_iter=n_iterations, n_jobs=-1, random_state=1234)
    kmeans.fit(data)  # 训练
    
    # 统计各类别的数目
    r1 = pd.Series(kmeans.labels_).value_counts()
    # 找出聚类中心
    r2 = pd.DataFrame(kmeans.cluster_centers_)
    # 拼接,得到各聚类中心下类别的数目
    r = pd.concat([r2, r1], axis=1)
    # 重命名表头
    r.columns = list(data.columns) + ['类别数目']
    print(r)
    # 将聚类类别保存到数据中
    rs = pd.concat([data, pd.Series(kmeans.labels_, index=data.index)], axis=1)
    rs.columns = list(data.columns) + ['聚类类别']
    rs.to_excel('data/data_type.xls')
    
    # 解决中文字体问题
    plt.rcParams['font.sans-serif'] = [u'simHei']
    plt.rcParams['axes.unicode_minus'] = False
    
    
    def density_plot(data1):
        p = data1.plot(kind='kde', linewidth=2, subplots=True, sharex=False)
        [p[i].set_ylabel(u'密度') for i in range(3)]
        plt.legend()
        return plt
    
    
    # 概率密度图文件名前缀
    pic_output = './data/pd'
    for i in range(k):
        density_plot(data[rs[u'聚类类别'] == i]).show()
        # density_plot(data[rs[u'聚类类别'] == i]).savefig(u'%s%s.png' %(pic_output, i))
    

    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    5.python中主要的聚类分析算法

      scikit-learn库中实现的聚类主要有:K-Means聚类、层次聚类、FCM以及神经网络聚类。主要相关函数如下表:
    在这里插入图片描述

    三、关联规则

      关联规则分析是数据挖掘中最活跃的研究方法之一,目的是在一个数据集中找到各项之间的关联关系,而这种关系并没有在数据中直接体现出来。在餐饮行业中,菜品的推荐就用到了关联规则,比如某些菜品是相互关联的,有些菜品之间是竞争关系,在顾客下单时推荐相关联的产品就可以引导顾客消费。

    1.常用的关联规则算法

    在这里插入图片描述

    2.Apriori算法

      Apriori算法的主要思想是找出存在于事务数据集中最大的频繁项集,再利用得到的最大频繁项集与预先设定的最小置信度阈值生成强关联规则。

    2.1.Apriori的性质

      频繁项集的所有非空子集一定是频繁项集。根据这一性质可以得出:向不是频繁项集 I I I的项集中添加事务 A A A,新的项集 I ∪ A I∪A IA一定不是频繁项集。

    2.2.Apriori算法实现过程

    第一步:
    找出所有频繁项集(支持度必须大于等于给定的最小支持度阈值),在这个过程中连接步与剪枝步相互融合,最终得到最大频繁项集 L k L_k Lk

    • 连接步
      连接步的目的是找到 K K K项集。对于给定的最小支持度阈值,分别对1项候选集 C 1 C_1 C1,剔除小于该阈值的项集得到1项频繁集 L 1 L_1 L1;下一步由 L 1 L_1 L1自身连接产生2项候选集 C 2 C_2 C2,剔除小于该阈值的项集得到2项频繁集 L 2 L_2 L2;再下一步由 L 2 和 L 1 L_2和L_1 L2L1连接产生3项候选集 C 3 C_3 C3,剔除小于该阈值的项集得到3项频繁集 L 3 L_3 L3,这样循环下去,直至由 L k − 1 和 L 1 L_{k-1}和L_1 Lk1L1连接产生 k k k项候选集 C k C_k Ck,剔除小于该阈值的项集得到最大频繁集 L k L_k Lk
    • 剪枝步
      剪枝步紧接着连接步,在产生候选项 C k C_k Ck的过程中起到了减小搜索空间的目的。根据Apriori的性质:频繁项集的所有非空子集也必须是频繁项集,所以不满足该性质的项集将不会存在于 C k C_k Ck中,该过程就是剪枝

    第二步:
    由频繁项集产生强关联规则。由第一步可知,未超过预定的最小支持阈值的项集已被剔除,如果剩下的这些项集又满足了预定的最小置信度阈值,那么就挖掘出了强关联规则。

    2.3.Apriori算法实现过程实例

      以餐饮行业点餐数据为例,首先先将事务数据整理成关联规则模型所需的数据结构。设最小支持度为0.2,将菜品id编号
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    3.Apriori算法—python实现

    数据集链接

    import numpy as np
    import pandas as pd
    
    
    def connect_string(x, ms):
        """
        与1项频繁集连接生成新的项集
        :param x: 项集
        :param ms:
        :return: 新的项集
        """
        x = list(map(lambda i: sorted(i.split(ms)), x))
        l = len(x[0])
        r = []
        for i in range(len(x)):
            for j in range(i, len(x)):
                if x[i][:l - 1] == x[j][:l - 1] and x[i][l - 1] != x[j][l - 1]:
                    r.append(x[i][:l - 1] + sorted([x[j][l - 1], x[i][l - 1]]))
        return r
    
    
    def find_rule(d, support, confidence, ms=u'-'):
        """
        寻找关联规则
        :param d: 数据集
        :param support: 最小支持度
        :param confidence: 最小置信度
        :param ms: 项集之间连接符号
        :return: 强关联规则以及其支持度与置信度
        """
        # 存储输出结果
        result = pd.DataFrame(index=['support', 'confidence'])
    
        # 1项集的支持度序列
        support_series = 1.0 * d.sum(axis=0) / d.shape[0]
        # 基于给定的最小支持度进行筛选,得到1项频繁集
        column = list(support_series[support_series > support].index)
    
        # 当1项频繁集个数大于1时
        k = 0
        while len(column) > 1:
            k = k + 1
            print(u'\n正在进行第%s次搜索...' % k)
            column = connect_string(column, ms)
            print(u'数目:%s...' % len(column))
            # 乘积为1表示两个项集同时发生,乘积为0表示不同发生
            sf = lambda i: d[i].prod(axis=1, numeric_only=True)  # 新一批支持度的计算函数
    
            # 创建连接数据,这一步耗时、耗内存最严重。当数据集较大时,可以考虑并行运算优化。
            d_2 = pd.DataFrame(list(map(sf, column)), index=[ms.join(i) for i in column]).T
    
            # 计算连接后的支持度
            support_series_2 = 1.0 * d_2[[ms.join(i) for i in column]].sum() / len(d)
            column = list(support_series_2[support_series_2 > support].index)  # 新一轮支持度筛选
            support_series = support_series.append(support_series_2)
    
            column2 = []
            # 遍历可能的推理,如{A,B,C}究竟是A+B-->C还是B+C-->A还是C+A-->B?
            for i in column:
                i = i.split(ms)
                for j in range(len(i)):
                    column2.append(i[:j] + i[j + 1:] + i[j:j + 1])
    
            # 定义置信度序列
            cofidence_series = pd.Series(index=[ms.join(i) for i in column2])
            # 计算置信度序列
            for i in column2:
                cofidence_series[ms.join(i)] = support_series[ms.join(sorted(i))] / support_series[ms.join(i[:len(i) - 1])]
    
            for i in cofidence_series[cofidence_series > confidence].index:  # 置信度筛选
                result[i] = 0.0
                result[i]['confidence'] = cofidence_series[i]
                result[i]['support'] = support_series[ms.join(sorted(i.split(ms)))]
    
        result = result.T.sort_values(['confidence', 'support'], ascending=False)  # 结果整理,输出
        print(u'\n结果为:')
        print(result)
        return result
    
    
    if __name__ == '__main__':
        # 加载数据
        data = pd.read_excel('../data/menu_orders.xls', header=None)
        print('转换原数据到0-1矩阵')
        ct = lambda x: pd.Series(1, index=x[pd.notnull(x)])
        b = map(ct, data.values)
        data = pd.DataFrame(list(b)).fillna(0)
        # 删除中间变脸b
        del b
    
        support = 0.2  # 最小支持度
        confidence = 0.5  # 最小置信度
    
        find_rule(data, support, confidence)
    
    转换原数据到0-1矩阵
    
    正在进行第1次搜索...
    数目:6...
    
    正在进行第2次搜索...
    数目:3...
    
    正在进行第3次搜索...
    数目:0...
    
    结果为:
           support  confidence
    e-a        0.3    1.000000
    e-c        0.3    1.000000
    c-e-a      0.3    1.000000
    a-e-c      0.3    1.000000
    c-a        0.5    0.714286
    a-c        0.5    0.714286
    a-b        0.5    0.714286
    c-b        0.5    0.714286
    b-a        0.5    0.625000
    b-c        0.5    0.625000
    a-c-e      0.3    0.600000
    b-c-a      0.3    0.600000
    a-c-b      0.3    0.600000
    a-b-c      0.3    0.600000
    

    其中,'e—a’表示e发生能够推出a发生,置信度为100%,支持度30%。搜索出的关联规则并不一定有实际意义,需要根据问题背景筛选适当的有意义的规则,并赋予合理的解释。

    四、时间序列模式

    见这个博客

    五、离群点检测

      离群点检测是数据挖掘中重要的一部分,它的任务是发现与大部分其他对象显著不同的对象。大部分数据挖掘方法都将这种差异信息视为噪声而丢弃。同时,一些噪声数据中,罕见的数据可能蕴含着更大的研究价值。

    1.离群点的成因及分类

      离群点的主要成因是:数据来源于不同的类、自然变异、数据测量和收集误差
    在这里插入图片描述

    2.离群点检测方法

    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    3.基于聚类的离群点检测方法

      聚类分析用于发现局部强相关的对象组,而异常检测用于发现不与其他对象强相关的对象。因此聚类分析也可以用于离群点检测。下面介绍两种基于聚类的离群点检测方法。

    3.1 丢弃远离其他簇的小簇

    在这里插入图片描述

    3.2 基于原型的聚类

    在这里插入图片描述
    下面使用第二种

    import numpy as np
    import pandas as pd
    
    # 参数初始化
    inputfile = '../data/consumption_data.xls'  # 销量及其他属性数据
    k = 3  # 聚类的类别
    threshold = 2  # 离散点阈值
    iteration = 500  # 聚类最大循环次数
    data = pd.read_excel(inputfile, index_col = 'Id')  # 读取数据
    data_zs = 1.0*(data - data.mean())/data.std()  # 数据标准化
    
    from sklearn.cluster import KMeans
    model = KMeans(n_clusters = k, n_jobs = 4, max_iter = iteration)  # 分为k类,并发数4
    model.fit(data_zs)  # 开始聚类
    
    # 标准化数据及其类别
    r = pd.concat([data_zs, pd.Series(model.labels_, index = data.index)], axis = 1)   # 每个样本对应的类别
    r.columns = list(data.columns) + ['聚类类别']  # 重命名表头
    
    norm = []
    for i in range(k):  # 逐一处理
      norm_tmp = r[['R', 'F', 'M']][r['聚类类别'] == i]-model.cluster_centers_[i]
      norm_tmp = norm_tmp.apply(np.linalg.norm, axis = 1)  # 求出绝对距离
      norm.append(norm_tmp/norm_tmp.median())  # 求相对距离并添加
    
    norm = pd.concat(norm)  # 合并
    
    import matplotlib.pyplot as plt
    plt.rcParams['font.sans-serif'] = ['SimHei']  # 用来正常显示中文标签
    plt.rcParams['axes.unicode_minus'] = False  # 用来正常显示负号
    norm[norm <= threshold].plot(style = 'go')  # 正常点
    
    discrete_points = norm[norm > threshold]  # 离群点
    discrete_points.plot(style = 'ro')
    
    for i in range(len(discrete_points)):  # 离群点做标记
      id = discrete_points.index[i]
      n = discrete_points.iloc[i]
      plt.annotate('(%s, %0.2f)'%(id, n), xy = (id, n), xytext = (id, n))
    
    plt.xlabel('编号')
    plt.ylabel('相对距离')
    plt.show()
    

    参考:

    • 《python分析与数据挖掘实战》

    如果对您有帮助,麻烦点赞关注,这真的对我很重要!!!如果需要互关,请评论留言或私信!
    在这里插入图片描述


    展开全文
  • 基于SAS软件的数据挖掘 SAS数据挖掘实战精简版 由浅入深 分步骤讲解清晰易懂
  • 数据挖掘实战聚类分析的资源,包括城市消费因素的数据集和k-means,k-medoids,层次聚类,Som四种聚类分析算法的代码。
  • Python数据分析与数据挖掘实战 有一次培训的讲义,仅仅用作记录,下次可以再好好复习一下。。。Python数据分析与数据挖掘实战 有一次培训的讲义,仅仅用作记录,下次可以再好好复习一下。。。
  • 【目录】 ■引言 如何找男朋友 一个具体案例 决策树行业应用 ■决策树分类算法 ■模型效果评估 ■决策树 R 实战 ■常见问题及对策
  • 【目录】 ■ 引言  几个具体案例  线性回归概念 ■ 多元线性回归算法 ■ 多元线性回归关键问题 ■ 多元线性回归R语言实战
  • icrosoft 数据分析与数据挖掘 实战案例 杨大川 dyangminesage 讲师简介 杨大川-迈思奇科技有限公司CT0 微软MP.2019(最有价值专家) 曾任美国硅谷 Annuncio公司首席工程师 招商迪辰产品研发部总经理 现兼任中科院客座...
  • 【目录】 ■ 引言 ■ Logistic回归算法 ■ Logistic回归关键问题 ■ Logistic回归R语言实战
  • 一个企业级数据挖掘实战项目|教育数据挖掘.pdf
  • python数据挖掘实战

    2019-01-27 17:10:09
    通过python进行数据挖掘分析,对数据进行分析预测,干货满满
  • 中科院高级数据挖掘分享课程 数据分析与数据挖掘实战案例 共28页.rar
  • 数据挖掘实战—航空公司客户价值分析

    千次阅读 多人点赞 2021-04-05 16:18:13
    文章目录引言一、数据探索分析(EDA)1.数据质量分析1.1 缺失值分析1.2 异常值分析1.3 重复数据分析2.数据特征分析2.1 描述性统计分析2.2 分布分析2.2.1 客户基本信息分布分析 引言   企业在面向客户制定运营策略与...


    案例数据及notebook百度网盘链接—提取码:1234 或者可以从我上传的资源里面找,下载不需要积分
    传送门:


    引言

      企业在面向客户制定运营策略与营销策略时,希望针对不同的客户推行不同的策略,实现精准化运营。通过客户分类,对客户群体进行细分,区分出低价值客户与高价值客户,对不同的客户群体开展不同的个性化服务,将有限的资源合理地分配给不同价值的客户,从而实现效益(利润)最大化。本文将使用航空公司客户数据,结合RFM模型,采用K-Means聚类算法,对客户进行分群,比较不同类别客户的价值,从而指定相应的营销策略。定义挖掘目标如下:

    • 借助航空公司数据对客户进行分类
    • 对不同的客户类别进行特征分析,比较不同类别客户的价值
    • 针对不同价值的客户制定相应的营销策略,为其提供个性化服务

    本文数据挖掘主要包括以下步骤:

    1. 抽取航空公司2012年4月1日至2014年3月31日的数据
    2. 对抽取的数据进行数据探索分析数据预处理,包括数据缺失值与异常值的探索分析、数据清洗特征构建标准化等操作
    3. 基于RFM模型,使用K-means算法进行客户分群
    4. 针对模型结果得到不同价值的客户,采用不同的营销手段,提供定制化服务
      在这里插入图片描述

    一、数据探索分析(EDA)

      航空公司数据属性说明如下:
    在这里插入图片描述

    %matplotlib inline
    import pandas as pd
    import numpy as np
    import missingno as mg
    import matplotlib.pyplot as plt
    import seaborn as sns
    
    # 加载数据
    air_data = pd.read_csv('data/air_data.csv',header=0,index_col=0)
    air_data.head(10)
    

    在这里插入图片描述

    1.数据质量分析

    1.1 缺失值分析

      缺失值可视化,图中的白线即为缺失值

    # 缺失值可视化
    mg.matrix(air_data)
    

    在这里插入图片描述
      利用柱状图进行缺失值可视化,柱状图的高度代表非缺失比例
    在这里插入图片描述
      定量展示每一列缺失值个数并排序

    air_data.isnull().sum().sort_values(ascending=False)
    

    在这里插入图片描述
      展示每一列的缺失值个数与缺失率以及缺失值的属性

    def missing_percentage(df):
        dtypes = df.dtypes[df.isnull().sum() != 0]
        total = df.isnull().sum().sort_values(ascending=False)[df.isnull().sum() != 0]
        percentage = total*100 / len(df)
        return pd.concat([total,percentage,dtypes],axis=1,keys=['Total','Percentage','Dtypes'])
    
    missing_percentage(air_data)
    

    ![在这里插入图片描述](https://img-blog.csdnimg.cn/202104052120

    1.2 异常值分析

      用箱型图来识别异常值,箱型图识别异常值是以四分位数与四分位距为基础,同时结合业务逻辑,因为异常值并不代表是错误值,需要结合业务来考虑异常值在不在合理的范围内。

    # 数据类别统计分析
    air_data.dtypes.value_counts()
    

    在这里插入图片描述

    # 连续型变量
    num_columns = air_data.loc[:,air_data.dtypes != object].columns
    for var in num_columns:
        fig,ax = plt.subplots(figsize=(5,5))
        sns.boxplot(air_data[var],orient='v')
        ax.set_xlabel(var)
    

    以AGE为例,很明显看出该特征有异常值,而且这个异常值对于业务来说属于噪声,应当进行删除异常值或者将异常值取为空,然后在进行补充
    在这里插入图片描述
      对每个图进行分析,分析结果如下,这个是自身对业务的认知水平基础上的分析

    FFP_TIER:会员卡级别中数据要么6要么5没有异常值
    AGE:年龄中可以看到有些大于100岁,要对这些数据进行处理
    FLIGHT_COUNT:观测窗口内的飞行次数没有小于0的值,其他不在箱子中的异常值是有价值
    BP_SUM:总基本积分没有小于0的值,其他不在箱子里面的值是有价值
    EP_SUM =EP_SUM_YR_1 +EP_SUM_YR_2 :总精英积分有1个值远高于其他值,这个我认为是有价值的异常值
    SUM_YR = SUM_YR_1 + SUM_YR_2:观测窗口的票价收入,没有低于0的,有特别高的,我认为是有价值的异常值
    SEG_KM_SUM :观测窗口的飞行里程数,没有小于0的值,有特别高,我认为是有价值的异常值
    WEIGHTED_SEG_KM : 含义未知,跟里程数有关
    AVG_FLIGHT_COUNT : 平均里程数 没有小于0的值,有特别高,我认为是有价值的异常值
    AVG_BP_SUM:平均基本积分,没有小于0的,有特别高的,我认为是有价值的异常值
    BEGIN_TO_FIRST:我猜测是第一次乘机时间至观测窗口结束时长,没有小于0的,有特别高的,我认为是有价值的异常值
    LAST_TO_END:最后一次乘机时间至观测窗口结束时长,我猜测是时间间隔类数据,没有小于0的,有特别高的,我认为是有价值的异常值
    AVG_INTERVAL : 平均乘机时间间隔,即(LAST_TO_END - BEGIN_TO_FIRST) / FLIGHT_COUNT,没有负值
    MAX_INTERVAL : 最大乘机时间间隔,没有负值
    EXCHANGE_COUNT : 积分兑换次数,没有负值
    ADD_POINT_SUM : 具体含义未知,累积积分的一种,看着没有负值,之后统计分析的时候再看一下,这个值与ADD_POINT_SUM_YR_1和ADD_POINT_SUM_YR_2有关
    Eli_Add_Point_Sum:具体含义未知,累积积分的一种,看着没有负值,之后统计分析的时候再看一下,
    Ponits_Sum : 总累积积分,看着没有小于0的,有特别高的,我认为是有价值的异常值
    Ponit_NotFlight:非乘机的积分变动次数,看着没有小于0的
    总结:AGE有异常值

    1.3 重复数据分析

    在这里插入图片描述

    2.数据特征分析

    2.1 描述性统计分析

    explore = air_data.describe().T
    # count代表非空值个数
    explore['null'] = len(air_data) - explore['count']
    # 构建缺失值个数,最大值,最小值的表格
    explore = explore[['null','min','max']]
    explore.columns = ['空值个数','最小值','最大值']
    # 按空值个数进行排序
    explore.sort_values(by='空值个数',ascending= False,inplace=True)
    

    在这里插入图片描述
    在这里插入图片描述
      从表中可以看出,有3个连续型数据列有缺失值,年龄最大值为110岁,年龄中存在异常值。在三个含缺失值列中有两个是票价(SUM_YR = SUM_YR_1 + SUM_YR_2),票价为空值的数据可能是客户不存在乘机记录造成的。票价列还存在票价为0,折扣率为0,但总飞行里程数大于0的记录。这种数据业务上可以这么理解:客户乘坐了0折机票或者机票是通过非购买的其他途径获得。

    2.2 分布分析

      从三个角度寻找客户信息的分布规律

    2.2.1 客户基本信息分布分析

      针对客户基本信息中的入会时间、性别、会员卡级别和年龄字段进行分析

    1. 入会时间—各年份入会人数变化图
    from datetime import datetime
    
    # 将时间字符串转换为日期
    ffp = air_data['FFP_DATE'].apply(lambda x : datetime.strptime(x,'%Y/%m/%d'))
    # 提取入会年份
    ffp_year = ffp.map(lambda x : x.year)
    # 统计人数
    ffp_year_count = ffp_year.value_counts()
    

    在这里插入图片描述

    # 绘制各年份入会人数趋势图
    plt.rcParams['font.sans-serif'] = [u'simHei']   # 显示中文
    plt.rcParams['axes.unicode_minus'] = False      # 解决负号问题
    
    plt.figure(figsize=(10,10))
    plt.hist(ffp_year,bins='auto',color='r')
    plt.xlabel('年份')
    plt.ylabel('入会人数')
    plt.title('各年份入会人数变化趋势图')
    plt.show()
    

    在这里插入图片描述
    可以发现入会人数大致是随着年份的增加而增加,在2012年达到顶峰。2009年与2013年与趋势不符,有可能是采样的问题,有可能是其他类似政策的问题

    1. 性别—入会性别比例图
    gender =  air_data['GENDER']
    # 统计男女比例
    gender_count = gender.value_counts()
    gender_count = gender_count/gender_count.sum()
    

    在这里插入图片描述

    plt.figure(figsize=(8,8))
    color = ['yellowgreen', 'gold']
    plt.pie(gender_count,labels=['男','女'],colors=color,autopct='%1.1f%%')
    plt.title('入会性别比例图',fontsize=20)
    plt.show()
    

    在这里插入图片描述

    1. 会员卡级别—会员卡级别统计图
    ffp_tier = air_data['FFP_TIER']
    # 会员卡级别统计
    ffp_tier_count = ffp_tier.value_counts()
    ffp_tier_count
    

    在这里插入图片描述

    plt.figure(figsize=(8,8))
    plt.hist(ffp_tier,bins='auto',color='b',alpha=0.8)
    plt.xlabel('会员卡级别',fontsize=15)
    plt.ylabel('人数',fontsize=15)
    plt.title('会员卡级别统计图',fontsize=20)
    plt.show()
    

    在这里插入图片描述
    可以看出绝大多数会员为4级会员,仅有少数5级或者6级会员

    1. 年龄
    age = air_data['AGE'].dropna()
    # 绘制箱型图
    plt.figure(figsize=(10,10))
    sns.boxplot(age,orient='v')
    plt.xlabel('会员年龄',fontsize=15)
    plt.title('会员年龄分布箱型图',fontsize=20)
    

    在这里插入图片描述
    可以看出绝大多数年龄位于30~50岁之间,还存在一个年龄大于100岁的异常数据

    2.2.2 客户乘机信息分析

      针对客户乘机信息中的观测窗口内的飞行次数,观测窗口内的总飞行公里数,观测窗口内的票价收入,平均乘机时间间隔来分析

    1. 观测窗口内的飞行次数与观测窗口内的总飞行公里数
    flight_count = air_data['FLIGHT_COUNT']
    # 统计飞行次数
    flight_count.value_counts()
    

    在这里插入图片描述

    seg_km_sum = air_data['SEG_KM_SUM']
    # 统计飞行里程数
    seg_km_sum.value_counts()
    

    在这里插入图片描述
      对观测窗口内的飞行次数与观测窗口内的总飞行公里数进行绘图

    fig,ax = plt.subplots(1,2,figsize=(16,8))
    sns.boxplot(flight_count,orient='v',ax=ax[0])
    ax[0].set_xlabel('飞行次数',fontsize=15)
    ax[0].set_title('会员飞行次数分布箱型图',fontsize=20)
    
    sns.boxplot(seg_km_sum,orient='v',ax=ax[1])
    ax[1].set_xlabel('飞行里程数',fontsize=15)
    ax[1].set_title('会员飞行里程数分布箱型图',fontsize=20)
    

    在这里插入图片描述
    通过图像可以很清晰的发现:客户的飞行次数与总飞行里程数明显分为两个群体,大部分客户集中在箱型图中的箱体中,少数客户位于箱体上方,这部分客户很可能就是高价值客户

    1. 观测窗口内的票价收入
    sum_yr = air_data['SUM_YR_1'] + air_data['SUM_YR_2']
    sum_yr.value_counts()
    

    在这里插入图片描述

    plt.figure(figsize=(10,10))
    sns.boxplot(sum_yr,orient='v')
    plt.xlabel('票价收入',fontsize=15)
    plt.title('会员票价收入分布箱型图',fontsize=20)
    

    在这里插入图片描述
    通过直方图可以发现:绝大多数的会员票价收入小于3000,客户明显被分为两个群体,箱型体上方的客户很可能是高价值客户

    1. 平均乘机时间间隔统计
    avg_interval = air_data['AVG_INTERVAL']
    avg_interval.value_counts()
    

    在这里插入图片描述

    plt.figure(figsize=(10,10))
    sns.boxplot(avg_interval,orient='v')
    plt.xlabel('平均乘机时间间隔',fontsize=15)
    plt.title('会员平均乘机时间间隔分布箱型图',fontsize=20)
    

    在这里插入图片描述

    1. 最后一次乘机时间至观测窗口时长
    last_to_end = air_data['LAST_TO_END']
    plt.figure(figsize=(8,8))
    sns.boxplot(last_to_end,orient='v')
    plt.xlabel('最后一次乘机时间至观测窗口时长',fontsize=15)
    plt.title('客户最后一次乘机时间至观测窗口时长箱型图分布',fontsize=20)
    

    在这里插入图片描述
    最后一次乘机时间至观测窗口时长越短,表示客户对航空公司越满意。时间间隔越短同时也表示该客户可能是高价值客户。并且还可以从这个属性中看到公司的发展问题,如果时间间隔短的客户越来越少,说明该公司的运营出现了问题,需要及时调整营销策略。

    2.2.3 客户积分信息分布分析

      针对客户积分信息中的积分兑换次数、总累计积分进行分析

    1. 积分兑换次数
    exchange_count = air_data['EXCHANGE_COUNT']
    # 统计积分兑换次数
    exchange_count.value_counts()
    

    在这里插入图片描述

    plt.figure(figsize=(8,8))
    plt.hist(exchange_count,bins='auto',color='b',alpha=0.8)
    plt.xlabel('积分兑换次数',fontsize=15)
    plt.ylabel('会员人数',fontsize=15)
    plt.title('会员卡积分兑换次数分布直方图',fontsize=20)
    plt.show()
    

    在这里插入图片描述
    通过图形可以看出:绝大多数兑换次数位于0~10次之间,这表明大部分客户很少进行积分兑换
    2. 总累计积分

    point_sum= air_data['Points_Sum']
    # 统计总累计积分
    point_sum.value_counts()
    

    在这里插入图片描述

    plt.figure(figsize=(10,10))
    sns.boxplot(point_sum,orient='v')
    plt.xlabel('总累计积分',fontsize=15)
    plt.title('会员总累计积分分布箱型图',fontsize=20)
    

    在这里插入图片描述
    通过箱型图可以看出:绝大多数的累积积分比较小,箱型体外的积分明显高于箱型体内的积分

    2.3 相关性分析

    corr = air_data.corr()
    # 画热力图
    fig,ax = plt.subplots(figsize=(16,16))
    sns.heatmap(corr,
               annot=True,
               square=True,
               center=0,
               ax=ax)
    plt.title("Heatmap of all the Features", fontsize = 30)
    

    在这里插入图片描述
      分析入会时间、会员卡级别、会员年龄、飞行次数、飞行里程数、观测窗口内的票价收入,平均乘机时间间隔,最近一次乘机至结束时长、积分兑换次数、总累计积分属性的相关性

    data_corr = air_data[['FFP_TIER','FLIGHT_COUNT','LAST_TO_END','SEG_KM_SUM','AVG_INTERVAL','EXCHANGE_COUNT','Points_Sum']]
    age1 = air_data['AGE'].fillna(0)
    data_corr['AGE'] = age1.astype('int64')
    data_corr['ffp_year'] = ffp_year
    data_corr['sum_yr'] = sum_yr.fillna(0)
    data_corr
    

    在这里插入图片描述

    # 计算相关性矩阵
    dt_corr = data_corr.corr(method='pearson')
    dt_corr
    

    在这里插入图片描述

    fig,ax = plt.subplots(figsize=(16,16))
    # 绘制热力图
    sns.heatmap(dt_corr,
               annot=True,
               square= True,
                center=0,
               ax=ax)
    plt.title("Heatmap of some Features", fontsize = 30)
    

    在这里插入图片描述
    通过热力图可以看出:部分属性之间存在强相关性,比如总飞行公里数与票价收入,总累计积分,飞行次数。

    二、数据预处理

      针对航空客户数据从数据清洗、属性归纳与数据变换入手进行数据预处理

    1.数据清洗

    1.1 异常值处理

      根据数据预处理我们知道了,原始数据中存在票价为空值的记录,同时存在票价最小值为0,折扣率最小值为0,总飞行公里数大于0的记录,同时年龄中存在一个大于100的记录。由于这类数据在原始数据中占比不大,这里采用丢弃处理。

    # 删除年龄中的异常值
    data = pd.read_csv('data/air_data.csv',header=0,index_col=0)
    print(data.shape)
    # 去除票价为空的记录
    data_notnull = data.loc[data['SUM_YR_1'].notnull() & data['SUM_YR_2'].notnull(),:]
    

    在这里插入图片描述

    # 只保留票价非零的,或者平均折扣率不为0且总飞行公里数大于0的记录,去除年龄大于100的记录
    index1 = data_notnull['SUM_YR_1'] !=0
    index2 = data_notnull['SUM_YR_2'] !=0
    index3 = (data_notnull['avg_discount'] !=0) & (data_notnull['SEG_KM_SUM'] >0)
    index4 = data_notnull['AGE'] >100
    
    airline = data_notnull[(index1|index2 ) & index3 & ~index4]   # 按位取反
    airline.to_csv('data_cleaned.csv')
    

    在这里插入图片描述

    1.2 缺失值处理

    在这里插入图片描述

    发现有4个类别型数据:WORK_CITY,WORK_PROVINCE ,WORK_COUNTRY ,GENDER中缺失值
    1个连续型数据:AGE有缺失值
    由前面的相关性图可以看出,年龄与其他属性的相关性低,因此这里可以采用均值填充

    data_clean['AGE'].fillna(data_clean['AGE'].mean(),inplace = True)
    

    在这里插入图片描述

    2.属性归约

      RFM模型中,消费金额(M)表示一段时间内客户购买该企业产品金额的总和。由于航空公司票价受运输距离、舱位等级等影响因素,即并不是金额越高的客户并不一定比金额低的客户价值高(长途经济舱与短途商务舱的对比)。基于航空公司业务,这个特征用一定时间内累计的飞行里程M 与客户在一定时间内乘坐舱位对应的平均折扣率C来代替。同时考虑到会员的入会时间在一定程度上能够影响客户的价值,所以在模型中增加客户关系长度L,作为区分客户的一种特征。本模型将以下5个特征作为识别客户价值的特征,即为LRFMC模型。
    在这里插入图片描述
    根据LRFMC模型,选择与LRFMC指标相关的6个属性:FFP_DATE,LOAD_TIME,FLIGHT_COUNT,AVG_DISCOUNT,SEG_KM_SUM,LAST_TO_END,删除与其不相关、弱相关或冗余属性。

    data_select = data_clean[['FFP_DATE','LOAD_TIME','LAST_TO_END', 'FLIGHT_COUNT','SEG_KM_SUM','avg_discount']]
    

    在这里插入图片描述

    3.数值变换

      构造入会时长指标,并对数据进行标准化

    # 构造L 单位为天数
    L = pd.to_datetime(data_select['LOAD_TIME']) - pd.to_datetime(data_select['FFP_DATE'])
    L = L.astype('str').str.split().str[0]   # 去掉单位
    
    # 构造LRFMC指标
    data_change = pd.concat([L,data_select.iloc[:,2:]],axis=1)
    data_change.columns = ['L','R','F','M','C']
    
    # 标准化—聚类模型基于距离
    from sklearn.preprocessing import StandardScaler
    data_scale = StandardScaler().fit_transform(data_change)
    # 保存数据
    np.savez('data_scale.npz',data_scale)
    

    在这里插入图片描述

    三、模型构建

    1.客户聚类分群

      采用Kmeans算法对客户进行聚类,基于业务逻辑,聚类为5群

    from sklearn.cluster import KMeans
    kmeans = KMeans(n_clusters=5,n_jobs=-1,random_state=1234)
    # 模型训练
    kmeans_fit = kmeans.fit(data_scale)
    # 聚类中心
    kmeans_cluster = kmeans_fit.cluster_centers_
    print('聚类中心为\n',kmeans_fit.cluster_centers_)
    # 聚类后样本的类别标签
    kmeans_label = kmeans_fit.labels_
    print('聚类后样本标签为\n',kmeans_fit.labels_)
    # 聚类后各个类别数目
    r1 = pd.Series(kmeans_label).value_counts()
    print('聚类后各个类别数目\n',r1)
    # 输出聚类分群结果
    cluster_center = pd.DataFrame(kmeans_cluster,columns=['ZL','ZR','ZF','ZM','ZC'])
    cluster_center.index = pd.DataFrame(kmeans_label).drop_duplicates().iloc[:,0]
    cluster = pd.concat([r1,cluster_center],axis=1)
    # 修改第一列列名
    list_column = list(cluster.columns)
    list_column[0] = '类别数目'
    cluster.columns = list_column
    

    在这里插入图片描述

    2.客户价值分析

      针对聚类结果进行特征分析,绘制客户分群雷达图

    import matplotlib.pyplot as plt 
    plt.rcParams['font.sans-serif'] = ['SimHei']  # 用来正常显示中文标签
    plt.rcParams['axes.unicode_minus'] = False  # 用来正常显示负号 
    
    # 客户分群雷达图
    labels = ['ZL','ZR','ZF','ZM','ZC']
    legen = ['客户群' + str(i + 1) for i in cluster_center.index]  # 客户群命名,作为雷达图的图例
    lstype = ['-','--',(0, (3, 5, 1, 5, 1, 5)),':','-.']
    kinds = list(cluster_center.index)
    # 由于雷达图要保证数据闭合,因此再添加L列,并转换为 np.ndarray
    cluster_center = pd.concat([cluster_center, cluster_center[['ZL']]], axis=1)
    centers = np.array(cluster_center)
    
    # 分割圆周长,并让其闭合
    n = len(labels)
    # endpoint=False表示一定没有stop
    angle = np.linspace(0, 2 * np.pi, n, endpoint=False)
    angle = np.concatenate((angle, [angle[0]]))
    # 绘图
    fig = plt.figure(figsize = (8,6))
    # 以极坐标的形式绘制图形
    ax = fig.add_subplot(111, polar=True)  
    # 画线
    for i in range(len(kinds)):
        ax.plot(angle, centers[i], linestyle=lstype[i], linewidth=2,label=kinds[i])
    # 添加属性标签
    ax.set_thetagrids(angle * 180 / np.pi, labels)
    plt.title('客户特征分析雷达图')
    plt.legend(legen)
    plt.show()
    

    在这里插入图片描述
    由雷达图中可知:客群1在C处最大,在F,M处的值较小,说明客群1是偏好坐高级舱的客户群(一般航班舱位等级越高,折扣系数越大)。客群2在L,R,F,M,C处都小,说明客群2是新入会员较多客户群。客群3在L处最大,在R处值较小,其他特征适中,说明客群3属于入会时间长,飞行频率高的高价值客户。客群4在F,M处最大,且在R处最小,说明客户群体4频繁乘机并且最近也有乘机记录。客群5在R处最大,在其他特征处都较小,属于入会时间短的低价值客户群。
      总结每个客户群的优势与弱势特征
    在这里插入图片描述
      根据以上特征分析,说明不同用户类别的表现特征不同。基于特征描述,我们将客户分为5个等级:重要保持客户,重要发展客户,重要挽留客户,一般客户与低价值客户
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    参考于《python数据分析与挖掘实战》


    如果对您有帮助,麻烦点赞关注,这真的对我很重要!!!如果需要互关,请评论留言或私信!
    在这里插入图片描述


    展开全文
  • 1. 大数据挖掘实战平台建设是培养云计算与大数据时代新型数据分析人才的需要。 2. 大数据挖掘实战平台建设能有力促进及推动学校及各学院科研水平,为大数据的分析及挖掘提供基础平台。 3. 该工程与实战中心的建立能...
  • python零基础学习篇课程资料-CLASSDATA_ch13_企业数据挖掘实战(更新信用评分案例注
  • R语言数据分析与数据挖掘实战随书代码
  • 数据挖掘实战(贝叶斯,神经网络和决策树)的代码以及借用共享单车的因素的数据集 使用三种分类方法来进行数据挖掘的实战,得出借用共享单车因素之间的关系。

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 52,390
精华内容 20,956
关键字:

数据挖掘实战