Python DataFrame做t-test求特征p值返回nan,如何提取各特征p值?
问题原因与解决方案
1. 返回nan的核心原因
scipy.stats.ttest_ind的作用是检验两组独立连续样本的均值是否存在显著差异,你的传参逻辑不符合函数要求:
你需要对比的是MinTemp这个连续特征,在「明日下雨」和「明日不下雨」两个分组下的均值差异,而非直接把标签列RainTomorrow和特征列MinTemp作为两组样本传入。此外数据中存在空值也会导致t检验返回nan结果。
2. 单个特征p值的正确计算代码
先按标签对特征分组,再传入检验,同时开启跳过空值的参数即可:
from scipy import stats # 按RainTomorrow分组提取MinTemp的两组值 # 若你的RainTomorrow已编码为数值(1=下雨/0=不下雨),把下方的'Yes'/'No'替换为1/0即可 group_rain = df2[df2['RainTomorrow'] == 'Yes']['MinTemp'].dropna() group_norain = df2[df2['RainTomorrow'] == 'No']['MinTemp'].dropna() # 执行独立样本t检验,equal_var可根据方差齐性检验结果调整,默认True t_stat, p_value = stats.ttest_ind(group_rain, group_norain, equal_var=False, nan_policy='omit') print(f"MinTemp对应的p值为:{p_value}")
3. 批量提取所有数值特征p值的实现
如果需要一次性计算所有数值型特征对应的p值,可以用循环批量处理:
import pandas as pd from scipy import stats # 筛选所有数值型特征 numeric_features = df2.select_dtypes(include=['int64', 'float64']).columns.tolist() p_value_result = {} for feature in numeric_features: group_rain = df2[df2['RainTomorrow'] == 'Yes'][feature].dropna() group_norain = df2[df2['RainTomorrow'] == 'No'][feature].dropna() # 兼容某组全为空的极端情况 if len(group_rain) == 0 or len(group_norain) == 0: p_value_result[feature] = None continue t_stat, p_val = stats.ttest_ind(group_rain, group_norain, equal_var=False, nan_policy='omit') p_value_result[feature] = p_val # 转换为DataFrame并按p值从小到大排序,方便后续筛选特征 p_df = pd.DataFrame(p_value_result.items(), columns=['特征名', 'p值']).sort_values(by='p值', ascending=True) print(p_df)
注意事项
- 独立样本t检验仅适用于「数值型特征+二分类标签」的显著性检验,如果是类别型特征需要改用卡方检验
- t检验的前提是样本近似服从正态分布、两组方差齐,如果你的数据不符合前提可以改用曼惠特尼U检验
内容的提问来源于stack exchange,提问作者Tobias Funke
相关产品推荐
相关产品推荐

