Pandas,如何使用带有多索引数据框的子集来删除值?

Pandas, how to dropna values using subset with multiindex dataframe?

我有一个包含多索引列的数据框。

我需要从此数据框中删除列子集中具有 NaN 值的行。

我正在尝试使用 pd.dropnasubset 选项,但我没能找到指定列子集的方法。我试过使用 pd.IndexSlice 但这不起作用。

在下面的示例中,我需要搭乘最后一排。

import pandas as pd

# ---
a = [1, 1, 2, 2, 3, 3]
b = ["a", "b", "a", "b", "a", "b"]
col = pd.MultiIndex.from_arrays([a[:], b[:]])
val = [
    [1, 2, 3, 4, 5, 6],
    [None, None, 1, 2, 3, 4],
    [None, 1, 2, 3, 4, 5],
    [None, None, 5, 3, 3, 2],
    [None, None, None, None, 5, 7],
]
# ---
df = pd.DataFrame(val, columns=col)
# ---
print(df)
# ---
idx = pd.IndexSlice
df.dropna(axis=0, how="all", subset=idx[1:2, :])
# ---
print(df)

使用 thresh 选项是一种替代方法,但如果可能的话,我想使用 subsethow='all'

在处理MultiIndex时,MultiIndex的每一列都可以指定为一个元组:

In [67]: df.dropna(axis=0, how="all", subset=[(1, 'a'), (1, 'b'), (2, 'a'), (2, 'b')])
Out[67]: 
     1         2       3   
     a    b    a    b  a  b
0  1.0  2.0  3.0  4.0  5  6
1  NaN  NaN  1.0  2.0  3  4
2  NaN  1.0  2.0  3.0  4  5
3  NaN  NaN  5.0  3.0  3  2

或者,对于 select 第一级等于 12 的所有列,您可以使用:

In [69]: df.dropna(axis=0, how="all", subset=df.loc[[], [1,2]].columns)
Out[69]: 
     1         2       3   
     a    b    a    b  a  b
0  1.0  2.0  3.0  4.0  5  6
1  NaN  NaN  1.0  2.0  3  4
2  NaN  1.0  2.0  3.0  4  5
3  NaN  NaN  5.0  3.0  3  2

df[[1,2]].columns 也可以,但是这个 returns 是一个(可能很大的)中间 DataFrame。 df.loc[[], [1,2]].columns 更节省内存,因为它的中间 DataFrame 是空的。

如果要将dropna应用到级别1中有1或2的列,您可以按如下方式进行:

cols= [(c0, c1) for (c0, c1) in df.columns if c0 in [1,2]]
df.dropna(axis=0, how="all", subset=cols)

如果应用于您的数据,结果为:

Out[446]: 
     1         2       3   
     a    b    a    b  a  b
0  1.0  2.0  3.0  4.0  5  6
1  NaN  NaN  1.0  2.0  3  4
2  NaN  1.0  2.0  3.0  4  5
3  NaN  NaN  5.0  3.0  3  2

如您所见,最后一行 (index=4) 不见了,因为 1 和 2 以下的所有列都是此行的 NaN。如果您希望删除列中出现任何 NaN 的所有行,您需要:

df.dropna(axis=0, how="any", subset=cols)

这导致:

Out[447]: 
     1         2       3   
     a    b    a    b  a  b
0  1.0  2.0  3.0  4.0  5  6