在多索引上使用切片器
Using slicers on a multi-index
我有以下形式的数据框:
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
其中合同和日期分别是 int
和 datetime64
类型的索引。
我想要的是select一个日期范围。它的工作原理是:
df.reset_index('Contract', drop=True).loc['2014-09']
但我讨厌这个,因为它失去了 index/is 不是很愉快(我必须做很多这样的事情)。
我想我应该可以这样做:
df.loc[:,'2014-09']
恢复 2014 年 9 月的所有数据。实际上,这是行不通的。我一天只能 select 做:
df.loc[:,'2014-09-02']
为什么我的多索引切片器不起作用?
Pandas 需要您明确说明您是 select 分层索引的列还是子级别。在这种情况下,df.loc[:,'2014-09']
失败,因为 pandas 尝试获取所有行,然后查找标记为 '2014-09'
的列(不存在)。
相反,您需要为多索引 和 的两个级别提供列 labels/slice。
要 select 您示例中所有 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
您可以使用 .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
您可以根据 MultiIndex
的每个 level
的范围使用 pd.Indexslice
到 select,就像这样 (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
我有以下形式的数据框:
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
其中合同和日期分别是 int
和 datetime64
类型的索引。
我想要的是select一个日期范围。它的工作原理是:
df.reset_index('Contract', drop=True).loc['2014-09']
但我讨厌这个,因为它失去了 index/is 不是很愉快(我必须做很多这样的事情)。
我想我应该可以这样做:
df.loc[:,'2014-09']
恢复 2014 年 9 月的所有数据。实际上,这是行不通的。我一天只能 select 做:
df.loc[:,'2014-09-02']
为什么我的多索引切片器不起作用?
Pandas 需要您明确说明您是 select 分层索引的列还是子级别。在这种情况下,df.loc[:,'2014-09']
失败,因为 pandas 尝试获取所有行,然后查找标记为 '2014-09'
的列(不存在)。
相反,您需要为多索引 和 的两个级别提供列 labels/slice。
要 select 您示例中所有 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
您可以使用 .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
您可以根据 MultiIndex
的每个 level
的范围使用 pd.Indexslice
到 select,就像这样 (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