17370845950

如何筛选DataFrame中指定列存在多个非零不同值的行

本文介绍一种简洁高效的方法,使用pandas的`replace`与`nunique`组合,快速识别在特定列中(排除0后)包含超过1个不同非零值的数据行。

在数据分析中,常

需检测某几列是否“一致”——例如多列编码字段本应相同或为0,若出现多个非零且互异的值,则可能表示异常或特殊逻辑分支。原始实现通过apply(pd.unique)配合复杂lambda判断,不仅可读性差、性能低,还易出错。

更优解是利用pandas内置的统计能力:将0替换为NaN(自然被nunique忽略),再按行计算非空唯一值数量。nunique(axis=1)默认自动跳过NaN,因此只需一步即可完成“排除0后统计不同非零值个数”的核心逻辑。

以下是完整示例代码:

import pandas as pd

df = pd.DataFrame({
    'id': [1, 2, 3, 4],
    'col_A': [1, 1, 1, 0],
    'col_B': [2, 1, 0, 2],
    'col_C': [3, 1, 0, 3],
    'col_D': [4, 1, 1, 4],
    'col_E': [5, 1, 1, 5]
})

# 筛选 col_ 开头的列,将0替换为NaN,按行统计非空唯一值数量 > 1 的行
mask = df.filter(like='col_').replace(0, float('nan')).nunique(axis=1) > 1
result = df[mask].copy()

print(result)

输出:

   id  col_A  col_B  col_C  col_D  col_E
0   1      1      2      3      4      5
3   4      0      2      3      4      5

关键优势

  • 语义清晰:replace(0, NaN) + nunique() 直观表达“忽略零值后统计不同值”;
  • 性能优异:避免逐行apply,全程向量化操作;
  • 健壮性强:nunique天然处理NaN,无需额外条件判断;
  • 灵活可扩展:只需修改filter()条件(如filter(regex=r'^code_'))即可适配任意列名模式。

⚠️ 注意事项

  • 若数据中已存在真实NaN,需先明确其业务含义——本方法会将其与0一并排除在计数外;
  • float('nan')可简写为np.nan(需导入import numpy as np),效果一致;
  • 如需保留原始列不变,建议对筛选结果使用.copy()避免链式赋值警告。

该方法体现了pandas“用原生操作替代手动循环”的最佳实践,推荐作为类似场景的标准解决方案。