数据挖掘(二)用python实现数据探索:汇总统计和可视化

时间:2023-03-08 17:15:26
数据挖掘(二)用python实现数据探索:汇总统计和可视化

  今天我们来讲一讲有关数据探索的问题。其实这个概念还蛮容易理解的,就是我们刚拿到数据之后对数据进行的一个探索的过程,旨在了解数据的属性与分布,发现数据一些明显的规律,这样的话一方面有助于我们进行数据预处理,另一方面在进行特征工程时可以给我们一些思路。所以这样一个过程在数据挖掘中还是蛮有用的,相信大家在网上看过不少数据挖掘比赛的Kernel,一般一上来都先是个数据探索的过程。之前听过一个老师讲课,说数据探索过程其实可有可无,直接预处理猛搞,但典型的口嫌体正直,在演示一个比赛的流程时,还是先进行了汇总统计及可视化,哈哈哈,其实八数据探索归结到数据预处理中也未尝不可。
  
  那回到正题,数据探索主要包括两个方面
  
  一 汇总统计
  
  二 数据可视化
  
  我们先对汇总统计涉及的概念进行一些梳理,然后讲解如何用Python完成汇总统计以及常见的数据可视化。就我个人经验来说,可视化真的很重要,文章写得好不如图画的漂亮。
  
  ====================================================================
  
  什么是汇总统计呢?就是用单个数或者数的小集合去表示一个大的值的集合的特征,其实就是一些描述性的统计量,概念非常容易理解,比较常见的如下
  
  1 频率和众数
  
  频率就是指某个值出现的次数占总体数值个数或者某个属性为某值的对象占总体对象数目的比例。频率最高对应的值或属性就称之为众数。通常我们会对频率值比较极端的情况感兴趣,需要注意的就是对于连续数据通常不存在频率或者众数的概念,不过我们可以通过阈值切分完成离散化再进行相关统计。
  
  2 百分位数
  
  百分位数就是指处于对应百分数处的数据所对应的值。这个数据可以很好地帮我们认识数据的分布,主要集中在哪个区域,是否存在很明显的离群点等等。
  
  3 均值和中位数
  
  这两个概念不用介绍了吧,一个是均值,一个是最中间的一个数的值或两个数的均值。日常生活中,人们总喜欢用均值来表示平均水平,但这其实有个前提,就是数据是对称分布的,而且均值对于离群值很敏感,这就是大家会吐槽国家统计局发布的什么地区平均收入水平的原因,假如马云爸爸身家200亿美金,浙江省人口5000万,那马云爸爸一个人就把均值拉升了400美金,你说这个均值的意义到底在哪里啊……相比之下,中位数是一个更好的衡量指标,相比较均值,更能够体现数据中部处于怎样一个水平。
  
  4 极差和方差、
  
  极差就是数据中最大值最小值之差,可以体现数据分布范围,但是极差由于只涉及最值,所以对于数据分布比较倾斜或者存在离群值的时候,并不能很好刻画数据范围。而方差则是指每个数据与均值之差的平方和除以数据数目,该数据可以刻画数据的集中程度,但由于它用到了均值,所以它同样对离群值很敏感。
  
  5 多元汇总统计
  
  对于包含多个属性的数据,我们当然可以分别计算各项数据的上述属性,但是除此之外,有的时候我们需要各项属性之间的相关程度,这个时候我们通常会用到协方差矩阵,协方差用来描述属性之间的线性关系,+1线性正相关,-1线性负相关,0无线性相关关系,但相比于协方差矩阵,相关矩阵更适合表现数据间的相关性,因为它相当于对数据先做了一个标准化。
  
  ===============================================================================
  
  这里用到的还是我在之前那个系列里用烂的鸢尾花数据,哈哈哈,没办法,谁让它简单呢。
  
  这里我们首先从sklearn里引入鸢尾花数据,并将其转换成pandas中的dataframe,因为pandas做汇总统计真又轻松又愉快啊。
  
  [python] view plain copy
  
  from sklearn.datasets import load_iris
  
  import pandas as pd
  
  import numpy as np
  
  from pandas import DataFrame as df
  
  column=load_iris().feature_names
  
  data=load_iris().data
  
  target=load_iris().target
  
  df1=df(data,columns=column)
  
  df2=df(target,columns=['target'])
  
  data_df=pd.concat([df1,df2],axis=1)
  
  print data_df.shape
  
  data_df.describe()
  
  结果如下
  
  首先介绍以下这个数据吧。鸢尾花数据总共有150个,每个数据对应四个属性,分别是花萼和花瓣的长度与宽度,花的类型有三种。代码中,我们首先输出了一下原始数据的形状,150行5列,然后利用describe函数一次性输出了多个汇总统计变量。其中唯一一个要注意的就是count变量代表的是数据中非NA值的数量,比对该值和数据形状可以知道数据中是否存在无效值。而对于均值,标准差,极值和百分位数在第一个表中的意义并不大,因为它是把三个种类的花一起进行了计算,并不能看出各个属性对分类的影响,因此我们接下来分别对每种属性进行一次describe。
  
  [python] view plain copy
  
  data_df[data_df['target']==0].describe()
  
  data_df[data_df['target']==1 www.jinhuyouxi.cn].describe()
  
  data_df[data_df['target']==2]www.niucaiyule1.cn .describe()
  
  结果如下
  
  从这三个表我们就能看出一点东西了。对于第一种花而言,它的花瓣长度和宽度远小于第二种和第三种花,它的最大值都不如另外两种的最小值大,设定一个阈值就可以愉快的把第一种花与另外两种分开了。而第二种和第三种则没有那么明显的区分了,只能看出第三种花的每个属性似乎都比第二种大些,当然我们也不苛求自己光靠数据探索就把分类工作完成了啊,不然还要什么算法,光看就好了。当然汇总统计还包括协方差和相似矩阵,在python中可以这么算。
  
  [python] view plain copy
  
  data_df.cov()
  
  data_df.corr()
  
  结果如下
  
  从系数矩阵中也能得到一些信息,比如花瓣的长度与宽度和目标的相关性明显要高些,而花萼的宽度似乎和目标有那么一点点负相关,这些都是我们后续分析的线索。
  
  上面说的都是一些汇总统计量的计算,数据探索中还有很大一块就是数据的可视化。
  
  对于分类数据而言,由于我们可以用颜色或者标记去区别不同的类,所以我们的坐标轴可以全部用于属性的表示,比如说在这里我们可以用一个二维图来表示每个样本对应的两个属性的分布,假如用花瓣的长度和宽度这两个属性,我们用python来画一下看看
  
  [python] view plain copy
  
  from matplotlib import pyplot as plt
  
  plt.plot(data_df[data_df['target']==0]['petal length (cm)'],data_df[data_df['target']==0]['petal width (cm)'],'r*',label='0')
  
  plt.plot(data_df[data_df['target']==1]['petal length (cm)'],data_df[data_df['target']==1]['petal width (cm)'],'ro',label='1')
  
  plt.plot(data_df[data_df['target']==2]['petal length (cm)'],data_df[data_df['target']==2]['petal width (cm)'],'bx',label='2')
  
  plt.xlabel('petal length (cm)')
  
  plt.ylabel('petal width (cm)')
  
  plt.legend(loc='best')
  
  plt.grid()
  
  plt.show()
  
  结果如下
  
  这里只是举了一个简单的例子,相似的我们可以做出所有其他属性的分布。从这个图上我们其实对这个简单的分类问题有了一个大概的认知,第一类在右下角与另外两类完全分开,另外两类虽然有所重叠但是也有一个基本的范围。但这样的做法有一个缺点就是最多拓展到三维空间,也就是说你最多只能表示三个属性啊,并我要是属性多了想看看这种综合的影响该怎么做呢,在数据量不多的时候有一个比较有效的办法叫做平行坐标系法,与之前的情况的不同在于,之前各属性的坐标轴是相互正交的,用点去表示一个样本,而平行坐标轴各属性的坐标轴是平行的,因此用一条线来代表一个样本,下面是我强行画的一个图。
  
  [python] view plain copy
  
  from matplotlib import pyplot as plt
  
  data0=data_df[data_df['target']==0][www.zyzxylvip.cn ['sepal length (cm)','sepal width (cm)','petal length (cm)','petal width (cm)']].T
  
  data1=data_df[data_df['target']==1][www.wmyl11.com ['sepal length (cm)','sepal width (cm)','petal length (cm)','petal width (cm)']].T
  
  data1.columns=data0.columns
  
  data2=data_df[data_df['target']==2][['sepal length www.aomenyonli.cn (cm)','sepal width (cm)','petal length (cm)','petal width (cm)']].T
  
  data2.columns=data0.columns
  
  for i in xrange(0,50):
  
  plt.plot([0,1,2,3],data0[i],'r-')
  
  plt.plot([0,1,2,3],data1[i],'b-')
  
  plt.plot([0,1,2,3],data2[i],'g-')
  
  plt.xticks([0,1,2,3],['sepal length (cm)','sepal width (cm)','petal length (cm)','petal width (cm)'])
  
  plt.show()
  
  结果如下
  
  从这个图里我们可以看出来前面两个属性交叉比较多分起来比较困难,后面这两个的区分度比较高,还是比较直观的。这里画的这个图其实是有我强行画的,是有点问题的,一旦把这个图例加上就会爆炸了,即使我把dataframe里的columns都改了,最后还是会出来很多,也是醉了,不过如果用最初的ndarray对象的话没有问题。
  
  其他常见的可视化方法还有直方图和箱形图等等,在pandas里面都可以非常方便的做出来,具体代码如下:
  
  [python] view plain copy
  
  from matplotlib import www.lieqibiji.com pyplot as plt
  
  plt.hist(data_df[data_df['target']==0]['petal length (cm)'],color='blue',label='Class 0',alpha=0.5,bins=20)
  
  plt.hist(data_df[data_df['target']==1]['petal length (cm)'],color='red',label='Class 1',alpha=0.5,bins=20)
  
  plt.hist(data_df[data_df['target']==2]['petal /www.xingcaiyule.net/ length (cm) www.caihonyule.com'],color='green',label='Class 2',alpha=0.5,bins=20)
  
  plt.legend(loc='best')
  
  plt.grid()
  
  plt.show()
  
  data_df.boxplot(by='target',layout=(2,2))
  
  plt.show()
  
  结果如下
  
  通过直方图我们可以观察并比较每个品种的花的各项属性的分布,而通过箱形图我们则可以比较不同种类花的各项属性的分布及集中程度。从上面的直方图和箱图中我们可以明显看出在花瓣属性上三者存在着比较明显的区别。
  
  OK,数据探索大概的内容就讲这么多,主要包括汇总统计和数据可视化两部分,同时讲了如何用Python进行数据探索,我觉得特别是可视化的部分大家可以多尝试尝试,哪怕不做数据挖掘,任何时候图表都比文字叙述来的更直观和有说服力。
  
  新的一周,祝大家元气满满~~~