##1.引言

在处理数据时常常需要对数据进行可视化以便观察,但是,在笛卡尔坐标系下,超过3维的数据我们就无法可视化了,所以,我们就需要一种有效的方法来可视化高维数据.

常用的方法有Parallel Coordinates,关于这个方法的介绍可以看wikipedia页面,这里就不再重复了.

##2.python解决方案

用python实现高维数据可视化需要用到几个库函数 :

  1. Pandas : parallel_coordinates
  2. Pandas : DataFrame
  3. scikit-learn : datasets.load_iris()
  4. Numpy

这里有一个简单的教程来熟悉pands语法:
10分钟熟悉pandas

如果对pandas的数据结构不了解,还要熟悉一下它的数据结构
Pandas 数据结构简介

DataFrame 的API文档

材料准备齐全,就可以开始进行可视化操作了.


##3. 实现过程

3.1 准备数据

首先找一个经典的4维数据集: 鸢尾花 iris数据集 wiki ,uci下载地址

数据集简要描述:

只有四个属性:

  1. sepal length in cm
  2. sepal width in cm
  3. petal length in cm
  4. petal width in cm

共三类:

  • Iris Setosa
  • Iris Versicolour
  • Iris Virginica

3.1.1 导入数据

由于scikit-learn已经内建了这个数据集,可以直接导入使用

1
2
3
from sklearn import datasets
data_origin = datasets.load_iris()

data_origin是一个 python 字典, 包含了

  • ‘target_names’: 标签名,’setosa’ ‘versicolor’ ‘virginica’
  • ‘data’: 数据 ,150 * 4的 ndarray 对象
  • ‘target’: 标签值, 0 1 2, 分别对应一个标签名
  • ‘feature_names’: 特征名, ‘sepal length (cm)’, ‘sepal width (cm)’, ‘petal length (cm)’, ‘petal width (cm)’
  • ‘DESC’ : 数据集描述字符串

3.1.2 处理数据

由于我们要调用 pandas 的 parallel_coordinates 函数,它需要一个 Pandas.DataFrame 对象格式的数据,所以我们要把上面的数据包装到一个 DataFrame对象里.

DataFrame对象其实就和Sql数据库中的表一样,它和矩阵的不同之处在于它包含了每一列的名称和每一行的名称.

由于Pandas可以由多种数据类型构造:

  • Dict of 1D ndarrays,lists,or Series (由 1维的 ndarray,list,Serie 构成的 字典Dict)
  • 2-D numpy.ndarray 2维的numpy 多维数组
  • numpy中的 Structured or record ndarry
  • Pandas中的 一个 Series
  • 另一个DataFrame

这里,我选用第一种方式,用python中的字典对象构造.把iris数据包装成一个DataFrame对象,前四列是每个特征对应的值,最后一列是该行数据的数据类型(用target_name构造).每一行是一个数据.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 先把数据提取出来
data = data_origin['data']
# 处理类标签数据
target= data_origin['target']
target_names = data_origin['target_names']
target_labels=[]
for class_num in target:
target_labels.append(target_names[class_num])
feature_names = data_origin['feature_names']
# 合成字典
data_dict = {}
column = 0
for feature_name in feature_names:
data_dict[feature_name] = data[:,column]
column+=1
data_dict['target_labels'] = target_labels

有了字典后就可以合成pandas DataFrame了

1
2
3
4
5
# 包装成 DataFrame
import pandas as pd
pd_data = pd.DataFrame(data_dict)


###3.1.3 画图

有了数据后,画图就十分方便,只需要调用 pandas 的内置函数 parallel_coordinates() 就好了:

1
2
3
4
5
6
7
8
9
from pandas.tool.plotting import parallel_coordinates
import matplotlib.pyplot as plt
plt.figure()
parallel_coordinates(pd_data,'target-labels')
plt.show()

这样,图就画好了 :
plot

##画一个 500维的数据集 madelon

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
#coding=utf-8
__author__ = 'anboqing'
from pandas.tools.plotting import parallel_coordinates
import pandas as pd
import numpy as np
import LoadLibSvm as ld
import matplotlib.pyplot as plt
origin_data,origin_label = ld.load_libsvm_data('madelon')
#print type(origin_data)
# 读取到原始数据和数据的标签后,要包装成一个DataFrame对象
#print np.shape(origin_label)
mat_data = np.mat(origin_data)
mat_data = mat_data.transpose()
"""
#print type(mat_data)
arr_data = np.array(origin_data)
#print arr_data.shape
print type(arr_data)
print type(mat_data[1,:])
arr = np.array(mat_data[1,:])
lst = list(arr)
print type(lst)
print np.shape(lst)
print lst[0]
lst = list(lst[0])
print lst[0]
print type(lst[0])
"""
# 先包装成一个dict
data_dict = {}
for idx in range(mat_data.shape[0]):
arr = np.array(mat_data[idx,:])
lst = list(arr)
lst = list(lst[0])
data_dict[str(idx)] = lst
data_dict['label']=origin_label
pd_df = pd.DataFrame(data_dict)
"""
选了4列来画,能画出来,说明方法是对的,然而画所有列全都是黑的,说明图片尺寸太小了
small_data = pd.DataFrame(pd_df,columns=['1','2','3','label'])
plt.figure()
parallel_coordinates(small_data,'label')
plt.show()
"""
plt.figure(figsize=(100,50),dpi=20)
parallel_coordinates(pd_df,'label')
plt.show()

画出来效果是这样:
小图
下面是大图,可以在新页面打开放大看细节:
4M大图

Comments

⬆︎TOP