Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/330.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 计算两列之间的chi sqaure_Python_Pandas_Scipy - Fatal编程技术网

Python 计算两列之间的chi sqaure

Python 计算两列之间的chi sqaure,python,pandas,scipy,Python,Pandas,Scipy,我想计算一个数据帧中成对列之间的卡方检验统计量。看来一定有一种方法可以做到这一点,就像pandas.corr 如果我有以下数据框 df = pd.DataFrame([['a', 'x', 'a'], ['b', 'z', 'a'], ['a', 'x', 'a']], columns=['ll', 'kk', 'jj'], index=['

我想计算一个数据帧中成对列之间的卡方检验统计量。看来一定有一种方法可以做到这一点,就像
pandas.corr

如果我有以下数据框

df = pd.DataFrame([['a', 'x', 'a'], 
                   ['b', 'z', 'a'], 
                   ['a', 'x', 'a']], 
                  columns=['ll', 'kk', 'jj'], 
                  index=['nn', 'oo', 'pp'])
我希望能够为以下内容提供帮助:

df.corr('chisquare')
尽管这显然会失败。如果数据帧是数字的,而不是分类的,我可以简单地执行
df.corr()
并传递spearman或pearson。必须有一种方法来计算所有列之间的chi sqaured

因此输出(使用
scipy.stats.chi2_contractive
)将是

我只是遗漏了一些东西,或者如果没有对流程的每个步骤进行单独编码,这是不可能的。我正在寻找类似于
pd.corr
但带有分类数据的东西

编辑: 为了澄清我目前正在做什么的任何困惑,以获得结果矩阵:

from itertools import combinations
def get_corr_mat(df, f=chi2_contingency):
    columns = df.columns
    dm = pd.DataFrame(index=columns, columns=columns)
    for var1, var2 in combinations(columns, 2):
        cont_table = pd.crosstab(df[var1], df[var2], margins=False)
        chi2_stat = f(cont_table)[0]
        dm.loc[var2, var1] = chi2_stat
        dm.loc[var1, var2] = chi2_stat
    dm.fillna(0, inplace=True)
    return dm

get_corr_mat(df) 
正如我之前所说的,这是可行的,尽管它可能会变慢,并且没有经过测试。熊猫方法更可取

替代方法1 另一种在两列之间找到卡方检验统计量以及热图可视化的方法:

def ch_calculate(df):
    factors_paired = [(i,j) for i in df.columns.values for j in df.columns.values] 

    chi2, p_values =[], []

    for f in factors_paired:
        if f[0] != f[1]:
            chitest = chi2_contingency(pd.crosstab(df[f[0]], df[f[1]]))   
            chi2.append(chitest[0])
            p_values.append(chitest[1])
        else:      # for same factor pair
            chi2.append(0)
            p_values.append(0)

    chi2 = np.array(chi2).reshape((len(df.columns),len(df.columns))) # shape it as a matrix
    chi2 = pd.DataFrame(chi2, index=df.columns.values, columns=df.columns.values) # then a df for convenience
    fig, ax = plt.subplots(figsize=(30,30))
    sns.heatmap(chi2, annot = True)
    plt.show()

ch_calculate(df_categorical)
其中,
df_category
是数据集所有标称输入变量的数据帧,对于有序分类变量,我认为最好使用
.corr(method='spearman')
(spearman秩相关系数)

使用Cramers V的替代方法2 我还遇到了这个Cramers V实现,以发现分类变量之间的关联程度: 通过使用这个函数,我创建了另一个函数来创建热图可视化,以查找相关的分类列(在Cramers V中,您将在热图中找到从0到1的值,其中0表示无关联,1表示高关联)


您能否更详细地解释一下,您是如何使用
scipy.stats.chi2_contractive
确定输出的?如何计算数据帧的元素?这将是相当多的代码,但是基本思想是,我从成对的列(向量)创建列联表,然后将其传递给
scipy.stats.chi2_列联
函数。可能有很多方法可以实现这一点,但令我惊讶的是,有一种方法可以实现数字而不是分类。这也不一定是一个chi-sqaure测试。我可以看到需要另一个测试的情况“我正在从成对的列(向量)创建一个列联表”抱歉,如果我速度慢,但这仍然不清楚。如何从三列创建二维列联表?(我可以看到如何制作一个三维列联表:计算数据中每个唯一行出现的次数,然后使用每行中的元素,就像它们是三维表的命名索引一样,并将计数放在该位置。)这基本上就是我所做的,对于每一对独特的列,将创建列联表,并计算和记录测试统计数据,然后将其放入最终矩阵中。这正是
pd.corr
的工作方式,除非我使用了不同的测试,因此报告了不同的统计数据,我明白了。我不知道有任何现有代码可以为您构建该表。
def ch_calculate(df):
    factors_paired = [(i,j) for i in df.columns.values for j in df.columns.values] 

    chi2, p_values =[], []

    for f in factors_paired:
        if f[0] != f[1]:
            chitest = chi2_contingency(pd.crosstab(df[f[0]], df[f[1]]))   
            chi2.append(chitest[0])
            p_values.append(chitest[1])
        else:      # for same factor pair
            chi2.append(0)
            p_values.append(0)

    chi2 = np.array(chi2).reshape((len(df.columns),len(df.columns))) # shape it as a matrix
    chi2 = pd.DataFrame(chi2, index=df.columns.values, columns=df.columns.values) # then a df for convenience
    fig, ax = plt.subplots(figsize=(30,30))
    sns.heatmap(chi2, annot = True)
    plt.show()

ch_calculate(df_categorical)
from itertools import combinations
from scipy.stats import chi2_contingency
import scipy.stats as ss
import seaborn as sns
def get_corr_mat(df, f=chi2_contingency):
        columns = df.columns
        dm = pd.DataFrame(index=columns, columns=columns)
        for var1, var2 in combinations(columns, 2):
            cont_table = pd.crosstab(df[var1], df[var2], margins=False)
            chi2_stat = cramers_v(cont_table.values)
            dm.loc[var2, var1] = chi2_stat
            dm.loc[var1, var2] = chi2_stat
        dm.fillna(1, inplace=True)
        return dm

def cramers_v(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)))

cat_corr= get_corr_mat(df_categorical)
fig, ax = plt.subplots(figsize=(30,30))
sns.heatmap(cat_corr, annot = True)
plt.show()