【问题标题】:Pandas row filtering on multiple columnsPandas 在多列上进行行过滤
【发布时间】:2021-08-27 09:53:55
【问题描述】:
我正在尝试过滤以下 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,因为它们尊重约束。
感谢任何可以提供帮助的人。
【问题讨论】:
标签:
python
pandas
dataframe
statistics
【解决方案1】:
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
请注意,这假设这些值为NaNs;如果不是字符串,那么请事先这样做:
df = df.replace("Nan", np.nan)
【解决方案2】:
您可以先分离出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