克莱姆V(克莱姆相关系数、克莱姆关联系数、独立系数)的MATLAB计算

        前些时间需要衡量多个分类数据之间两两相关程度,想找出最相关的一对分类数据;于是想到了曾经看过的克莱姆相关系数,但在网上搜了好久之后,即没发现Matlab现成的built-in函数,也没找到别人分享的Matlab代码,于是决定自己动手写一个~

        克莱姆V(Cramer’s V),又称为克莱姆相关系数、克莱姆关联系数、独立系数等,是双变量相关分析的一种方法,专门用于衡量分类数据与分类数据之间相关程度。该系数取值范围为0到1,0表示两个变量无关,1表示完全相关。

        这里主要参考【高桥 信/著, 陈刚/译. 漫画统计学. 科学出版社, 2009: 127-142.】中的内容,基于matlab实现计算克莱姆V的函数。首先给出函数代码:

function [ cramer_V ] = CramersV( x1,x2 )
%Author: https://blog.csdn.net/jbb0523
%Version: 1.0@2019-05-27
%Description: compute variable Cramer's V between x1&x2
%Reference: 高桥 信/著, 陈刚/译. 漫画统计学. 科学出版社, 2009: 127-142.
    %Step 1: Observed frequency(contigency table )
    sym_x1 = unique(x1);
    sym_x2 = unique(x2);
    contigency_tab = zeros(length(sym_x1),length(sym_x2));
    for i=1:length(sym_x1)
        for j=1:length(sym_x2)
            ind_x1 = (x1==sym_x1(i));
            ind_x2 = (x2==sym_x2(j));
            contigency_tab(i,j) = sum(ind_x1&ind_x2);
        end
    end

    %Step 2: Expected frequency
    contigency_mean = zeros(length(sym_x1),length(sym_x2));
    for i=1:length(sym_x1)
        for j=1:length(sym_x2)
            contigency_mean(i,j) = sum(contigency_tab(i,:))*sum(contigency_tab(:,j))/sum(contigency_tab(:));
        end
    end

    %Step 3&4: Pearson chi-square statistic
    chi_square = sum(sum(((contigency_tab - contigency_mean).^2)./contigency_mean));

    %Step 5: Cramer's V
    cramer_V = sqrt(chi_square/sum(contigency_tab(:))/(min(length(sym_x1),length(sym_x2))-1));
end

整个计算过程其实很简单,这里简要解释一下:

        Step1对应于Reference中的步骤1(P130),即计算列联表(contingency table),也就是下图中框内的数据:

克莱姆V(克莱姆相关系数、克莱姆关联系数、独立系数)的MATLAB计算_第1张图片

        Step2对应于Reference中的步骤2(P130),计算期望次数,方框内的每个元素实际上就是第1步列联表对应的该行元素之和乘以该列元素之和再除以所有元素之和(例如女性行、打电话列为148*72/300,148为女性行元素之和(34+61+53),72为打电话列元素之和(34+38),300为所有元素之和(34+61+53+38+40+74)):

克莱姆V(克莱姆相关系数、克莱姆关联系数、独立系数)的MATLAB计算_第2张图片

        接下来计算皮尔森卡方统计量之值,在Reference中分两步完成,这里合二为一:

其中((contigency_tab - contigency_mean).^2)./contigency_mean对应于Reference中的步骤3(P131):

克莱姆V(克莱姆相关系数、克莱姆关联系数、独立系数)的MATLAB计算_第3张图片

        然后用两层sum求和实现计算矩阵元素之和,即Reference步骤4(P132):

克莱姆V(克莱姆相关系数、克莱姆关联系数、独立系数)的MATLAB计算_第4张图片

        最后一行计算Cramer’s V,这里计算列联表元素之和用sum(contigency_tab(:))实现,其中(:)表示将矩阵变为一个向量,即步骤5(P133):

克莱姆V(克莱姆相关系数、克莱姆关联系数、独立系数)的MATLAB计算_第5张图片

有了以上函数之后,可以执行以下三行代码计算Reference中第127~133页的例子:

x1 = [ones(148,1);2*ones(152,1)];
x2 = [ones(34,1);2*ones(61,1);3*ones(53,1);ones(38,1);2*ones(40,1);3*ones(74,1)];
cramer_V= CramersV(x1,x2)

程序输出为0.1634,说明程序是正确的。

 

        Reference的第138页还有一个例题,列联表如下:

克莱姆V(克莱姆相关系数、克莱姆关联系数、独立系数)的MATLAB计算_第6张图片

执行以下三行代码:

x1=[ones(43,1);2*ones(51,1);3*ones(29,1);ones(33,1);2*ones(53,1);3*ones(41,1)];
x2=[ones(123,1);2*ones(127,1)];
cramer_V= CramersV(x1,x2)

程序输出为0.1157,与Reference第141页给出的结果相同。

 

        注意:以上均使用1、2、3等表示分类数据中的类别,具体问题随意,只要输入的x1和x2是两个包含有限类别个数的向量即可,至于用哪个数据表示哪个类别并没有限制,因为在最开始给出的CramersV函数里使用了Matlab的built-in函数unique来识别包含哪些类别。

你可能感兴趣的:(理论/笔记)