使用pandas,计算Cramér的系数矩阵

not*_*ing 22 python statistics pandas

我有一个数据框,pandas其中包含在维基百科文章中计算的指标.nation文章所涉及的两个分类变量,以及lang取自哪种语言维基百科.对于单个指标,我想看看国家和语言变量的相关程度,我相信这是使用Cramer的统计数据完成的.

index   qid     subj    nation  lang    metric          value
5   Q3488399    economy     cdi     fr  informativeness 0.787117
6   Q3488399    economy     cdi     fr  referencerate   0.000945
7   Q3488399    economy     cdi     fr  completeness    43.200000
8   Q3488399    economy     cdi     fr  numheadings     11.000000
9   Q3488399    economy     cdi     fr  articlelength   3176.000000
10  Q7195441    economy     cdi     en  informativeness 0.626570
11  Q7195441    economy     cdi     en  referencerate   0.008610
12  Q7195441    economy     cdi     en  completeness    6.400000
13  Q7195441    economy     cdi     en  numheadings     7.000000
14  Q7195441    economy     cdi     en  articlelength   2323.000000
Run Code Online (Sandbox Code Playgroud)

我想生成一个矩阵,显示所有国家(法国,美国,科特迪瓦和乌干达)['fra','usa','uga']和三种语言组合之间的克莱默系数['fr','en','sw'].所以会产生一个4乘3的矩阵,如:

       en         fr          sw
usa    Cramer11   Cramer12    ... 
fra    Cramer21   Cramer22    ... 
cdi    ...
uga    ...
Run Code Online (Sandbox Code Playgroud)

最后,我将针对我正在跟踪的所有不同指标执行此操作.

for subject in list_of_subjects:
    for metric in list_of_metrics:
        cramer_matrix(metric, df)
Run Code Online (Sandbox Code Playgroud)

然后,我可以检验我的假设,即语言为维基百科语言的文章的指标会更高.谢谢

Zig*_*ien 27

在我做过的一些测试中,cramers V似乎非常乐观.维基百科推荐更正版本.

def cramers_corrected_stat(confusion_matrix):
    """ calculate Cramers V statistic for categorial-categorial association.
        uses correction from Bergsma and Wicher, 
        Journal of the Korean Statistical Society 42 (2013): 323-328
    """
    chi2 = ss.chi2_contingency(confusion_matrix)[0]
    n = confusion_matrix.sum()
    phi2 = chi2/n
    r,k = confusion_matrix.shape
    phi2corr = max(0, phi2 - ((k-1)*(r-1))/(n-1))    
    rcorr = r - ((r-1)**2)/(n-1)
    kcorr = k - ((k-1)**2)/(n-1)
    return np.sqrt(phi2corr / min( (kcorr-1), (rcorr-1)))
Run Code Online (Sandbox Code Playgroud)

另请注意,混淆矩阵可以通过内置的pandas方法计算分类列,方法如下:

import pandas as pd
confusion_matrix = pd.crosstab(df[column1], df[column2])
Run Code Online (Sandbox Code Playgroud)

  • 这很棒@Ziggy!如果混淆矩阵是使用`pd.crosstab(df [column1],df [column2])`计算的,那么`n = confusion_matrix.sum()`需要是`n = confusion_matrix.sum(). sum()`(`numpy`总和所有维度,`pandas`,只有一个.很棒的答案和非常易读的代码. (16认同)
  • 我认为上面的函数需要一个 2d numpy 数组作为输入,而不是 pandas 对象。它可能适用于 `confusion_matrix = pd.crosstab(df[column1], df[column2]).to_numpy()` (3认同)

Rom*_*anS 6

Cramer的V统计量允许理解一个数据集中两个分类特征之间的相关性.所以,这是你的情况.

要计算Cramers V统计量,您需要计算混淆矩阵.因此,解决方案步骤如下:
1.过滤单个度量的数据
2.计算混淆矩阵
3.计算Cramers V统计量

当然,您可以在帖子中提供的循环嵌套中执行这些步骤.但是在你的起始段落中,你只提到了指标作为外部参数,所以我不确定你是否需要两个循环.现在,我将提供步骤2-3的代码,因为过滤很简单,正如我所提到的,我不确定你需要什么.

步骤2.在下面的代码中,按步骤1中的任何data内容进行pandas.dataFrame过滤.

import numpy as np

confusions = []
for nation in list_of_nations:
    for language in list_of_languges:
        cond = data['nation'] == nation and data['lang'] == language
        confusions.append(cond.sum())
confusion_matrix = np.array(confusions).reshape(len(list_of_nations), len(list_of_languges))
Run Code Online (Sandbox Code Playgroud)

步骤3.在下面的代码中confusion_matrixnumpy.ndarray在步骤2中获得的.

import numpy as np
import scipy.stats as ss

def cramers_stat(confusion_matrix):
    chi2 = ss.chi2_contingency(confusion_matrix)[0]
    n = confusion_matrix.sum()
    return np.sqrt(chi2 / (n*(min(confusion_matrix.shape)-1)))

result = cramers_stat(confusion_matrix)
Run Code Online (Sandbox Code Playgroud)

此代码已在我的数据集上进行了测试,但我希望可以在不更改的情况下使用它.


Yur*_*let 5

Ziggy Eunicien的回答对功能做了一些修改。添加了2个修改1)检查一个变量为常数2)校正ss.chi2_contingency(conf_matrix,Correction = correct)-如果混淆矩阵为2x2,则为FALSE

import scipy.stats as ss
import pandas as pd
import numpy as np
def cramers_corrected_stat(x,y):

    """ calculate Cramers V statistic for categorial-categorial association.
        uses correction from Bergsma and Wicher, 
        Journal of the Korean Statistical Society 42 (2013): 323-328
    """
    result=-1
    if len(x.value_counts())==1 :
        print("First variable is constant")
    elif len(y.value_counts())==1:
        print("Second variable is constant")
    else:   
        conf_matrix=pd.crosstab(x, y)

        if conf_matrix.shape[0]==2:
            correct=False
        else:
            correct=True

        chi2 = ss.chi2_contingency(conf_matrix, correction=correct)[0]

        n = sum(conf_matrix.sum())
        phi2 = chi2/n
        r,k = conf_matrix.shape
        phi2corr = max(0, phi2 - ((k-1)*(r-1))/(n-1))    
        rcorr = r - ((r-1)**2)/(n-1)
        kcorr = k - ((k-1)**2)/(n-1)
        result=np.sqrt(phi2corr / min( (kcorr-1), (rcorr-1)))
    return round(result,6)
Run Code Online (Sandbox Code Playgroud)


小智 5

使用 Association-metrics python 包从 pandas.DataFrame 对象计算 Cram\xc3\xa9r\ 的系数矩阵,这非常简单,让我向您展示:

\n

首先使用以下命令安装关联指标:

\n
pip install association-metrics\n
Run Code Online (Sandbox Code Playgroud)\n

然后,您可以使用以下伪代码

\n
# Import association_metrics  \nimport association_metrics as am\n# Convert you str columns to Category columns\ndf = df.apply(\n        lambda x: x.astype("category") if x.dtype == "O" else x)\n\n# Initialize a CamresV object using you pandas.DataFrame\ncramersv = am.CramersV(df) \n# will return a pairwise matrix filled with Cramer\'s V, where columns and index are \n# the categorical variables of the passed pandas.DataFrame\ncramersv.fit()\n
Run Code Online (Sandbox Code Playgroud)\n

包裹信息

\n