
本文介绍如何用一行简洁的 numpy 代码识别并剔除数组中所有方差为零(即所有非 nan 值完全相同)的列,同时兼容含 nan 的数据。
在数据预处理中,零方差特征(如全为同一常数、或除 NaN 外全部相同)通常不具备区分能力,应被移除以提升模型效率与稳定性。NumPy 提供了 np.var() 函数,默认会将 NaN 视为缺失值并导致整列方差为 nan;但直接使用 np.var(X, axis=0) != 0 会因 NaN 比较返回 False,从而错误丢弃含 NaN 的列——这正是需特别注意的关键点。
✅ 正确做法是:先显式忽略 NaN 计算方差,再筛选非零方差列。推荐使用 np.nanvar()(NumPy ≥ 1.10):
import numpy as np X = np.array([[1, 10, np.nan, 0], [2, 10, np.nan, 0], [3, 10, np.nan, 0]]) # ✅ 安全剔除零方差列(自动跳过 NaN) mask = np.nanvar(X, axis=0) != 0 # 返回布尔数组:[True, False, False, False] X_filtered = X[:, mask] print(X_filtered) # 输出: # [[ 1. nan] # [ 2. nan] # [ 3. nan]]
⚠️ 注意事项:
- np.var() 在含 NaN 时返回 nan,而 nan != 0 为 False,会导致本该保留的列(如第1列 [10,10,10])被误删;
- np.nanvar() 自动沿指定轴忽略 NaN 计算方差,对全 NaN 列返回 nan,此时建议额外处理(例如设 nanvar(…, ddof=0) 并用 np.isfinite() 过滤);
- 若需同时剔除全 NaN 列、全零列和零方差列,可合并布尔掩码:
mask = ( ~np.all(np.isnan(X), axis=0) & # 非全 NaN ~np.all(X == 0, axis=0) & # 非全零 np.nanvar(X, axis=0) != 0 # 非零方差(忽略 NaN) ) X = X[:, mask]
总结:np.nanvar(X, axis=0) != 0 是剔除零方差列最简洁、鲁棒且符合数据科学实践的标准方案,务必优先替代原始 np.var() 调用。