在 Pandas Multiindex 中,如何在不知道关卡位置的情况下进行索引切片?

In Pandas Multiindex, how do you do an indexslice without knowing the position of the level?

提问人:byrey3 提问时间:7/3/2023 最后编辑:byrey3 更新时间:7/3/2023 访问量:45

问:

我有一个处理 pandas 数据帧的程序,使用 2 个级别(日期和数据)的多索引,例如:

Date_Time   Data    
date1       a
            b
            c

date2       a
            b
            c

date3       a
            b
            c
...

因此,当必须使用/修改 df 的内容时,所有函数都使用 pandas IndexSlice,例如:

df.loc[pd.IndexSlice[:,'a'],:]

这很好用,易于阅读,简短高效,并且使许多单行功能成为可能。

但是,我目前必须根据某些属性来区分数据,以便在进行重采样时不会使它们合并,并且我通过在必要时向索引添加第三级来做到这一点:

Date_Time   Property     Data    
date1       1            a
            1            b
            1            c

date2       2            a
            2            b
            2            c

date3       1            a
            1            b
            1            c
...

目标是能够随着时间的推移进行重新采样的分组,并最终得到这个多索引:

Date_Time   Property     Data    
Period1     1            a
            1            b
            1            c
            2            a
            2            b
            2            c

Period2     1            a
            1            b
            1            c
...

所以,问题是不再有效,我必须将其更改为df.loc[pd.IndexSlice[:,'a'],:]

df.loc[pd.IndexSlice[:,:,'a'],:]

但这意味着每次我将该数据帧与额外列一起使用时,都要更改代码本身。

有没有办法以灵活的方式定义切片??

我想使用变量来定义切片,就像在列表推导中一样,这样就可以防止将来对多索引级别的长度和顺序进行更多更改。但据我所知,这是不可能的,那我该怎么办??

我可以在每个函数的开头使用 try-except 块来定义切片,在已经确保级别和level_value存在的块内;或将属性级别向右移动,以便我仍然可以使用(但将来我可能会再次遇到这个问题)pd.IndexSlice[:,'a']


编辑:下面是一些代码,用于生成使用这种索引的数据帧:

iter1=[["03/07/2023 07:40:00", "03/07/2023 07:50:00"], ["S=0.1"],["Probe1","Probe2","Probe3"]]
iter2=[["03/07/2023 07:45:00", "03/07/2023 07:55:00"], ["S=0.2"],["Probe1","Probe2","Probe3"]]
idx1=pd.MultiIndex.from_product(iter1, names=["Date_Time", "Property",'Data'])
idx2=pd.MultiIndex.from_product(iter2, names=["Date_Time", "Property",'Data'])

df_aux1=pd.DataFrame(np.random.randn(6, 3), index=idx1, columns=['X','Y','Error'])
df_aux2=pd.DataFrame(np.random.randn(6, 3), index=idx2, columns=['X','Y','Error'])

df=pd.concat([df_aux1,df_aux2]).sort_index(level='Date_Time')
Python Pandas undefined slice 多索引

评论

0赞 mozway 7/3/2023
请提供可重现的代码df

答:

1赞 mozway 7/3/2023 #1

确切的数据和逻辑尚不清楚,但由于您已经命名了级别,因此可以使用Index.get_level_values布尔索引

df.loc[df.index.get_level_values('Data') == 'a']

或按位置:

df.loc[df.index.get_level_values(-1) == 'a']

评论

1赞 byrey3 7/4/2023
谢谢,它如我所愿。但是,我遇到了一次过滤多个级别值的问题,我使用它解决了这个问题,因此如果我想要而不是“a”,它也可以工作,我不知道这是否是效率方面的最佳选择,但如果其他人遇到同样的问题,那应该会有所帮助df.index.get_level_values('Data').isin('a')['a','c']