问题描述
我正在尝试过滤以下熊猫数据框。
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 值。如果 X
和 M
的计数大于或等于 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 {{1} } 值,然后相应地创建掩码,最后使用掩码得到所需的结果。
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)]