首页 > 解决方案 > 根据不同列子集的组合删除具有 NaN 的行

问题描述

我想根据列子集的组合删除所有具有 NaN 值的行。让我们用一个简单的例子来证明这一点:

df = pd.DataFrame(
    [[1, np.nan, 3, 4], [1, 2, 3, 4], [np.nan, np.nan, 3, 4], [1, np.nan, np.nan, 4], [1, 2, np.nan, np.nan]],
    columns=["a1", "a2", "b1", "b2"],
)

print(df)
#    a1   a2   b1   b2
# 0  1.0  NaN  3.0  4.0
# 1  1.0  2.0  3.0  4.0
# 2  NaN  NaN  3.0  4.0
# 3  1.0  NaN  NaN  4.0
# 4  1.0  2.0  NaN  NaN

而且我想删除其中任何一个集合中的所有功能都是NaN的行。所以输出将是(删除第 2 行和第 4 行):{a1, a2}{b1, b2}

   a1   a2   b1   b2
0  1.0  NaN  3.0  4.0
1  1.0  2.0  3.0  4.0
3  1.0  NaN  NaN  4.0

理想情况下,我需要一些df.dropna(how="all", subset=["a1", "a2"])和的组合df.dropna(how="all", subset=["b1", "b2"])。在这个简单的情况下,这不会是这样的问题,但是如果有 10 个不同的子集呢?(在我的真实场景中,它几乎是 50。)

是否有任何使用 pandas 或任何过滤器的智能解决方案如何组合这些子集并为dropna方法创造正确的条件?

动机:只是为了让您了解为什么我需要这样的东西,因为我有不同的功能集(a, b, ...),它们组合在一个 DataFrame 中,我需要分别处理这些功能。一些 NaN 是可以的,但是如果任何特征的任何行都充满了 NaN,这意味着测量错误,我也想为任何其他特征删除这一行(想象一下索引是测量时间,如果一组功能不正确,即使其他功能都很好,我也不想保留它)。

标签: pythonpandasdataframe

解决方案


方法

对于subset预定义列表中的每个,subsets您可以测试该子集的列是否存在任何非NaNaxis=1以创建一个布尔掩码,然后您可以reduce使用与每个子集对应的所有布尔掩码np.logical_and来创建一个结果布尔值mask,然后可用于过滤数据框中的行。

subs = [{'a1', 'a2'}, {'b1', 'b2'}]
mask = np.logical_and.reduce([df[s].notna().any(1) for s in subs])

结果

>>> df[mask]

    a1   a2   b1   b2
0  1.0  NaN  3.0  4.0
1  1.0  2.0  3.0  4.0
3  1.0  NaN  NaN  4.0

推荐阅读