层次化索引(hierarchical indexing)使你能在一个轴上拥有多个(两个以上)索引级别。抽象点说,它使你能以低维度形式处理高维度数据。下面演示一下使用方法。
首先创建一个具有层次化索引的数据:
In [9]: data = pd.Series(np.random.randn(9),...: index=[['a', 'a', 'a', 'b', 'b', 'c', 'c', 'd', 'd'],...: [1, 2, 3, 1, 3, 1, 2, 2, 3]])In [10]: dataOut[10]:a 1 -0.2047082 0.4789433 -0.519439b 1 -0.5557303 1.965781c 1 1.3934062 0.092908d 2 0.2817463 0.769023dtype: float64
层次化索引的类型是MultiIndex:
In [11]: data.indexOut[11]:MultiIndex(levels=[['a', 'b', 'c', 'd'], [1, 2, 3]],labels=[[0, 0, 0, 1, 1, 2, 2, 3, 3], [0, 1, 2, 0, 2, 0, 1, 1, 2]])
对于一个层次化索引的对象,可以使用部分索引选取数据子集:
In [12]: data['b']Out[12]:1 -0.5557303 1.965781dtype: float64In [13]: data['b':'c']Out[13]:b 1 -0.5557303 1.965781c 1 1.3934062 0.092908dtype: float64In [14]: data.loc[['b', 'd']]Out[14]:b 1 -0.5557303 1.965781d 2 0.2817463 0.769023dtype: float64
也可以在“内层”中进行选取:
In [15]: data.loc[:, 2]Out[15]:a 0.478943c 0.092908d 0.281746dtype: float64

stack与unstack
具有层次化索引的Series可以通过unstack方法转换成DataFrame:
In [16]: data.unstack()Out[16]:1 2 3a -0.204708 0.478943 -0.519439b -0.555730 NaN 1.965781c 1.393406 0.092908 NaNd NaN 0.281746 0.769023
unstack的逆运算stack则将DataFrame转换为具有层次化索引的Series:
In [17]: data.unstack().stack()Out[17]:a 1 -0.2047082 0.4789433 -0.519439b 1 -0.5557303 1.965781c 1 1.3934062 0.092908d 2 0.2817463 0.769023dtype: float64

DataFrame的分层索引
对于一个DataFrame,每条轴都可以有分层索引:
In [18]: frame = pd.DataFrame(np.arange(12).reshape((4, 3)),....: index=[['a', 'a', 'b', 'b'], [1, 2, 1, 2]],....: columns=[['Ohio', 'Ohio', 'Colorado'],....: ['Green', 'Red', 'Green']])In [19]: frameOut[19]:Ohio ColoradoGreen Red Greena 1 0 1 22 3 4 5b 1 6 7 82 9 10 11
各层索引都可以有名字,如果指定了名称,它们就会显示在控制台输出中:
In [20]: frame.index.names = ['key1', 'key2']In [21]: frame.columns.names = ['state', 'color']In [22]: frameOut[22]:state Ohio Coloradocolor Green Red Greenkey1 key2a 1 0 1 22 3 4 5b 1 6 7 82 9 10 11
有了部分列索引,可以轻松选取列分组:
In [23]: frame['Ohio']Out[23]:color Green Redkey1 key2a 1 0 12 3 4b 1 6 72 9 10
可以单独创建MultiIndex然后复用。上面的DataFrame中的列(带有分级名称)可以这样创建:
MultiIndex.from_arrays([['Ohio', 'Ohio', 'Colorado'], ['Green', 'Red', 'Green']],names=['state', 'color'])

重排与分级排序
有时需要重新调整某条轴上各级别的顺序,或根据指定级别上的值对数据进行排序。
swaplevel接受两个级别编号或名称,并返回一个互换了级别的新对象(但数据不会发生变化):
In [22]: frameOut[22]:state Ohio Coloradocolor Green Red Greenkey1 key2a 1 0 1 22 3 4 5b 1 6 7 82 9 10 11In [24]: frame.swaplevel('key1', 'key2')Out[24]:state Ohio Coloradocolor Green Red Greenkey2 key11 a 0 1 22 a 3 4 51 b 6 7 82 b 9 10 11
而sort_index可指定
level参数根据单个级别中的值对数据进行排序:
In [25]: frame.sort_index(level=1)Out[25]:state Ohio Coloradocolor Green Red Greenkey1 key2a 1 0 1 2b 1 6 7 8a 2 3 4 5b 2 9 10 11
交换级别时,常常也会用到sort_index,这样最终结果就是按照指定顺序进行字母排序了(level=0也可以写为level='key2'):
In [26]: frame.swaplevel(0, 1).sort_index(level=0)Out[26]:state Ohio Coloradocolor Green Red Greenkey2 key11 a 0 1 2b 6 7 82 a 3 4 5b 9 10 11

根据指定级别汇总统计
DataFrame和Series的许多描述和汇总统计函数都有一个level选项,它用于指定在某条轴上求和的级别,可以根据行或列上的级别来进行求和:
In [27]: frame.sum(level='key2')Out[27]:state Ohio Coloradocolor Green Red Greenkey21 6 8 102 12 14 16In [28]: frame.sum(level='color', axis=1)Out[28]:color Green Redkey1 key2a 1 2 12 8 4b 1 14 72 20 10

使用DataFrame的列进行索引
下面演示如何将一个或多个列转换为行索引,或将行索引转化为列。
准备数据:
In [29]: frame = pd.DataFrame({'a': range(7), 'b': range(7, 0, -1),....: 'c': ['one', 'one', 'one', 'two', 'two',....: 'two', 'two'],....: 'd': [0, 1, 2, 0, 1, 2, 3]})In [30]: frameOut[30]:a b c d0 0 7 one 01 1 6 one 12 2 5 one 23 3 4 two 04 4 3 two 15 5 2 two 26 6 1 two 3
DataFrame的set_index函数会将其一个或多个列转换为行索引,并创建一个新的DataFrame:
In [31]: frame2 = frame.set_index(['c', 'd'])In [32]: frame2Out[32]:a bc done 0 0 71 1 62 2 5two 0 3 41 4 32 5 23 6 1
默认情况下,那些列会从DataFrame中移除,但也可以将其保留下来:
In [33]: frame.set_index(['c', 'd'], drop=False)Out[33]:a b c dc done 0 0 7 one 01 1 6 one 12 2 5 one 2two 0 3 4 two 01 4 3 two 12 5 2 two 23 6 1 two 3
reset_index的功能跟set_index刚好相反,层次化索引的级别会被转移到列里面:
In [34]: frame2.reset_index()Out[34]:c d a b0 one 0 0 71 one 1 1 62 one 2 2 53 two 0 3 44 two 1 4 35 two 2 5 26 two 3 6 1




