You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

scipy.stats卡方独立性检验报期望频数为零、p值异常解决

报错原因
  • 零期望频数报错:卡方独立性检验的适用前提是列联表所有单元格的期望频数不小于1,且期望频数小于5的单元格占比不超过20%。第9列检验时报(1,0)位置期望频数为0,说明该列与covid19列交叉分组后存在空单元格(即两个分类的交叉组合没有任何观测样本),不满足卡方检验的适用条件。
  • p值大于1的异常:生成列联表时设置了margins=True,该参数会在列联表末尾追加行、列的合计值。如果把带合计值的列联表直接传入chi2_contingency,函数会将合计行、合计列识别为独立的分类水平,导致自由度计算完全错误,最终输出超出[0,1]合理范围的无效p值。
  • 原有代码的额外隐患:硬编码切片0:5截取列联表数值,默认每列都有5个分类水平,一旦某列的分类数不等于5,就会截取到错误的观测矩阵,直接导致计算结果失真。
修正方案

直接使用不带边际合计的原始列联表传入检验函数,不要硬编码切片,同时增加期望频数校验逻辑,对不满足卡方检验前提的场景做兼容处理,修正后的代码如下:

import pandas as pd
import numpy as np
from scipy.stats import chi2_contingency, fisher_exact

def independence_test(col_1, col_2="covid19", merge_low_freq=False):
    # 生成无合计值的原始列联表,禁止加margins=True
    ct = pd.crosstab(df[col_2], df[col_1])
    obs = ct.values

    # 初次计算获取期望频数
    chi2, p, dof, expected = chi2_contingency(obs, correction=False)
    min_expected = expected.min()

    if min_expected < 1:
        if merge_low_freq:
            # 方案1:合并低频分类,将列方向频数<5的分类合并为「其他」组,可根据业务规则调整阈值
            col_totals = ct.sum(axis=0)
            low_cats = col_totals[col_totals < 5].index
            df_copy = df.copy()
            df_copy[col_1] = df_copy[col_1].replace({cat: "其他" for cat in low_cats})
            ct_new = pd.crosstab(df_copy[col_2], df_copy[col_1])
            chi2, p, dof, expected = chi2_contingency(ct_new.values, correction=False)
            return ("chi2_test", chi2, p, dof)
        else:
            # 方案2:不满足卡方前提时,切换为费希尔精确检验(适合小样本/空单元格场景)
            odds_ratio, p_fisher = fisher_exact(obs)
            return ("fisher_exact", odds_ratio, p_fisher)
    
    return ("chi2_test", chi2, p, dof)
注意事项
  • 传入统计检验函数的列联表必须是纯交叉计数的原始矩阵,不要加入边际合计、占比等人工计算的衍生行列。
  • 不要硬编码分类数做切片,不同字段的分类水平数量可能存在差异,直接取列联表的values属性即可拿到正确的观测矩阵。
  • 若列联表维度超过2x2、样本量较大但存在少量低期望频数单元格,可开启chi2_contingency的correction=True参数做连续性修正,结果会更稳健。

内容的提问来源于stack exchange,提问作者berkaiii

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.29 17:03:17