调和曲线图用于聚类判断, 比较方便
多元数据的可视化方法很多,譬如散点图、星图、雷达图、脸谱图、协同图等,大致可分为以下几类:1.基于点(如二维、三维散点图);2.基于线(如轮廓图、调和曲线图);3.基于平面图形(如星图、雷达图、蛛网图);4.基于三维曲面(如三维曲面图)。其思想是将高维数据映射到低维空间(三维以下)内,尽量使信息损失最少,同时又能利于肉眼辨识。调和曲线图和轮廓图(即平行坐标图)都是多元数据的可视化方法,它们基于“线”的形式,将多元数据表示出来,对于聚类分析有很好的帮助。
轮廓图
轮廓图的思想非常简单、直观,它是在横坐标上取 p 个点,依次表示各个指标(即变量);横坐标上则对应各个指标的值(或者经过标准化变换后的值),然后将每一组数据对应的点依次连接即可。
lattice 包中的 parallel() 函数可以轻松绘出轮廓图。利用 iris 数据,以下代码可以画出其轮廓图(图1)。
library(lattice)
data(iris)
parallel(~iris[1:4], iris, groups = Species,
horizontal.axis = FALSE, scales = list(x = list(rot = 90)))
图1 Iris 数据的轮廓图(Parallel Coordinate Plots)
观察图1,可以发现同一品种的鸢尾花的轮廓图粗略地聚集在一起。
调和曲线图
调和曲线图的思想和傅立叶变换十分相似,是根据三角变换方法将 p 维空间的点映射到二维平面上的曲线上。假设
Xr
是 p 维数据的第 r 个观测值,即
XTr=(xr1,⋯,xrp)
则对应的调和曲线是
fr(t)=xr1sqrt2+xr2sint+xr3cost+xr4sin2t+xr5cos2t+⋯
其中
−π≤t≤π
.
同样利用 iris 数据,下面代码(主要取自《统计建模与R软件》,尚未优化)可以画出其调和曲线图(图2)。
x = as.matrix(iris[1:4])
t = seq(-pi, pi, pi/30)
m = nrow(x)
n = ncol(x)
f = matrix(0, m, length(t))
for (i in 1:m) {
f[i, ] = x[i, 1]/sqrt(2)
for (j in 2:n) {
if (j%%2 == 0)
f[i, ] = f[i, ] + x[i, j] * sin(j/2 * t)
else f[i, ] = f[i, ] + x[i, j] * cos(j%/%2 * t)
}
}
plot(c(-pi, pi), c(min(f), max(f)), type = "n", main = "The Unison graph of Iris",
xlab = "t", ylab = "f(t)")
for (i in 1:m) lines(t, f[i, ], col = c("red", "green3",
"blue")[unclass(iris$Species[i])])
legend(x = -3, y = 15, c("setosa", "versicolor", "virginica"),
lty = 1, col = c("red", "green3", "blue"))
图2 Iris 数据的调和曲线图
观察图2,同样可以发现同一品种鸢尾花数据的调和曲线图基本上扭在一起。同图1 比较后,发现图2 更加清楚明白,事实上Andrews证明了调和曲线图有许多良好性质。
讨论
轮廓图和调和曲线图有着相近的功能,而技巧大有不同。轮廓图简单却现得粗糙,调和曲线图公式复杂却十分精细。从这一个侧面可以发现直观的统计思想固然重要,但存在很多种不可能通过直观思想得到的、而又非常精细、美妙的方法,此时倍受众多统计学家责难的数学显得优雅而又强大。
从去年刚学R的时候碰了下调和曲线图之后就再也没碰过了,碰巧今天正好有人问起,索性干脆就几种常见的实现方法简单写一写,不算上自己动手写函数的话大致有那么三种,当然肯定也还有很多更好的办法。
1 MSG包中的andrews_curve()
这是我觉得最不错的方法,函数代码很科学,在我的另一篇文章上也以它作为示例,并且在参数设置上与一般的plot等保持了一致,感觉在作图效果的设置上也很灵活,这是因为函数本身依赖于matplot,参数中除去x和n外其余均可完全参照matplot,x则指的是需提供作图的数据,数据框和矩阵均可,n用于控制取点个数,即曲线的平滑度,n越大平滑程度越高,缺省值是101。
andrews_curve(iris[, -5])
曲线的颜色可以col参数控制,缺省时采用默认的调色板,也可以自己设置一个向量,如果曲线数超过调色板长度或向量的长度则会重复使用,上述代码未经任何设置即采用了 默认的调色板,但事实上效果并不理想,曲线一多就会显得很乱,但仔细观察可以看到曲线大致可以分成那么几类,于是可以“按类”指定颜色
andrews_curve(iris[, -5], col = as.integer(iris[, 5]))
这里借助了数据中的分类变量,将其转化为整数后即可调用调色板中的颜色。
2 andrews包中的andrews()
andrews包是专门为调和曲线服务的,但除了提供了更多的f(t)形式外,实在找不出更多的优点,函数本身也并不灵活。用法如下
andrews(df, type=1, clr=NULL, step=100, ymax=10, main=NULL, sub=NULL)
df指的是data frame,即需要用于作图的数据,但事实上matrix也是可以的,type可以指定f(t)的形式,主要提供了四种形式
1: f(t)=x1/(2^0.5)+x2*sin(t)+x3*cos(t)+x4*sin(2*t)+x5*cos(2*t)+...
2: f(t)=x1*sin(t)+x2*cos(t)+x3*sin(2*t)+x4*cos(2*t)+...
3: f(t)=x1*cos(t)+x2*cos((2*t)^0.5)+x3*cos((3*t)^0.5)+...
4: f(t)=1/(2^0.5)*(x1+x2*(sin(t)+cos(t))+x3*(sin(t)-cos(t))+x4*(sin(2*t)+cos(2*t))+x5*(sin(2*t)-cos(2*t))+...)
clr是与之前介绍的andrews_curve最大的不同点,这里颜色的设置需要依赖于数据集中的某一变量,一般用分类变量,而不能直接在函数参数中设置颜色。例如
andrews(iris,clr=5,ymax=3)
这里就是采用数据集irish中的第五个变量的取值来设置颜色(当然这其实也是分类变量可视化的一种很好的办法),其实也就是类似于之前的
col = as.integer(iris[, 5])
当然如果原始数据中并没有合适的变量可以自行在原始数据中添加一列,但这样就没有充分利用原始数据的信息,略微有点浪费。step的用法与andrews_curve中的参数n基本一致。函数本身并没有提供更多用于美化图形的参数,可以通过par或者一些低级绘图函数来实现,可能并没有那么方便,另外函数源代码中的嵌套式循环也让人觉得非常遗憾。
3 tourr包中的andrews()
这个包里的andrews()是没有画图功能,仅仅只能用来计算,也就是数据的转换,但数据都转换好了,剩下其实也就没啥了。不过比较有意思的是,包中还有一个关于调和曲线的函数提供了一种动画形式的实现(虽然没什么技术含量)
animate_andrews(flea[, 1:6], grand_tour(d = 3))
当然在这不经任何修缮的情况下,效果是比较恶心的,好在有那三个点,所以最终能画成什么样,完全就事在人为啦。
另外包的作者心眼不错,为此还配了一个GUI,也就是tourrGui包,当然范围也不止调和曲线,还有脸谱图、平行坐标图(轮廓图)等等,玩一玩挺不错。