1.3 距离、相异系数、相似系数和列联系数
在分类问题中,一般会把特征接近的事物归为一类,把特征不同的事物归为不同的类。因此,首先需要建立定量指标来刻画事物之间的相近程度或相似程度。这类指标就是距离、相异系数、相似程度和列联系数。它们是学习多元统计分析方法的基础。
1.3.1 基于数值型变量的距离
一个研究对象常常需要用多个变量来刻画其特征。如果n个对象需要用p个数值型变量描述,那么可以把这n个对象看成p维空间中的n个点。很自然地,两个对象之间的相似程度可用p维空间中两点之间的距离来度量。令dij表示对象Xi与Xj的距离,常用的距离定义有以下几种。
(1)欧氏距离
(1.3)
(2)绝对值距离(曼哈顿距离)
(1.4)
(3)切比雪夫距离(棋盘距离)
(1.5)
(4)闵氏距离
(1.6)
(5)兰氏距离(堪培拉距离)
(1.7)
其中,欧氏距离是人们较为熟悉的,也是使用最多的距离。stats包里的函数dist()可以用于计算上述各种距离,函数中的参数method用于设定计算距离的方法。欧氏距离、绝对值距离、切比雪夫距离、闵氏距离、兰氏距离的参数method的取值分别为euclidean、manhattan、maximum、minkowski、canberra,默认为“euclidean”,即欧氏距离。例如,使用表1-2中的4项临床检测指标计算前5个研究对象的距离:
>dist(bio[1:5,]) 1234 27.014421 39.0372402.108886 429.03126922.02427120.009190 525.01511918.00734616.0382644.196737
上面的命令选取了数据框bio的前5行,用函数dist()计算了5个对象两两之间的欧氏距离。
距离矩阵是一个对称矩阵,函数dist()的默认输出只显示距离矩阵的下三角,我们可以通过设置参数diag和upper为TRUE显示完整的距离矩阵:
>dist(bio[1:5,],diag=TRUE,upper=TRUE) 12345 10.0000007.0144219.03724029.03126925.015119 27.0144210.0000002.10888622.02427118.007346 39.0372402.1088860.00000020.00919016.038264 429.03126922.02427120.0091900.0000004.196737 525.01511918.00734616.0382644.1967370.000000
需要注意的是,在使用欧氏距离时,变量的量纲不能相差太大。当变量的量纲不同,测量值的变异相差悬殊时,需要先对数据进行标准化处理,然后用标准化后的数据计算距离。
由1.2.1节中算得的均值向量可以看出,各指标之间由于测量单位的不同导致数值的差异较大。如果直接计算行与行之间的距离,会出现“大数吃小数”现象,即PTA所在列的权重远大于其他各列。因此,这里需要用函数scale()将数据标准化后再计算距离矩阵:
>bio.scale<-scale(bio) >dist(bio.scale[1:5,]) 1234 20.8735292 31.54278680.9613100 42.85990022.10209321.4349353 51.78659711.10155741.61753182.0507346
由于两个变量的量纲不同,数据的变异也相差较大,上面得到的两个距离矩阵有很大的不同。此外,在计算距离矩阵时,还应尽可能地避免变量间的多重相关。多重相关所造成的信息重叠,会片面强调某些变量的重要性。
鉴于上述距离的不足,一种改进的距离就是马氏距离:
(1.8)
其中,为总体的协方差矩阵,实际中常用样本协方差矩阵估计。马氏距离不受量纲的影响。当变量之间彼此完全不相关时,为单位矩阵,此时马氏距离就是欧氏距离。
在R中,stats包的函数mahalanobis()可用于计算样本点到某个中心点的马氏距离。需要注意的是,该函数的返回值是上面定义的马氏距离的平方。
StatMatch包的函数mahalanobis.dist()可以用来计算数据框中各样品之间的马氏距离。使用该包之前需要先安装。
>library(StatMatch) >mahalanobis.dist(bio)[1:5,1:5] 12345 10.0000001.1460371.7174573.9725193.052284 21.1460370.0000001.2748363.0594832.248249 31.7174571.2748360.0000002.8843753.273679 43.9725193.0594832.8843750.0000002.992607 53.0522842.2482493.2736792.9926070.000000
上面计算对象之间的马氏距离,其中的总体协方差矩阵用样本协方差矩阵估计。用户也可以使用函数中的参数vc自定义协方差矩阵。
1.3.2 基于分类变量的相异系数
如果研究对象的特征是用分类变量来刻画的,我们可以用相异系数(dissimilarity coefficient)度量对象之间的相异性。两个对象i和j之间的相异系数根据对象之间的不匹配率来衡量,计算公式为
(1.9)
其中,k是匹配的数目(即对象i和j取值相同的属性数),p是刻画对象的属性总数。
将研究对象彼此之间的相异系数用矩阵的形式表示就得到相异系数矩阵(dissimilarity coefficient matrix)。StatMatch包的函数gower.dist()可以用来计算对象之间的相异系数矩阵。例如,在数据集cirr中,如果只用性别描述对象的特征(此时p = 1,k为0或者1),那么对象之间的相异系数矩阵为:
>g1<-gower.dist(cirr[,1])
与距离矩阵类似,相异系数矩阵也是一个对角线上全为0的方阵。
>dim(g1) [1]3636 >diag(g1) [1]000000000000000000000000000000000000
由于该矩阵较大,下面仅显示前5个对象的相异系数矩阵:
>g1[1:5,1:5] [,1][,2][,3][,4][,5] [1,]00100 [2,]00100 [3,]11011 [4,]00100 [5,]00100
可以看出,性别相同的对象之间的相异系数为0,而性别不同的对象之间的相异系数为1。
进一步地,用两个分类变量(性别、年龄组)描述对象的特征(此时p = 2),相异系数矩阵为:
>g2<-gower.dist(cirr[,1:2]) >g2[1:5,1:5] [,1][,2][,3][,4][,5] [1,]0.00.51.00.50.5 [2,]0.50.00.50.00.0 [3,]1.00.50.00.50.5 [4,]0.50.00.50.00.0 [5,]0.50.00.50.00.0
从上面的相异系数矩阵可以看出,性别和年龄组都相同的对象之间的相异系数为0(如对象2与对象4),性别和年龄组有其中一个相同的对象之间的相异系数为0.5(如对象1与对象2),而性别和年龄组均不同的对象之间的相异系数为1(如对象1与对象3)。
1.3.3 基于混合类型变量的相异系数
实际上,函数gower.dist()不仅可以用于计算基于分类变量的相异系数,还可以依据Gower相异系数的定义(Gower,1971)扩展到混合类型(包括逻辑型、因子型、字符型、有序因子型、数值型)的数据。Gower相异系数也称Gower距离,它依据不同类型的变量给出了不同的计算方法,并将计算结果映射到共同的值域区间[0, 1]上,值越大表示相异程度越大。例如:
>g3<-gower.dist(cirr) >g3[1:5,1:5] [,1][,2][,3][,4][,5] [1,]0.00000000.23156840.43877400.35545760.3086653 [2,]0.23156840.00000000.22418090.14086450.0770969 [3,]0.43877400.22418090.00000000.26081940.2796814 [4,]0.35545760.14086450.26081940.00000000.1408094 [5,]0.30866530.07709690.27968140.14080940.0000000
从上面的输出结果可以看到,在前5个研究对象中,第1个和第3个对象之间的差异最大,而第2个和第5个对象之间的差异最小。
在相异系数矩阵g3中,最大的值为:
>max(g3) [1]0.7910371
除去对角线上的0,最小的值为:
>min(g3[g3!=0]) [1]0.0349978
如果想找到整个数据集cirr中差异最大和最小的对象,可以使用下面的命令:
>which(g3==max(g3),arr.ind=TRUE) rowcol [1,]2916 [2,]1629 >cirr[c(16,29),] sexagegrpFIBlnPTPTAlnCHE 16male40-590.783.05327.55 29female60+2.402.391138.79 >which(g3==min(g3[g3!=0]),arr.ind=TRUE) rowcol [1,]3426 [2,]2634 >cirr[c(26,34),] sexagegrpFIBlnPTPTAlnCHE 26male60+2.482.73747.72 34male60+2.592.70787.53
cluster包的函数daisy()也可以用来计算Gower相异系数,在聚类分析中经常用到。
1.3.4 相似系数
样品间的亲疏关系用距离度量,而变量间的相似程度用相似系数度量。常用的相似系数有相关系数和夹角余弦。
Pearson相关系数是最常用的一种相关系数,其计算公式见式(1.2)。函数cor()可用于计算Pearson样本相关系数,例如:
>cor(bio$FIB,bio$PTA) [1]0.7460267
需要注意的是,计算Pearson相关系数时,要求变量服从二元正态分布。函数cor()中的参数method默认为“pearson”,即默认计算Pearson相关系数。如果变量不服从正态分布,可以将method设为“spearman”计算Spearman秩相关系数。
夹角余弦使用向量空间中两个向量的夹角的余弦值来衡量它们之间的相似程度。两变量与的夹角余弦定义为
(1.10)
R的基本包中没有计算夹角余弦的函数,不过我们很容易根据上面的公式计算。例如,表1-2中FIB与PTA两个变量的夹角余弦为:
>x<-bio$FIB >y<-bio$PTA >sum(x*y)/sqrt(sum(x^2)*sum(y^2)) [1]0.9770776
实际上,就是向量与的夹角余弦。若将原始数据标准化,则夹角余弦与Pearson样本相关系数等价。
>x.scale<-scale(x) >y.scale<-scale(y) >sum(x.scale*y.scale)/sqrt(sum(x.scale^2)*sum(y.scale^2)) [1]0.7460267
Philentropy包实现了46种不同的距离算法、相似性度量以及信息熵的度量。它为分类问题、信息理论和机器学习算法等提供了核心的计算框架。使用该包之前需要先安装。
>library(philentropy)
使用函数getDistMethods()查看可以使用的距离算法:
>getDistMethods() [1]"euclidean""manhattan""minkowski" [4]"chebyshev""sorensen""gower" [7]"soergel""kulczynski_d""canberra" [10]"lorentzian""intersection""non-intersection" [13]"wavehedges""czekanowski""motyka" [16]"kulczynski_s""tanimoto""ruzicka" [19]"inner_product""harmonic_mean""cosine" [22]"hassebrook""jaccard""dice" [25]"fidelity""bhattacharyya""hellinger" [28]"matusita""squared_chord""squared_euclidean" [31]"pearson""neyman""squared_chi" [34]"prob_symm""divergence""clark" [37]"additive_symm""kullback-leibler""jeffreys" [40]"k_divergence""topsoe""jensen-shannon" [43]"jensen_difference""taneja""kumar-johnson" [46]"avg"
函数distance()是philentropy包中的核心函数,用于计算各种距离。其中的参数method可以设置为上面46种算法之一。参数method的默认值为“euclidean”,即计算欧氏距离。例如,1.3.1节中计算的欧氏距离也可以用下面的命令实现:
>distance(bio[1:5,]) Metric:'euclidean';comparing:5vectors. v1v2v3v4v5 v10.0000007.0144219.03724029.03126925.015119 v27.0144210.0000002.10888622.02427118.007346 v39.0372402.1088860.00000020.00919016.038264 v429.03126922.02427120.0091900.0000004.196737 v525.01511918.00734616.0382644.1967370.000000
再如,本小节前面两个变量的夹角余弦也可以用下面的命令实现:
>distance(rbind(x,y),method='cosine') Metric:'cosine';comparing:2vectors. cosine 0.9770776
上面的命令用函数rbind()将两个变量x和y按行排列。这是因为函数distance()计算的是行与行之间的距离或相关系数。在通常情况下,矩阵或者数据框的行表示记录、列表示变量。因此,在计算变量之间的相关系数时,需要将矩阵或者数据框用函数t()作行与列的转置。
>distance(t(scale(bio)),method='cosine') Metric:'cosine';comparing:4vectors. v1v2v3v4 v11.0000000-0.63727590.74602670.5176411 v2-0.63727591.0000000-0.9206450-0.6577195 v30.7460267-0.92064501.00000000.7014260 v40.5176411-0.65771950.70142601.0000000
上面的命令将数据框bio标准化后计算了各个变量之间的夹角余弦,此时的夹角余弦等价于Pearson相关系数。
>cor(bio) FIBlnPTPTAlnCHE FIB1.0000000-0.63727590.74602670.5176411 lnPT-0.63727591.0000000-0.9206450-0.6577195 PTA0.7460267-0.92064501.00000000.7014260 lnCHE0.5176411-0.65771950.70142601.0000000
1.3.5 列联系数
对于分类变量,常用列联系数(contingency coefficient)表示列联表资料的关联强度。常用的列联系数有Phi系数、Pearson列联系数和克莱姆V系数。
Phi系数只适用于四格表资料,其计算公式为
(1.11)
Pearson列联系数是Phi系数的校正和推广,可以用于多维列联表资料,其计算公式为
(1.12)
克莱姆V系数是在列联表行列数不同时对Pearson列联系数的修正方法,其计算公式为
(1.13)
式(1.11)、式(1.12)和式(1.13)中,为列联表的值,n为样本量,r和c分别是列联表的行数和列数。
上面3种列联系数的取值范围都在0和1之间。值越接近0,行变量和列变量关系越不密切;值越接近1,行变量和列变量关系越密切。vcd包里的函数assocstats()可以用来计算上述3种列联系数,例如:
>mytable<-table(cirr$sex,cirr$agegrp) >mytable <4040-5960+ female274 male3164 >library(vcd) >assocstats(mytable) X^2dfP(>X^2) LikelihoodRatio1.004320.60522 Pearson1.022920.59963 Phi-Coefficient:NA ContingencyCoeff.:0.166 Cramer'sV:0.169
结果显示,值为1.0229,Pearson列联系数和克莱姆V系数分别为0.166和0.169。这表明在该数据集里,性别和年龄组之间的关联比较弱。由于上面的列联表是2行3列的,Phi系数在这里不适用,所以给出的结果是NA。