在多索引上使用切片器

时间:2016-07-10 16:59:03

标签: python pandas indexing dataframe slice

我有一个表格的数据框:

Contract  Date      
201501    2014-04-29    1416.0
          2014-04-30    1431.1
          2014-05-01    1430.6
          2014-05-02    1443.9
          2014-05-05    1451.6
          2014-05-06    1461.4
          2014-05-07    1456.0
          2014-05-08    1441.1
          2014-05-09    1437.8
          2014-05-12    1445.2
          2014-05-13    1458.2
          2014-05-14    1487.6
          2014-05-15    1477.6
          2014-05-16    1467.9
          2014-05-19    1484.9
          2014-05-20    1470.5
          2014-05-21    1476.9
          2014-05-22    1490.0
          2014-05-23    1473.3
          2014-05-27    1462.5
          2014-05-28    1456.3
          2014-05-29    1460.5
201507    2014-05-30    1463.5
          2014-06-02    1447.5
          2014-06-03    1444.4
          2014-06-04    1444.7
          2014-06-05    1455.9
          2014-06-06    1464.0

合同与合同日期分别是intdatetime64类型的索引。

我想要的是选择日期范围。它的工作原理是:

df.reset_index('Contract', drop=True).loc['2014-09']

但是我讨厌它,因为它失去了索引/不是很愉快(我必须做很多这些)。

我想我应该能够这样做:

df.loc[:,'2014-09']

带回2014年9月的所有数据。实际上,这不起作用。我只能选择一天:

df.loc[:,'2014-09-02']

为什么我的多索引切片机不起作用?

3 个答案:

答案 0 :(得分:2)

Pandas需要您明确是否要选择分层索引的列或子级别。在这种情况下,df.loc[:,'2014-09']失败,因为pandas尝试获取所有行,然后查找标记为'2014-09'的列(不存在)。

相反,您需要为多标志提供两个级别的列标签/切片。

要从您的示例中选择所有2014年5月的数据,您可以写:

>>> df.loc[(slice(None), '2014-05'), :]                            
Contract Date              
201501   2014-05-01  1430.6
         2014-05-02  1443.9
         2014-05-05  1451.6
         2014-05-06  1461.4
         2014-05-07  1456.0
         2014-05-08  1441.1
         2014-05-09  1437.8
         2014-05-12  1445.2
         2014-05-13  1458.2
         2014-05-14  1487.6
         2014-05-15  1477.6
         2014-05-16  1467.9
         2014-05-19  1484.9
         2014-05-20  1470.5
         2014-05-21  1476.9
         2014-05-22  1490.0
         2014-05-23  1473.3
         2014-05-27  1462.5
         2014-05-28  1456.3
         2014-05-29  1460.5
201507   2014-05-30  1463.5

此处[(slice(None), '2014-05'), :]会转换为行的[:, '2014-05']切片和列的[:]

引入pd.IndexSlice对象使这些切片语义更容易:

>>> idx = pd.IndexSlice
>>> df.loc[idx[:, '2014-05'], :]
# same slice of DataFrame

答案 1 :(得分:2)

您可以使用pd.Indexslice根据level的每个MultiIndex的范围进行选择(see docs):

idx = pd.IndexSlice
df.loc[idx[:, '2014-05'], :]

得到:

Contract Date              
201501   2014-05-01  1430.6
         2014-05-02  1443.9
         2014-05-05  1451.6
         2014-05-06  1461.4
         2014-05-07  1456.0
         2014-05-08  1441.1
         2014-05-09  1437.8
         2014-05-12  1445.2
         2014-05-13  1458.2
         2014-05-14  1487.6
         2014-05-15  1477.6
         2014-05-16  1467.9
         2014-05-19  1484.9
         2014-05-20  1470.5
         2014-05-21  1476.9
         2014-05-22  1490.0
         2014-05-23  1473.3
         2014-05-27  1462.5
         2014-05-28  1456.3
         2014-05-29  1460.5
201507   2014-05-30  1463.5

答案 2 :(得分:1)

您可以使用.dt accessor提取9月份的所有值,如下所示:

df.loc[(pd.to_datetime(df['Date']).dt.month == 9)]

时间限制:

timeit df.loc[(pd.to_datetime(df['Date']).dt.month == 5)]
1000 loops, best of 3: 796 µs per loop