Pandas 对多列进行行过滤

Pandas row filtering on multiple columns

我正在尝试过滤以下 pandas 数据框。

    id        X_1      X_2    X_4     M_1       M_2     M_3 
0    i24     Nan     0.27     Nan     0.20     0.25    0.27 
1    i25     0.45    0.47     0.46    0.42     Nan     0.42  
2    i11     Nan     Nan      0.32    0.32     0.35    0.29    
3    i47     Nan     0.56     0.59     Nan     0.56    0.51 

特别是,我想分别处理 M_ 列和 X_columns 并且只保留那些对于每个“组”M 和 X 至少有两个非 Nan 值的条目。 例如。不应包括条目 i24,因为它在 X_1 和 X_4 中的值都是 Nan,在 X“组”中只留下一个正确的值。 i25 和 i47 应该保留,因为它们尊重约束。

感谢任何能提供帮助的人。

ndf = df.set_index("id")
good_rows = (ndf.groupby(lambda col: col.split("_", maxsplit=1)[0], axis=1)
                .count()
                .ge(2)
                .all(axis=1))
ndf = ndf.loc[good_rows]

这里我们先设置id作为索引,放在一边。然后按列名称分组,直到第一个 _,然后计算非 NaN 值。如果 XM 计数都大于或等于 2,我们称它为好行。然后用这些行建立索引,

得到

>>> ndf

      X_1   X_2   X_4   M_1   M_2   M_3
id
i25  0.45  0.47  0.46  0.42   NaN  0.42
i47   NaN  0.56  0.59   NaN  0.56  0.51

请注意,这假设这些值为 NaN;如果不是字符串,请事先执行此操作:

df = df.replace("Nan", np.nan)

可以先把X列和M列的列表分开,然后用apply检查两个列组是否满足小于2的条件NaN 值,然后相应地创建掩码,最后使用掩码得到所需的结果。

xCols = [col for col in df if col.startswith('X')]  # ['X_1', 'X_2', 'X_4']
mCols = [col for col in df if col.startswith('M')]  # ['M_1', 'M_2', 'M_3']

df[df.apply(lambda row: sum(row[mCols].isna())<2 and sum(row[xCols].isna())<2, axis=1)]

输出:

    id   X_1   X_2   X_4   M_1   M_2   M_3
1  i25  0.45  0.47  0.46  0.42   NaN  0.42
3  i47   NaN  0.56  0.59   NaN  0.56  0.51