克莱姆V(克莱姆相关系数、克莱姆关联系数、独立系数)

    科技2023-10-19  100

    前些时间需要衡量多个分类数据之间两两相关程度,想找出最相关的一对分类数据;于是想到了曾经看过的克莱姆相关系数,但在网上搜了好久之后,即没发现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),也就是下图中框内的数据:

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

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

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

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

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

    有了以上函数之后,可以执行以下三行代码计算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页还有一个例题,列联表如下:

    执行以下三行代码:

    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来识别包含哪些类别。

    补充@20200215:若想在论文中引用Cramer's V,可参考如下文献:

    直接搜索Cramer's V可以搜到以下文献:

    [1] Michael W. Kearney, Cramér's V, In book: Sage Encyclopedia of Communication Research Methods, Publisher: Sage (https://www.researchgate.net/publication/307963787_Cramer's_V)

    以上文献影响似乎不是很有影响,在wikipedia (http://en.volupedia.org/wiki/Cram%C3%A9r%27s_V 或 https://en.academic.ru/dic.nsf/enwiki/11586155),包括以上文献中,都提到了Cramer本人所著的专著: [2] Cramér, Harald. 1946. Mathematical Methods of Statistics. Princeton: Princeton University Press, page 282 (Chapter 21. The two-dimensional case).

    这本书是1946年的,也有人引用为1999年,是第N次印刷的时间,没有找到好的资源,以下链接可供参考:http://www.doc88.com/p-6059182784178.html

    Processed: 0.026, SQL: 8