首页 > 解决方案 > 如何对熊猫数据框行执行卡方测试?

问题描述

我有一个表单的数据框df

          class_1_frequency    class_2_frequency
group_1          20                    10
group_2          60                    25 
..
group_n          50                    15 

假设 class_1 共有 70 个成员,而 class_2 有 30 个。

对于每一行(group_1,group_2,..group_n),我想创建列联表(最好是动态的),然后进行卡方检验来评估 p 值。

例如,对于 group_1,引擎盖下的列联表如下所示:

                   class_1      class_2
group_1_present      20           10
group_1_absent     70-20         30-10

另外,我知道scipy.stats.chi2_contingency()是 chisquare 的合适函数,但我无法将它应用到我的上下文中。我查看了之前讨论过的问题,例如:herehere

实现这一目标的最有效方法是什么?

标签: pythonpandasnumpyscipystatistics

解决方案


您可以利用 上的apply功能pd.DataFrame。它允许将任意函数应用于DataFrame. 使用您的示例:

df = pd.DataFrame([[20, 10], [60, 25], [50, 15]])

为了产生一个可以使用的列联表lambda和一些向量操作

>>> members = np.array([70, 30])
>>> df.apply(lambda x: np.array([x, members-x]), axis=1)
0    [[20, 10], [50, 20]]
1    [[60, 25], [10,  5]]
2    [[50, 15], [20, 15]]

这当然可以用scipy函数包装。

df.apply(lambda x: chi2_contingency(np.array([x, members-x])), axis=1)

这会产生所有可能的返回值,但是通过对输出进行切片,可以指定想要的返回值,例如留下预期的数组。结果系列也可以转换为DataFrame.

>>> s = df.apply(lambda x: chi2_contingency(np.array([x, members-x]))[:-1], axis=1)
>>> s
0    (0.056689342403628114, 0.8118072280034329, 1)
1                                    (0.0, 1.0, 1)
2      (3.349031920460492, 0.06724454934343391, 1)
dtype: object
>>> s.apply(pd.Series)
          0         1    2
0  0.056689  0.811807  1.0
1  0.000000  1.000000  1.0
2  3.349032  0.067245  1.0

现在我不知道这种方法的执行效率,但我相信那些实现了这些功能的人。而且很可能速度并不那么关键。但至少在它(假设)易于理解和快速编写的意义上是有效的。


推荐阅读