Pandas MultiIndex 中列的条件切片

Posted

技术标签:

【中文标题】Pandas MultiIndex 中列的条件切片【英文标题】:Conditional Slicing from Columns in Pandas MultiIndex 【发布时间】:2021-01-03 15:06:21 【问题描述】:

我正在尝试根据列名而不是索引有条件地从多索引中分割数据。例如,我有以下 MultiIndex 数据框:

   203        204         205
  TIME VALUE TIME VALUE  TIME VALUE
0    1   bar  1.0   LH2  10.0   dog
1    2   baz  2.0   LOX  11.0   cat
2    3   foo  3.0   CH4  12.0   pig
3    4   qux  NaN   NaN  13.0   rat
4    5   qaz  NaN   NaN   NaN   NaN
5    6   qoo  NaN   NaN   NaN   NaN

(我基本上有带有时间和值的测量数据(203、204 等),使用不同的采样率记录。因此,行数总是不同的。我将所有数据放入单个 MultiIndex,因为它可以包含不同数量的行。)

如果 TIME > 3,我想选择所有数据。预期输出如下:

   203        204         205
  TIME VALUE TIME VALUE  TIME VALUE
0    4   qux  NaN   NaN  10.0   dog
1    5   qaz  NaN   NaN  11.0   cat
2    6   qoo  NaN   NaN  12.0   pig
3   NaN  NaN  NaN   NaN  13.0   rat
4   NaN  NaN  NaN   NaN   NaN   NaN
5   NaN  NaN  NaN   NaN   NaN   NaN

我尝试使用查询方法,但它只适用于索引,而不适用于列名。我不想转置数据框以使用查询。我也尝试过使用 loc 但似乎从来没有找到一种方法来获得我想要的东西。我什至考虑过使用 xs,但我认为我不能用它添加条件切片。

我在 SO 上找到了这个,但它不包括条件切片: Selecting columns from pandas MultiIndex

这是我用来测试的代码:

import pandas as pd
import numpy as np

d1 = 'TIME': [1,2,3,4,5,6], 'VALUE': ['bar', 'baz', 'foo', 'qux', 'qaz', 'qoo']
df1 = pd.DataFrame(data=d1)

d2 = 'TIME': [1,2,3], 'VALUE': ['LH2', 'LOX', 'CH4']
df2 = pd.DataFrame(data=d2)

d3 = 'TIME': [10,11,12,13], 'VALUE': ['dog', 'cat', 'pig', 'rat']
df3 = pd.DataFrame(data=d3)

df_list = [df1, df2, df3] 

pids = [203, 204, 205]

df_multi = pd.concat(df_list, axis=1, keys=list(zip(pids)))

print(df_multi)

# Slice all time columns
ALL = slice(None)
df_multi_2 = df_multi.loc[ALL, (ALL, 'TIME')]
print(df_multi_2)

# Condition based slicing - does not work
ALL = slice(None)
df_multi_3 = df_multi.loc[ALL, df_multi.loc[ALL,(ALL,'TIME')] > 3]
print(df_multi_3)

【问题讨论】:

【参考方案1】:

让我们尝试IndexSlice 对数据进行切片:

from pandas import IndexSlice

mask = (df_multi.loc[:, IndexSlice[:,"TIME"]].gt(3)
    .reindex(df_multi.columns, axis=1)
    .groupby(level=0, axis=1)
    .transform('any')
)

df_multi.where(mask)

输出:

   203        204         205      
  TIME VALUE TIME VALUE  TIME VALUE
0  NaN   NaN  NaN   NaN  10.0   dog
1  NaN   NaN  NaN   NaN  11.0   cat
2  NaN   NaN  NaN   NaN  12.0   pig
3  4.0   qux  NaN   NaN  13.0   rat
4  5.0   qaz  NaN   NaN   NaN   NaN
5  6.0   qoo  NaN   NaN   NaN   NaN

【讨论】:

这是一个不错的解决方案。 transform('any') 有什么作用?掩码是否必须匹配相同形状的数据?

以上是关于Pandas MultiIndex 中列的条件切片的主要内容,如果未能解决你的问题,请参考以下文章

带有 MultiIndex Pandas 面板的切片函数

切片 pandas 的 MultiIndex DataFrame

pandas分层索引(层级索引MultiIndex)的创建取值切片统计计算以及普通索引和层级索引的转换方法

Pandas Dataframe 日期时间切片与 Index vs MultiIndex

为啥在具有一级索引的 MultiIndex 列的 pandas DataFrame 中表现不同?

Pandas Multiindex Groupby 聚合列与另一列的值