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