【笔记】python数据分析与挖掘实战


数据挖掘的基本任务包括利用分类与预测、聚类分析、关联规则、时序模式、偏差检测、智能推荐等方法,帮助企业提取数据中蕴含的商业价值,提高企业的竞争力。

数据挖掘的基本流程:

  1. 定义挖掘目标
  2. 数据采样
  3. 数据探索
  4. 数据预处理
  5. 挖掘建模
  6. 模型评价

数据探索

数据质量分析

数据质量分析是数据挖掘中数据准备过程的重要一环,是数据预处理的前提,也是数据挖掘分析结论有效性和准确性的基础。数据质量分析的主要任务是检查原始数据中是否存在脏数据,脏数据一般是指不符合要求,以及不能直接进行相应分析的数据,如缺失值、异常值、不一致的值、重复数据和含有特殊符号的值。

可以进行简单的统计分析、描述性统计等方法,也可以使用3σ原则查看数据是否符合正态分布,可以用箱线图作图查看,python中可以使用describe()函数。

数据特征分析

分布分析

分布分析能揭示数据的分布特征和分布类型。对于定量数据,欲了解其分布形式是对称的还是非对称的,发现某些特大或特小的可疑值,可通过绘制频率分布表、绘制频率分布直方图、绘制茎叶图进行直观地分析;对于定性分类数据,可用饼图和条形图直观地显示分布情况。

定量数据:求极差;决定组距和组数;决定分点;列出频率分布表;绘制频率分布直方图

对比分析

对比分析是指把两个相互联系的指标进行比较,从数量上展示和说明研究对象规模的大小,水平的高低,速度的快慢,以及各种关系是否协调。特别适用于指标间的横纵向比较、时间序列的比较分析。

  1. 绝对数分析
  2. 相对数分析:结构相对数;比例相对数;比较相对数;强度相对数;计划完成程度相对数;动态相对数

统计量分析

用统计指标对定量数据进行统计描述,常从集中趋势和离中趋势两个方面进行分析。平均水平的指标是对个体集中趋势的度量,使用最广泛的是均值和中位数还有众数;反映变异程度的指标则是对个体离开平均水平的度量,使用较广泛的是极差、标准差(方差)、变异系数、四分位间距。

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%'] # 四分位数间距

周期性分析

周期性分析是探索某个变量是否随着时间变化而呈现出某种周期变化趋势。时间尺度相对较长的周期性趋势有年度周期性趋势、季节性周期趋势,相对较短的有月度周期性趋势、周度周期性趋势,甚至更短的天、小时周期性趋势

贡献度分析

贡献度分析又称帕累托分析,它的原理是帕累托法则,又称20/80定律。同样的投入放在不同的地方会产生不同的效益。例如,对一个公司来讲,80%的利润常常来自于20%最畅销的产品,而其他80%的产品只产生了20%的利润。

data.plot(kind='bar')
p = 1.0*data.cumsum()/data.sum()
p.plot(color = 'r', secondary_y = True, style = '-o',linewidth = 2)
plt.annotate(format(p[6], '.4%'), xy = (6, p[6]), xytext=(6*0.9, p[6]*0.9), arro    wprops=dict(arrowstyle="->", connectionstyle="arc3,rad=.2")) # 添加注释,即85%处的标记。这里包括了指定箭头样式。

相关性分析

分析连续变量之间线性相关程度的强弱,并用适当的统计指标表示出来的过程称为相关分析。

可以直接绘制散点图、绘制散点图矩阵、计算相关系数

data.corr() # 相关系数矩阵,即给出了任意两款菜式之间的相关系数
data.corr()[u'百合酱蒸凤爪'] # 只显示“百合酱蒸凤爪”与其他菜式的相关系数
data[u'百合酱蒸凤爪'].corr(data[u'翡翠蒸香茜饺']) # 计算“百合酱蒸凤爪”与“翡翠蒸香茜饺”

数据预处理

数据预处理一方面是要提高数据的质量,另一方面是要让数据更好地适应特定的挖掘技术或工具。统计发现,在数据挖掘的过程中,数据预处理工作量占到了整个过程的60%

数据清洗

主要是删除原始数据集中的无关数据、重复数据,平滑噪声数据,筛选掉与挖掘主题无关的数据,处理缺失值、异常值等。

缺失值处理

  1. 删除
  2. 插补
  3. 不处理

在这里插入图片描述

# 拉格朗日插值代码
import pandas as pd
from scipy.interpolate import lagrange  # 导入拉格朗日插值函数
data[u'销量'][(data[u'销量'] < 400) | (data[u'销量'] > 5000)] = None  # 过滤异常值,将其变为空值
# 自定义列向量插值函数
# s为列向量,n为被插值的位置,k为取前后的数据个数,默认为5
def ployinterp_column(s, n, k=5):  
    y = s[list(range(n-k, n)) + list(range(n+1, n+1+k))]  # 取数  
    y = y[y.notnull()]  # 剔除空值  
    return lagrange(y.index, list(y))(n)  # 插值并返回插值结果
# 逐个元素判断是否需要插值
for i in data.columns:  
    for j in range(len(data)):    
        if (data[i].isnull())[j]:  # 如果为空即插值。      
            data[i][j] = ployinterp_column(data[i], j)

异常值处理

  1. 删除
  2. 视为缺失值
  3. 平均值修正
  4. 不处理

数据集成

需要的数据往往分布在不同的数据源中,数据集成就是将多个数据源合并存放在一个一致的数据存储(如数据仓库)中的过程。在数据集成时,来自多个数据源的现实世界实体的表达形式是不一样的,有可能不匹配,要考虑实体识别问题和属性冗余问题,从而将源数据在最低层上加以转换、提炼和集成。

实体识别:同名异义;异名同义;单位不统一

冗余属性识别:同一属性出现多次,同一属性命名不一致导致重复

数据变换

数据变换主要是对数据进行规范化处理,将数据转换成“适当的”形式,以适用于挖掘任务及算法的需要。

如简单函数变换;规范化;连续属性离散化;属性构造;小波变换

规范化

也称归一化。

(data - data.min())/(data.max() - data.min()) #最小-最大规范化
(data - data.mean())/data.std() #零-均值规范化
data/10**np.ceil(np.log10(data.abs().max())) #小数定标规范化

连续属性离散化

一些数据挖掘算法,特别是某些分类算法(如ID3算法、Apriori算法等),要求数据是分类属性形式。

连续属性的离散化就是在数据的取值范围内设定若干个离散的划分点,将取值范围划分为一些离散化的区间,最后用不同的符号或整数值代表落在每个子区间中的数据值。所以,离散化涉及两个子任务:确定分类数以及如何将连续属性值映射到这些分类值。

k = 4
d1 = pd.cut(data, k, labels = range(k))  # 等宽离散化,各个类比依次命名为0,1,2,3
#等频率离散化
w = [1.0*i/k for i in range(k+1)]
w = data.describe(percentiles = w)[4:4+k+1]  # 使用describe函数自动计算分位数
w[0] = w[0]*(1-1e-10)
d2 = pd.cut(data, w, labels = range(k))
from sklearn.cluster import KMeans  # 引入KMeans
kmodel = KMeans(n_clusters = k, n_jobs = 4)  # 建立模型,n_jobs是并行数,一般等于CPU数较好
kmodel.fit(data.reshape((len(data), 1)))  # 训练模型
c = pd.DataFrame(kmodel.cluster_centers_).sort(0)  # 输出聚类中心,并且排序(默认是随机序的)
w = pd.rolling_mean(c, 2).iloc[1:]  # 相邻两项求中点,作为边界点
w = [0] + list(w[0]) + [data.max()]  # 把首末边界点加上
d3 = pd.cut(data, w, labels = range(k))
def cluster_plot(d, k):  # 自定义作图函数来显示聚类结果  
    import matplotlib.pyplot as plt  
    plt.figure(figsize = (8, 3))  
        for j in range(0, k):    
            plt.plot(data[d==j], [j for i in d[d==j]], 'o')  
            plt.ylim(-0.5, k-0.5)  
    return plt
cluster_plot(d1, k).show()
cluster_plot(d2, k).show()
cluster_plot(d3, k).show()

属性构造

在数据挖掘的过程中,为了提取更有用的信息,挖掘更深层次的模式,提高挖掘结果的精度,我们需要利用已有的属性集构造出新的属性,并加入到现有的属性集合中

数据规约

意义:降低无效、错误数据对建模的影响,提高建模的准确性;少量且具代表性的数据将大幅缩减数据挖掘所需的时间;降低储存数据的成本。

在这里插入图片描述

# 主成分分析
from sklearn.decomposition import PCA
pca = PCA()pca.fit(data)
pca.components_ #返回模型的各个特征向量
pca.explained_variance_ratio_ #返回各个成分各自的方差百分比

数值规约:直方图;聚类;抽样;参数回归

在这里插入图片描述

挖掘建模

分类与预测

分类和预测是预测问题的两种主要类型,分类主要是预测分类标号(离散属性),而预测主要是建立连续值函数模型,预测给定自变量对应的因变量的值。

在这里插入图片描述

回归分析

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

Logistic回归

Logistic回归模型中的因变量的只有1-0(如是和否、发生和不发生)两种取值。假设在p个独立自变量x1,x2,…,xp作用下,记y取1的概率是p=P(y=1|X),取0概率是1-p,取1和取0的概率之比为p/(1-p),称为事件的优势比odds,对odds取自然对数即得Logistic变换Logit§=ln[p/(1-p)]。令Logit§=ln[p/(1-p)]=z,则p=1/(1+e-z)即为Logistic函数

from sklearn.linear_model import LogisticRegression as LR
from sklearn.linear_model import RandomizedLogisticRegression as RLR
rlr = RLR()  # 建立随机逻辑回归模型,筛选变量
rlr.fit(x, y)  # 训练模型
rlr.get_support()  # 获取特征筛选结果,也可以通过.scores_方法获取各个特征的分数
print(u'有效特征为:%s' % ','.join(data.columns[rlr.get_support()]))
x = data[data.columns[rlr.get_support()]].as_matrix()  # 筛选好特征
lr = LR()  # 建立逻辑货柜模型
lr.fit(x, y)  # 用筛选后的特征数据来训练模型
print(u'模型的平均正确率为:%s' % lr.score(x, y))  # 给出模型的平均正确率

逻辑回归本质上还是一种线性模型,因此这里的模型有效性检验本质上还是在做线性相关检验,因此,所筛选出来的变量,说明与结果具有比较强的线性相关性,然而被筛掉的变量并不一定就跟结果没有关系,因为它们之间有可能是非线性关系。对于非线性关系的变量筛选方法有决策树、神经网络等。

决策树

构造决策树的核心问题是在每一步如何选择适当的属性对样本做拆分。对一个分类问题,从已知类标记的训练样本中学习并构造出决策树是一个自上而下,分而治之的过程。

在这里插入图片描述

# 数据是类别标签,要将它转换为数据
# 用1来表示“好”“是”“高”这三个属性,用-1来表示“坏”“否”“低”
data[data == u'好'] = 1
data[data == u'是'] = 1
data[data == u'高'] = 1
data[data != 1] = -1
x = data.iloc[:,:3].as_matrix().astype(int)
y = data.iloc[:,3].as_matrix().astype(int)
from sklearn.tree import DecisionTreeClassifier as DTC
dtc = DTC(criterion='entropy')  # 建立决策树模型,基于信息熵
dtc.fit(x, y)  # 训练模型
# 导入相关函数,可视化决策树。
# 导出的结果是一个dot文件,需要安装Graphviz才能将它转换为pdf或png等格式。
from sklearn.tree import export_graphviz
from sklearn.externals.six import StringIOwith 
open("tree.dot", 'w') as f:
    f = export_graphviz(dtc, feature_names = x.columns, out_file = f)

人工神经网络

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

# 数据是类别标签,要将它转换为数据
# 用1来表示“好”“是”“高”这3个属性,用0来表示“坏”“否”“低”
data[data == u'好'] = 1
data[data == u'是'] = 1
data[data == u'高'] = 1
data[data != 1] = 0
x = data.iloc[:,:3].as_matrix().astype(int)
y = data.iloc[:,3].as_matrix().astype(int)
from keras.models import Sequential
from keras.layers.core import Dense, Activation
model = Sequential()  # 建立模型
model.add(Dense(3, 10))
model.add(Activation('relu'))  # 用relu函数作为激活函数,能够大幅提供准确度
model.add(Dense(10, 1))
model.add(Activation('sigmoid'))  # 由于是0-1输出,用sigmoid函数作为激活函数
model.compile(loss = 'binary_crossentropy', optimizer = 'adam', class_mode = 'binary')  # 编译模型。由于我们做的是二元分类,所以我们指定损失函数为binary_crossentropy,以及模式为binary
# 另外常见的损失函数还有mean_squared_error、categorical_crossentropy等,请阅读帮助文件。
# 求解方法我们指定用adam,还有sgd、rmsprop等可选
model.fit(x, y, nb_epoch = 1000, batch_size = 10)  # 训练模型,学习一千次
yp = model.predict_classes(x).reshape(len(y))  # 分类预测
from cm_plot import *  # 导入自行编写的混淆矩阵可视化函数
cm_plot(y,yp).show()  # 显示混淆矩阵可视化结果

聚类分析

与分类不同,聚类分析是在没有给定划分类别的情况下,根据数据相似度进行样本分组的一种方法。与分类模型需要使用有类标记样本构成的训练数据不同,聚类模型可以建立在无类标记的数据上,是一种非监督的学习算法。聚类的输入是一组未被标记的样本,聚类根据数据自身的距离或相似度将其划分为若干组,划分的原则是组内距离最小化而组间(外部)距离最大化。

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

K-MEANS算法

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

  1. 从N个样本数据中随机选取K个对象作为初始的聚类中心。
  2. 分别计算每个样本到各个聚类中心的距离,将对象分配到距离最近的聚类中。
  3. 所有对象分配完成后,重新计算K个聚类的中心。
  4. 与前一次计算得到的K个聚类中心比较,如果聚类中心发生变化,转过程2,否则转过程5。
  5. 当质心不发生变化时停止并输出聚类结果
k = 3  # 聚类的类别
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)  # 开始聚类
# 简单打印结果
r1 = pd.Series(model.labels_).value_counts()  # 统计各个类别的数目
r2 = pd.DataFrame(model.cluster_centers_)  # 找出聚类中心
r = pd.concat([r2, r1], axis = 1)  # 横向连接(0是纵向),得到聚类中心对应的类别下的数目
r.columns = list(data.columns) + [u'类别数目']  # 重命名表头
print(r)  # 详细输出原始数据及其类别
r = pd.concat([data, pd.Series(model.labels_, index = data.index)], axis = 1)  # 详细输出每个样本对应的类别
r.columns = list(data.columns) + [u'聚类类别']  # 重命名表头
# 绘制聚类后得概率密度图
def density_plot(data, title):  # 自定义作图函数  
    import matplotlib.pyplot as plt  
    plt.figure()  
    for i in range(len(data.iloc[0])):  # 逐列作图    
        (data.iloc[:,i]).plot(kind='kde', label = data.columns[i], linewidth = 2)  
    plt.ylabel(u'密度')  
    plt.xlabel(u'人数')  
    plt.title(u'聚类类别%s各属性的密度曲线' %title)  
    plt.legend()  
    return plt

def density_plot(data):  # 自定义作图函数  
    import matplotlib.pyplot as plt    
    p = data.plot(kind='kde', linewidth = 2, subplots = True, sharex = False)  
    [p[i].set_ylabel(u'密度') for i in range(k)]  
    plt.legend()  
    return plt

pic_output = '../tmp/pd_' #概率密度图文件名前缀
for i in range(k):  
    density_plot(data[r[u'聚类类别']==i]).savefig(u'%s%s.png' %(pic_output, i))

在这里插入图片描述

关联规则

关联规则分析也成为购物篮分析,最早是为了发现超市销售数据库中不同的商品之间的关联关系。目的是在一个数据集中找出各项之间的关联关系,而这种关系并没有在数据中直接表示出来。

在这里插入图片描述

Apriori算法

from __future__ import print_function
import pandas as pd
from apriori import *  # 导入自行编写的apriori函数
ct = lambda x : pd.Series(1, index = x[pd.notnull(x)])  # 转换0-1矩阵的过渡函数
b = map(ct, data.as_matrix())  # 用map方式执行
data = pd.DataFrame(list(b)).fillna(0)  # 实现矩阵转换,空值用0填充
del b  # 删除中间变量b,节省内存
support = 0.2  # 最小支持度
confidence = 0.5  # 最小置信度
ms = '---'  # 连接符,默认'--',用来区分不同元素,如A--B。需要保证原始表格中不含有该字符
find_rule(data, support, confidence, ms).to_excel(outputfile)  # 保存结果

时序模式

在这里插入图片描述

时间序列预处理

拿到一个观察值序列后,首先要对它的纯随机性和平稳性进行检验,这两个重要的检验称为序列的预处理。

对于纯随机序列,又称为白噪声序列,序列的各项之间没有任何相关关系,序列在进行完全无序的随机波动,可以终止对该序列的分析。白噪声序列是没有信息可提取的平稳序列。对于平稳非白噪声序列,它的均值和方差是常数,现已有一套非常成熟的平稳序列的建模方法。通常是建立一个线性模型来拟合该序列的发展,借此提取该序列的有用信息。ARMA模型是最常用的平稳序列拟合模型。对于非平稳序列,由于它的均值和方差不稳定,处理方法一般是将其转变为平稳序列,这样就可以应用有关平稳时间序列的分析方法,如建立ARMA模型来进行相应的研究。如果一个时间序列经差分运算后具有平稳性,则该序列为差分平稳序列,可以使用ARIMA模型进行分析。

平稳性的检验
  1. 时序图检验。根据平稳时间序列的均值和方差都为常数的性质,平稳序列的时序图显示该序列值始终在一个常数附近随机波动,而且波动的范围有界;如果有明显的趋势性或者周期性,那它通常不是平稳序列。
  2. 自相关图检验。平稳序列具有短期相关性,这个性质表明对平稳序列而言通常只有近期的序列值对现时值的影响比较明显,间隔越远的过去值对现时值的影响越小。随着延迟期数k的增加,平稳序列的自相关系数ρk(延迟k期)会比较快的衰减趋向于零,并在零附近随机波动,而非平稳序列的自相关系数衰减的速度比较慢,这就是利用自相关图进行平稳性检验的标准。
  3. 单位根检验。单位根检验是指检验序列中是否存在单位根,如果存在单位根就是非平稳时间序列了.

如果一个序列是纯随机序列,那么它的序列值之间应该没有任何关系,即满足γ(k)=0,k≠0这是一种理论上才会出现的理想状态,实际上纯随机序列的样本自相关系数不会绝对为零,但是很接近零,并在零附近随机波动。

平稳时间序列分析

ARMA模型的全称是自回归移动平均模型,它是目前最常用的拟合平稳序列的模型。它又可以细分为AR模型、MA模型和ARMA三大类。都可以看作是多元线性回归模型。
在这里插入图片描述

在这里插入图片描述

非平稳时间序列分析

可以分为确定性因素分解的时序分析和随机时序分析两大类。

确定性因素分解的方法把所有序列的变化都归结为4个因素(长期趋势、季节变动、循环变动和随机波动)的综合影响,其中长期趋势和季节变动的规律性信息通常比较容易提取,而由随机因素导致的波动则非常难确定和分析,对随机信息浪费严重,会导致模型拟合精度不够理想。

随机时序分析法的发展就是为了弥补确定性因素分解方法的不足。根据时间序列的不同特点,随机时序分析可以建立的模型有ARIMA模型、残差自回归模型、季节模型、异方差模型等。

  1. p阶差分: 相距一期的两个序列值之间的减法运算称为1阶差分运算。
  2. k步差分: 相距k期的两个序列值之间的减法运算称为k步差分运算.
# ARIMA模型
import pandas as pd  # 参数初始化
discfile = '../data/arima_data.xls'
forecastnum = 5  # 读取数据,指定日期列为指标,Pandas自动将“日期”列识别为Datetime格式
data = pd.read_excel(discfile, index_col = u'日期')  
# 时序图
import matplotlib.pyplot as plt
data.plot()
plt.show()  
# 自相关图
from statsmodels.graphics.tsaplots import plot_acf
plot_acf(data).show()  
# 平稳性检测
from statsmodels.tsa.stattools import adfuller as ADF
print(u'原始序列的ADF检验结果为:', ADF(data[u'销量']))  # 返回值依次为adf、pvalue、usedlag、nobs、critical values、icbest、regresults、resstore#差分后的结果
D_data = data.diff().dropna()D_data.columns = [u'销量差分']
D_data.plot() 
# 时序图
plt.show()
plot_acf(D_data).show() 
# 自相关图
from statsmodels.graphics.tsaplots import plot_pacf
plot_pacf(D_data).show() 
# 偏自相关图
print(u'差分序列的ADF检验结果为:', ADF(D_data[u'销量差分']))  # 平稳性检测
# 白噪声检验 
from statsmodels.stats.diagnostic import acorr_ljungbox
print(u'差分序列的白噪声检验结果为:', acorr_ljungbox(D_data, lags=1))  # 返回统计量和p值
from statsmodels.tsa.arima_model import ARIMA  
# 定阶
pmax = int(len(D_data)/10)  # 一般阶数不超过length/10
qmax = int(len(D_data)/10)  # 一般阶数不超过length/10
bic_matrix = []  # bic矩阵
for p in range(pmax+1):  
    tmp = []  
    for q in range(qmax+1):    
        try:  # 存在部分报错,所以用try来跳过报错。      
            tmp.append(ARIMA(data, (p,1,q)).fit().bic)    
        except:      
            tmp.append(None)  
        bic_matrix.append(tmp)
bic_matrix = pd.DataFrame(bic_matrix)  # 从中可以找出最小值
p,q = bic_matrix.stack().idxmin()  # 先用stack展平,然后用idxmin找出最小值位置。
print(u'BIC最小的p值和q值为:%s、%s' %(p,q))
model = ARIMA(data, (p,1,q)).fit()  # 建立ARIMA(0, 1, 1)模型
model.summary2()  # 给出一份模型报告
model.forecast(5)  # 作为期5天的预测,返回预测结果、标准误差、置信区间。

在这里插入图片描述

离群点检测

离群点检测已经被广泛应用于电信和信用卡的诈骗检测、贷款审批、电子商务、网络入侵和天气预报等领域。例如,可以利用离群点检测分析运动员的统计数据,以发现异常的运动员。

主要成因有:数据来源于不同的类、自然变异、数据测量和收集误差。

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

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) + [u'聚类类别']  # 重命名表头
norm = []
for i in range(k):  # 逐一处理  
    norm_tmp = r[['R', 'F', 'M']][r[u'聚类类别'] == 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
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(u'编号')
plt.ylabel(u'相对距离')
plt.show()

笔记摘自于《python数据分析与挖掘实战》

猜你喜欢

转载自blog.csdn.net/food_for_thought/article/details/109427127