探索性数据分析与可视化

  世界如此大,我想去看看;数据如此丰富,怎么能看完。
  面对未知,人类是富有探索精神的,可以不畏艰险,可以排除万难,正是这种探索精神使得人类不断进步不断创造一个又一个奇迹。对于纷繁复杂的数据世界,我们如何进行探索性分析呢?

探索性数据分析

  之前的一些模型是假定数据服从某种分布,然后用样本去调整假设分布的参数,比如贝叶斯模型,GMM等。如果面临错综复杂的数据,我们想去直接看到数据最原始的特点,比如,某个属性是什么分布特点,某些属性的关系,哪些因素具有最大量的信息,某些不确定关系的研究等等。这个时候,假设模型的方法就不那么好使了,这时候就较为考验一个综合能力了。
  所谓探索性数据分析,是在没有头绪的情况下,对数据进行的基本分析,可以从中挖出更具有含金量的信息,为进一步的研究指明方向。探索性数据分析相当于做了个全身体检,重点部位重点检查,后续发现的问题不归其管,自己去找专家去搞定。

与可视化的关系

  探索性的数据分析,侧重于原始数据本身的展示,故此与数据可视化具有相当紧密的联系,并且图形展示更直观且有利于发现有价值的信息。
  可视化能够帮助我们搞定以下几个问题:
  1. 了解数据基本特征
  2. 发现数据潜在的模式
  3. 指导建模策略
  4. 为工程提供参考信息和必要的更正

探索内容与实现

  虽说是探索,但也得有点目标才好,不能啥都不知道就愣头愣脑地往上冲,那岂不是自我证明非二即傻。手段要灵活,快捷。
  Python2.7+ubuntu14.0
  我们采取一个先分后总的研究顺序来探索。
  分别看看各个属性的数据特征,大体分布时什么样子的(即可能会服从什么样子的分布),哪些值的数据最多,数据的均值方差最大最小各是多少,是否自相关等等。
  大体分布最直观的就是直方图了,这个最易于实现。

import matplotlib.pyplot as plt
data1 = [2,2,2,2,3,3,3,4,4,4,4,4,4]
data2 = [2.3,2.4,3.4,2,1,3.4,2,5.6]
plt.xlabel('Smarts')
plt.ylabel('Probability')
plt.title(r'$\mathrm{Histogram\ of\ IQ:}\ \mu=100,\ \sigma=15$')
plt.axis([1, 6, 0, 6]) # 横纵范围
plt.grid(True)
plt.show(plt.hist(data2, bins=4, facecolor='green'))#分成四份
# plt.subplot()用来分子图
plt.hist(data1, bins = 4, facecolor = 'green', alpha = 0.5)
plt.hist(data2, bins = 4, facecolor = 'blue', alpha = 0.5)
plt.show()

上面的代码得到的两个图如下:

探索性数据分析与可视化_第1张图片 探索性数据分析与可视化_第2张图片

图中的横纵坐标的名称和标题只是为了展示如何给图配置,而不是真实情况。
稍微进阶一下,将多个图放到同一个图中展示(添加标题之类的操作和单个图时是一样的)。

import matplotlib.pyplot as plt
data1 = [2,2,2,2,3,3,3,4,4,4,4,4,4]
data2 = [2.3,2.4,3.4,2,1,3.4,2,5.6]
fig = plt.figure()
ax1 = fig.add_subplot(2, 2, 1) # 2*2 的 第一个,及左上侧
ax1.hist(data1, bins=5, facecolor='green')#分成5份

ax2 = fig.add_subplot(222) # 2*2 的 第二个,及右上侧
ax2.hist(data2, bins=5, facecolor='green')#分成5份

ax3 = fig.add_subplot(212) # 2*1 的 第3个, 及下侧一整个
ax3.hist(data1, bins = 4, facecolor = 'green', alpha = 0.5)
ax3.hist(data2, bins = 4, facecolor = 'blue', alpha = 0.5)
plt.show()

探索性数据分析与可视化_第3张图片

  而数据的均值、最大最小表现形式较好的则是 箱线图

import pandas as pd
import matplotlib.pyplot as plt
# 本地读取数据 #
#df = pd.read_csv("your/file/direction/name.csv")
# 读取网络数据 #
data_url = "https://raw.githubusercontent.com/alstat/Analysis-with-Programming/master/2014/Python/Numerical-Descriptions-of-the-Data/data.csv"
df = pd.read_csv(data_url)
print(type(df))
print df.head() # 头
print df.tail() # 细节
print df.columns # 列名
print df.index # 行号
#print df.drop(df.columns[[1, 2]], axis = 1).head() # 舍弃列axis=1;舍弃行axis=0(默认)
print df.describe() # 统计特性,最大,最小,均值,方差
plt.show(df.boxplot()) # 箱线图绘制展示
#### 或者采用 模块 seaborn #### 这个也非常好用,颜色自动搭配
import seaborn as sns
import matplotlib.pyplot as plt
plt.show(sns.boxplot(data = df))
#plt.show(sns.distplot(df.ix[:,2], rug = True, bins = 15))

上面代码的两个图如下:

pandas自带的boxplot 探索性数据分析与可视化_第4张图片

seaborn的箱线图 探索性数据分析与可视化_第5张图片

  是否自相关?对于时间序列,自相关是对某个属性值,时间T和T+1时刻的值存在线性关系。

# 自相关系数
import numpy as np
def autocorrelation(x,lags):
# 计算lags阶以内的自相关系数,返回lags个值,分别计算序列均值,标准差
# lags表示错开的时间间隔
  n = len(x)
  x = np.array(x)
  result = [np.correlate(x[i:]-x[i:].mean(),x[:n-i]-x[:n-i].mean())[0]\
    /(x[i:].std()*x[:n-i].std()*(n-i)) \
    for i in range(1,lags+1)]
  return result

z = autocorrelation(df.ix[:, 1], 1)
print(z)
# 绘制个原始数据的散点图 并将一阶到10阶的自相关系数也绘制到上面
import matplotlib.pyplot as plt
import numpy as np

def autocorrelation(x,lags):
# 计算lags阶以内的自相关系数,返回lags个值,分别计算序列均值,标准差
# lags表示错开的时间间隔
# Notice: 标题神马的不支持中文 #
  n = len(x)
  x = np.array(x)
  result = [np.correlate(x[i:]-x[i:].mean(),x[:n-i]-x[:n-i].mean())[0]\
    /(x[i:].std()*x[:n-i].std()*(n-i)) \
    for i in range(1,lags+1)]
  return result


fig = plt.figure()

axes1 = fig.add_axes([0.1, 0.1, 0.8, 0.8]) # main axes
axes2 = fig.add_axes([0.2, 0.5, 0.4, 0.3]) # inset axes

# main figure
x1 = np.linspace(1, len(df.ix[:, 1]), len(df.ix[:, 1]))
axes1.plot(x1, df.ix[:, 1], 'r')
axes1.set_xlabel(df.columns[1])
axes1.set_ylabel('value')
axes1.set_title('main')

# insert
x2 = np.linspace(1, 10, 10)
y2 = autocorrelation(df.ix[:, 1], 10)
y2 = np.array(y2)
axes2.plot(x2, y2, 'g')
axes2.set_xlabel('jieci')
axes2.set_ylabel('ar')
axes2.set_title('autoRelation of different jieci')
plt.show()

原始数据的折线图与10阶内的自相关值

探索性数据分析与可视化_第6张图片

  密度与热度。密度表示分布情况,可以是单个属性,也可以是多个属性的联合分布。单个属性的密度可以用细密的直方图(将bins值调大)展示。多个属性可以用 气泡图来展示,也可以用heat map来表示。(三维heat map) 热点图图示化了离散数据(事件或事物)的 分布及其相互关系,常常以一张具备显著颜色差异图片的方式呈现最终 结果,亮色一般代表事件发生频率较高或事物分布密度较大,暗色反之。很明显,heat map对数据的要求就是需要有 坐标

#(1) 基于二维位置信息的热点图 #
import seaborn as sns
plt.show(sns.jointplot(df.ix[:,1], df.ix[:,2], kind = "kde"))
#df.ix[:,1]代表所有点在X轴的位置 #
#df.ix[:,2]代表所有点在Y轴的位置 #

探索性数据分析与可视化_第7张图片

```
#(2) 或者借助别人写的一个模块
from pyheatmap.heatmap import HeatMap
http://www.open-open.com/lib/view/open1348041833834.html
但是不怎么好使
#(3) 基于二维位置信息+密度值 的 平面热点图 #
import matplotlib.pyplot as plt
import matplotlib.cm as cm
import numpy as np
side = np.linspace(-2, 2, 15)
X, Y = np.meshgrid(side, side)
# X 和 Y 联合起来表示了网格的位置 #
# X 表示了网格中所有点的x轴值 #
print(type(X)) # narray 矩阵 #
Z = np.exp(-((X-1)**2 + Y**2))
# Z 表示了某个位置处的值 #
print(type(Z)) # Z是一个矩阵 #
plt.show(plt.pcolormesh(X, Y, Z, cmap=cm.RdBu))
# 没有cmap时,默认是黑白的 #

探索性数据分析与可视化_第8张图片

#(4) 用 plt.pcolor 绘制效果, 跟pcolormesh效果类似 #
import matplotlib.pyplot as plt
import matplotlib.cm as cm
import numpy as np
fig, ax = plt.subplots()
p = ax.pcolor(X/(2*np.pi), Y/(2*np.pi), Z, cmap=cm.RdBu, vmin=abs(Z).min(), vmax=abs(Z).max())
cb = fig.colorbar(p, ax=ax)
plt.show()

探索性数据分析与可视化_第9张图片

#(5)基于密度值(高度)的 等高线图 # 需要矩阵表示的高度 #
import matplotlib.pyplot as plt
cnt = plt.contour(Z, cmap=cm.RdBu, vmin=abs(Z).min(), vmax=abs(Z).max(), extent=[0, 1, 0, 1])
plt.show()

探索性数据分析与可视化_第10张图片

#(6) 基于二维位置信息+密度值 的 三维热点图
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
import numpy as np
# suface图
fig = plt.figure(figsize=(14,6))
# `ax` is a 3D-aware axis instance because of the projection='3d' keyword argument to add_subplot
ax = fig.add_subplot(1, 2, 1, projection='3d')
p = ax.plot_surface(X, Y, Z, rstride=4, cstride=4, linewidth=0)
# surface_plot with color grading and color bar
ax = fig.add_subplot(1, 2, 2, projection='3d')
p = ax.plot_surface(X, Y, Z, rstride=1, cstride=1, cmap=cm.coolwarm, linewidth=0, antialiased=False)
cb = fig.colorbar(p, shrink=0.5)
plt.show()

探索性数据分析与可视化_第11张图片

#(7)想将在各个平面上的投影也体现出来 #
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
import matplotlib.cm as cm
import numpy as np

alpha = 0.7
phi_ext = 2 * np.pi * 0.5

def flux_qubit_potential(phi_m, phi_p):
    return 2 + alpha - 2 * np.cos(phi_p) * np.cos(phi_m) - alpha * np.cos(phi_ext - 2*phi_p)

fig = plt.figure(figsize=(8,6))
ax = fig.add_subplot(1,1,1, projection='3d')
phi_m = np.linspace(0, 2*np.pi, 100)
phi_p = np.linspace(0, 2*np.pi, 100)
X,Y = np.meshgrid(phi_p, phi_m)
Z = flux_qubit_potential(X, Y).T
ax.plot_surface(X, Y, Z, rstride=4, cstride=4, alpha=0.25)
cset = ax.contour(X, Y, Z, zdir='z', offset=-np.pi, cmap=cm.coolwarm)
cset = ax.contour(X, Y, Z, zdir='x', offset=-np.pi, cmap=cm.coolwarm)
cset = ax.contour(X, Y, Z, zdir='y', offset=3*np.pi, cmap=cm.coolwarm)
ax.set_xlim3d(-np.pi, 2*np.pi);
ax.set_ylim3d(0, 3*np.pi);
ax.set_zlim3d(-np.pi, 2*np.pi);
plt.show()

探索性数据分析与可视化_第12张图片

  有人会问,空缺值怎么办,这就要看你自己怎么处理了。
  有人会问,为什么不加上归一化的操作,没有说不行,但我们更倾向于发现原始数据的特点,所以操作最好是原始数据来操作。
   看看哪些属性对结果更重要一些。这里可选的方法就多了,有统计学的方法,比如Pearson相关系数(Spearman系数等)、卡方检验,有信息论的方 ,比如信息增益率、GainRatio等,有数据挖掘的方法,比如逻辑回归的属性系数、随机森林的属性重要性等。

#(1)Pearson线性相关系数
import numpy as np
# np.correlate 只是计算两个向量对应位置相乘,再求和 
# 样本协方差如下
cov = np.correlate(df.ix[:, 1] - df.ix[:, 1].mean(), df.ix[:, 2] - df.ix[:, 2].mean())/(len(df.ix[:, 1] - 1))
# 与下面的计算是一样的 
#cov = np.dot(df.ix[:, 1] - df.ix[:, 1].mean(), df.ix[:, 2] - df.ix[:, 2].mean())/(len(df.ix[:, 1] - 1))
# 样本方差如下
std1 = df.ix[:, 1].std()
std2 = df.ix[:, 2].std()
# 故两个属性的Pearson线性相关系数如下
Pearson = cov/(std1*std2)
print(Pearson)
# 相关系数的大小 与 线性相关性 的关系
#    0.8-1.0 极强相关
#    0.6-0.8 强相关
#    0.4-0.6 中等程度相关
#    0.2-0.4 弱相关
#    0.0-0.2 极弱相关或无相关

  看看某些属性间是否也存在某些关系

# 两个属性之间的 散点图 #
import matplotlib.pyplot as plt
plt.xlabel(df.columns[2])
plt.ylabel(df.columns[3])
plt.grid(True)
plt.show(plt.scatter(df.ix[:, 2], df.ix[:, 3]))
# 两个属性之间的 联合分布 # 用seaborn更方便一些 #
import matplotlib.pyplot as plt
import seaborn as sns
plt.show(sns.jointplot(df.ix[:,1], df.ix[:,2], kind = "kde"))
# 三个属性之间的关系 展示 # 可以用上面的三维展示方法,plot_surface,如上文中的介绍,此处不再赘述。

散点图与联合分布图

探索性数据分析与可视化_第13张图片 探索性数据分析与可视化_第14张图片

# 多个个体之间的关系,比如社交关系 的展示 #

  再简单聚个类,不要小瞧聚类,很多时候会非常给力。当然聚类方法的选择和聚类个数需要好好试试。聚类可以看到数据大体的特点,还可以把某些属性跟所分的类联系到一起。

# python 聚类
#(1)K-Means聚类

#(2)基于密度的聚类

  最富信息内容的提取,这也是个很重要的问题。如果有标签属性,可以通过前面的分析得出来。若是没有标签属性,那么可以利用降维技术,来提取出重要因素,数据经过有效降维后,剩下的是有用信息,更便于分析。
  
  
参考:
(1)http://blog.sciencenet.cn/blog-251664-800766.html
(2)http://www.jb51.net/article/62982.htm
(3)http://www.tuicool.com/articles/mYNvamI
(4)http://blog.sina.com.cn/s/blog_6252a9bf0101b257.html
(5)http://nbviewer.ipython.org/github/jrjohansson/scientific-python-lectures/blob/master/Lecture-4-Matplotlib.ipynb#pcolor
(6)http://www.cnblogs.com/taceywong/p/4570155.html
(7)http://san-yun.iteye.com/blog/1935786

你可能感兴趣的:(技术博客)