##1.引言
在处理数据时常常需要对数据进行可视化以便观察,但是,在笛卡尔坐标系下,超过3维的数据我们就无法可视化了,所以,我们就需要一种有效的方法来可视化高维数据.
常用的方法有Parallel Coordinates,关于这个方法的介绍可以看wikipedia页面,这里就不再重复了.
##2.python解决方案
用python实现高维数据可视化需要用到几个库函数 :
- Pandas : parallel_coordinates
- Pandas : DataFrame
- scikit-learn : datasets.load_iris()
- Numpy
这里有一个简单的教程来熟悉pands语法:
10分钟熟悉pandas
如果对pandas的数据结构不了解,还要熟悉一下它的数据结构
Pandas 数据结构简介
DataFrame 的API文档
材料准备齐全,就可以开始进行可视化操作了.
##3. 实现过程
3.1 准备数据
首先找一个经典的4维数据集: 鸢尾花 iris数据集 wiki ,uci下载地址
数据集简要描述:
只有四个属性:
- sepal length in cm
- sepal width in cm
- petal length in cm
- 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
| 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()
|
这样,图就画好了 :
##画一个 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
| __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') 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]) """ 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()
|
画出来效果是这样:
下面是大图,可以在新页面打开放大看细节: