如何使用 NumPy 高效删除零方差列

23次阅读

如何使用 NumPy 高效删除零方差列

本文介绍如何用一行简洁的 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() 调用。

text=ZqhQzanResources