繁体   English   中英

如何使用一级标签列表对多索引 dataframe 进行切片

[英]How to slice multiindex dataframe with list of labels on one level

MultiIndex 数据帧非常强大,但我个人认为没有足够的(清晰的)文档,特别是针对不同类型的切片......这是我的问题:

如何使用标签列表在一个级别上对多索引 dataframe 进行切片? 如果您有解决方案,请帮助我(无需重置索引并将 dataframe 转换为单级索引!这很明显但效率不高

例如,我们有以下 dataframe:

import pandas as pd
import numpy as np

df = pd.DataFrame(index=range(10))
df['id'] = pd.Series(range(10,20))
df['name'] = [f'name_{id}' for id in range(10,20)]
df['price'] = np.random.rand(df.index.size)
df['date'] = pd.date_range('20200310', '20200319')
df = df.set_index(['id', 'date'])
df

在此处输入图像描述

切片一个 label 工作得很好:

df.xs('2020-03-10', level='date', drop_level=False)

在此处输入图像描述

但是我们如何才能在该级别上对标签列表进行切片呢?

df.xs(('2020-03-10', '2020-03-11', '2020-03-12'), level='date', drop_level=False)

这导致了一个异常:

在此处输入图像描述

但是 Python 文档说“key”参数也可以是一个元组:

https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.xs.html

在此处输入图像描述

Index.get_level_values多个值过滤,请使用Index.get_level_valuesIndex.isinboolean indexing

a = df[df.index.get_level_values('date').isin(('2020-03-10', '2020-03-11', '2020-03-12'))]
print (a)
                  name     price
id date                         
10 2020-03-10  name_10  0.557772
11 2020-03-11  name_11  0.122315
12 2020-03-12  name_12  0.775976

然而 Python 文档说“key”参数也可以是一个元组:

元组可以使用,但工作方式不同 - 您可以通过两个标签进行选择,例如:

b = df.xs((10, '2020-03-10'), drop_level=False)
print (b)
name      name_10
price    0.348808
Name: (10, 2020-03-10 00:00:00), dtype: object

c = df.xs((10, '2020-03-10'), level=('id','date'), drop_level=False)
print (c)
                  name     price
id date                         
10 2020-03-10  name_10  0.239876

像@yatu提到,与其他解决方案IndexSlice:所有的第一级别和最后:所有列:

df = df.loc[pd.IndexSlice[:, ['2020-03-10', '2020-03-11', '2020-03-12']], :]
print (df)
                  name     price
id date                         
10 2020-03-10  name_10  0.557488
11 2020-03-11  name_11  0.592082
12 2020-03-12  name_12  0.547747

访问多索引时使用元组是为了解决不同的级别/层次结构。 元组用于此用途,而不是作为在同一层次结构/级别内传递多个项目的一种形式。 对于同一级别内的多个选择,您需要使用其他一些功能,例如一个Jezrael

dates = ['2020-03-10', '2020-03-11', '2020-03-12']
filtered_df = df[df.index.get_level_values('date').isin(dates)]

这与@jezrael 提供的答案略有不同。

您可以像这样使用loc()slice(None)结合:

dates = ['2020-03-10', '2020-03-11', '2020-03-12']

df.loc[(slice(None), dates), :]


id  date        name    price
10  2020-03-10  name_10 0.36806
11  2020-03-11  name_11 0.20436
12  2020-03-12  name_12 0.00443

.loc中的第一个参数是一个在 MultiIndex 中选择行的元组。 slice(None)从第一级id获取所有值。 列表dates过滤第二级date中的键。 第二个参数:选择所有列。

Pandas 文档 - MultiIndex - 高级索引中,您可以找到:

重要的是要注意,在索引方面,元组和列表在 pandas 中的处理方式不同。 元组被解释为一个多级键,而列表用于指定多个键。 或者换句话说,元组 go 水平(遍历级别),垂直列出 go(扫描级别)。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM