带有日期层级的MultiIndex DataFrame如何使用字符串索引取值?
编辑补充
我已经找到解决方案了:在进行任何切片操作前需要先执行sort_index对索引排序。
背景说明
我有一个结构如下的DataFrame(注:ticker层级可能包含不止SPY一个标的,此处仅以SPY举例):
open high low close adj_close volume ticker date SPY 1993-01-29 43.9688 43.9688 43.7500 43.9375 25.7297 1003200 1993-02-01 43.9688 44.2500 43.9688 44.2500 25.9127 480500 1993-02-02 44.2188 44.3750 44.1250 44.3438 25.9676 201300 1993-02-03 44.4062 44.8438 44.3750 44.8125 26.2421 529400 1993-02-04 44.9688 45.0938 44.8750 45.0000 26.3519 531500 ... ... ... ... ... ... ... 2021-10-18 443.9700 447.5500 443.2700 447.1900 447.1900 62213228 2021-10-19 448.9200 450.7100 448.2700 450.6400 450.6400 46996827 2021-10-20 451.1300 452.7320 451.0100 452.4100 452.4100 49571569 2021-10-21 451.7700 453.8290 451.3100 453.5900 453.5900 41305438 2021-10-22 453.1300 454.6700 451.0500 453.1200 453.1200 58845088
我原本打算用下面这个语法获取SPY在2015年1月的价格,这种写法可以完好保留DataFrame的原有结构:
df.loc[("SPY", "2015-01")]
但实际运行报错,于是我尝试了第二种语法,这种写法如果运行成功会返回单索引的DataFrame:
df.loc["SPY"]["2015-01"]
两种方案都运行失败,均返回KeyError。我已经核实索引的第二层存储的是date对象,并非纯字符串,索引信息如下:
In [24]: df.index Out[24]: MultiIndex([('SPY', '1993-01-29'), ('SPY', '1993-02-01'), ('SPY', '1993-02-02'), ('SPY', '1993-02-03'), ('SPY', '1993-02-04'), ('SPY', '1993-02-05'), ('SPY', '1993-02-08'), ('SPY', '1993-02-09'), ('SPY', '1993-02-10'), ('SPY', '1993-02-11'), ... ('SPY', '2021-10-11'), ('SPY', '2021-10-12'), ('SPY', '2021-10-13'), ('SPY', '2021-10-14'), ('SPY', '2021-10-15'), ('SPY', '2021-10-18'), ('SPY', '2021-10-19'), ('SPY', '2021-10-20'), ('SPY', '2021-10-21'), ('SPY', '2021-10-22')], names=['ticker', 'date'], length=7237) In [25]: df.index.get_level_values(1) Out[25]: Index(['1993-01-29', '1993-02-01', '1993-02-02', '1993-02-03', '1993-02-04', '1993-02-05', '1993-02-08', '1993-02-09', '1993-02-10', '1993-02-11', ... '2021-10-11', '2021-10-12', '2021-10-13', '2021-10-14', '2021-10-15', '2021-10-18', '2021-10-19', '2021-10-20', '2021-10-21', '2021-10-22'], dtype='object', name='date', length=7237)
目前我唯一能成功运行的写法如下:
In [19]: df = get_eod_data(["SPY"]) In [20]: df = df.loc["SPY"] In [21]: df.index = pd.to_datetime(df.index) In [22]: df.loc["2015-01"] Out[22]: open high low close adj_close volume date 2015-01-02 206.38 206.88 204.180 205.4300 180.9772 121465865 2015-01-05 204.17 204.37 201.350 201.7200 177.7088 169632646 2015-01-06 202.09 202.72 198.855 199.8200 176.0349 209151408 2015-01-07 201.42 202.72 200.880 202.3100 178.2285 125346709 2015-01-08 204.01 206.16 203.990 205.9000 181.3912 147217784 2015-01-09 206.40 206.42 203.510 204.2500 179.9376 158567288 2015-01-12 204.41 204.60 201.920 202.6500 178.5281 144396067 2015-01-13 204.12 205.48 200.510 202.0800 178.0259 214553306 2015-01-14 199.65 201.10 198.570 200.8600 176.9511 192991092 2015-01-15 201.63 202.01 198.880 199.0199 175.3301 176613906 2015-01-16 198.77 201.82 198.550 201.6300 177.6295 211879605 2015-01-20 202.40 202.72 200.170 202.0550 178.0039 130991069 2015-01-21 201.50 203.66 200.940 203.0800 178.9069 122942707 2015-01-22 203.99 206.26 202.330 206.1000 181.5674 174356029 2015-01-23 205.79 206.10 204.810 204.9700 180.5719 117516753 2015-01-26 204.71 205.56 203.850 205.4500 180.9948 92009711 2015-01-27 202.97 204.12 201.740 202.7400 178.6073 134044598 2015-01-28 204.17 204.29 199.910 200.1400 176.3168 168514312 2015-01-29 200.38 202.30 198.680 201.9902 177.9468 173585424 2015-01-30 200.57 202.17 199.130 199.4500 175.7090 197729724
看起来我需要手动将DataFrame索引的第二层转换为DateTimeIndex之后,才能使用字符串对其进行索引。
问题
我需要做哪些操作,才能直接使用df.loc[("SPY", "2015-01")]或者df.loc["SPY"]["2015-01"]这类语法,便捷地按日期范围索引数据?
解决方案
完成以下两步操作即可实现需求:
- 先将MultiIndex的第二层date层级转换为
DateTimeIndex类型 - 对整个DataFrame执行
sort_index()排序索引
# 转换date层级为日期类型 df.index = df.index.set_levels([df.index.levels[0], pd.to_datetime(df.index.levels[1])], level=['ticker', 'date']) # 排序索引 df = df.sort_index()
完成以上操作后就可以直接用df.loc[("SPY", "2015-01")]语法查询数据,同时保留原始的MultiIndex结构。
内容的提问来源于stack exchange,提问作者Bob Fang
相关产品推荐
相关产品推荐

