用Pandas处理DataFrame列计算卡方值结果不符,如何解决?
问题根源与修正方案
核心错误分析
你的代码存在两个关键问题,直接导致卡方检验结果完全偏离预期:
- 错误使用
pd.crosstab:你的数据集里Observed是每个分组的观测频数,Expected是对应分组的期望频数,并非两个独立的分类变量。用pd.crosstab会生成观测值与期望值的交叉计数表,这完全不是卡方检验需要的输入结构,最终得到的列联表毫无统计意义。 - 混淆卡方检验类型:你要做的是拟合优度卡方检验(验证观测频数是否符合给定的期望分布),但误用了用于独立性检验的
chi2_contingency函数。后者要求输入的是两个分类变量的交叉频数表,而不是单组观测与期望的对应数组。
修正步骤
1. 正确提取DataFrame列
直接从DataFrame中提取观测和期望的数值数组即可,不需要生成交叉表:
obs = df['Observed'].values exp = df['Expected'].values
2. 使用拟合优度卡方检验
调用scipy.stats.chisquare函数(专门用于拟合优度检验),传入观测数组和期望数组:
from scipy.stats import chisquare c, p = chisquare(obs, f_exp=exp)
3. 验证结果
拟合优度检验的自由度为类别数-1,这里有11个分组,自由度为10。计算后得到的p值会接近预期的0.411,卡方统计量也会符合理论计算值。
修正后的完整代码
import pandas as pd from scipy.stats import chisquare import logging logging.basicConfig(level=logging.DEBUG, format='%(asctime)s - %(levelname)s - %(message)s') # 读取数据集 df = pd.read_csv('dice_rolls.csv') logging.debug(f"观测频数:\n{df['Observed']}") logging.debug(f"期望频数:\n{df['Expected']}") # 提取观测和期望数组 obs = df['Observed'].values exp = df['Expected'].values # 执行拟合优度卡方检验 c, p = chisquare(obs, f_exp=exp) dof = len(obs) - 1 # 计算自由度 # 输出结果 logging.debug(f'卡方统计量: {c}') logging.debug(f'p值: {p}') logging.debug(f'自由度: {dof}')
预期输出说明
运行修正后的代码,会得到:
- 卡方统计量约为10.656
- p值约为0.411
- 自由度为10
完全符合你的预期结果。
内容的提问来源于stack exchange,提问作者Evan Gertis
相关产品推荐
相关产品推荐

