層次化索引是pandas的一項重要功能,它使你能在一個軸上擁有多個(兩個以上)索引級別。
創建一個
Series,並用一個由列表或數組組成的列表作為索引。
1 data=Series(np.random.randn(10), 2 index=[['a','a','a','b','b','b','c','c','d','d'], 3 [1,2,3,1,2,3,1,2,2,3]]) 4 5 data 6 Out[6]: 7 a 1 -2.842857 8 2 0.376199 9 3 -0.512978 10 b 1 0.225243 11 2 -1.242407 12 3 -0.663188 13 c 1 -0.149269 14 2 -1.079174 15 d 2 -0.952380 16 3 -1.113689 17 dtype: float64
這就是帶MultiIndex索引的Series的格式化輸出形式。索引之間的“間隔”表示“直接使用上面的標簽”。
1 data.index 2 Out[7]: 3 MultiIndex(levels=[['a', 'b', 'c', 'd'], [1, 2, 3]], 4 labels=[[0, 0, 0, 1, 1, 1, 2, 2, 3, 3], [0, 1, 2, 0, 1, 2, 0, 1, 1, 2]])
對於一個層次化索引的對象,選取數據子集的操作很簡單:
1 data['b'] 2 Out[8]: 3 1 0.225243 4 2 -1.242407 5 3 -0.663188 6 dtype: float64 7 8 9 data['b':'c'] 10 Out[10]: 11 b 1 0.225243 12 2 -1.242407 13 3 -0.663188 14 c 1 -0.149269 15 2 -1.079174 16 dtype: float64 17 18 data.ix[['b','d']] 19 __main__:1: DeprecationWarning: 20 .ix is deprecated. Please use 21 .loc for label based indexing or 22 .iloc for positional indexing 23 24 See the documentation here: 25 http://pandas.pydata.org/pandas-docs/stable/indexing.html#ix-indexer-is-deprecated 26 Out[11]: 27 b 1 0.225243 28 2 -1.242407 29 3 -0.663188 30 d 2 -0.952380 31 3 -1.113689 32 dtype: float64
甚至可以在“內層”中進行選取:
1 data[:,2] 2 Out[12]: 3 a 0.376199 4 b -1.242407 5 c -1.079174 6 d -0.952380 7 dtype: float64
層次化索引在數據重塑和基於分組的操作中扮演重要角色。
可以通過
unstack方法被重新安排到一個DataFrame中:
1 data.unstack() 2 Out[13]: 3 1 2 3 4 a -2.842857 0.376199 -0.512978 5 b 0.225243 -1.242407 -0.663188 6 c -0.149269 -1.079174 NaN 7 d NaN -0.952380 -1.113689 8 9 10 #unstack的逆運算是stack 11 data.unstack().stack() 12 Out[14]: 13 a 1 -2.842857 14 2 0.376199 15 3 -0.512978 16 b 1 0.225243 17 2 -1.242407 18 3 -0.663188 19 c 1 -0.149269 20 2 -1.079174 21 d 2 -0.952380 22 3 -1.113689 23 dtype: float64
對於DataFrame,每條軸都可以有分層索引:
1 frame=DataFrame(np.arange(12).reshape((4,3)), 2 index=[['a','a','b','b'],[1,2,1,2]], 3 columns=[['Ohio','Ohio','Colorado'], 4 ['Green','Red','Green']]) 5 6 frame 7 Out[16]: 8 Ohio Colorado 9 Green Red Green 10 a 1 0 1 2 11 2 3 4 5 12 b 1 6 7 8 13 2 9 10 11
各層都可以有名字。如果指定了名稱,它們會顯示在控制台中(不要將索引名稱和軸標簽混為一談!)
1 frame.index.names=['key1','key2'] 2 frame.columns.names=['state','color'] 3 4 frame 5 Out[22]: 6 state Ohio Colorado 7 color Green Red Green 8 key1 key2 9 a 1 0 1 2 10 2 3 4 5 11 b 1 6 7 8 12 2 9 10 11
由於有了分部的列索引,可以輕松選取列分組:
1 frame['Ohio'] 2 Out[23]: 3 color Green Red 4 key1 key2 5 a 1 0 1 6 2 3 4 7 b 1 6 7 8 2 9 10
重排分級排序
有時需要重新調整某條軸上各級別的順序,或根據指定級別上的值對數據進行排序。
swaplevel接受兩個級別編號或名稱,並返回一個互換了級別的新對象(但數據不會發生變化):
1 frame.swaplevel('key1','key2') 2 Out[24]: 3 state Ohio Colorado 4 color Green Red Green 5 key2 key1 6 1 a 0 1 2 7 2 a 3 4 5 8 1 b 6 7 8 9 2 b 9 10 11
sortlevel則根據單個級別中的值對數據進行排序。交換級別時,常用得到sortlevel,這樣最終結果也是有序的了:
1 frame.swaplevel(0,1) 2 Out[27]: 3 state Ohio Colorado 4 color Green Red Green 5 key2 key1 6 1 a 0 1 2 7 2 a 3 4 5 8 1 b 6 7 8 9 2 b 9 10 11 10 11 #交換級別0,1(也就是key1,key2) 12 #然后對axis=0進行排序 13 frame.swaplevel(0,1).sortlevel(0) 14 __main__:1: FutureWarning: sortlevel is deprecated, use sort_index(level= ...) 15 Out[28]: 16 state Ohio Colorado 17 color Green Red Green 18 key2 key1 19 1 a 0 1 2 20 b 6 7 8 21 2 a 3 4 5 22 b 9 10 11
根據級別匯總統計
有時需要重新調整某條軸上各級別的順序,或根據指定級別上的值對數據進行排序。swaplevel接受兩個級別編號或名稱,並返回一個互換了級別的新對象(但數據不會發生變化):
1 frame.sum(level='key2') 2 Out[29]: 3 state Ohio Colorado 4 color Green Red Green 5 key2 6 1 6 8 10 7 2 12 14 16 8 9 frame.sum(level='color',axis=1) 10 Out[30]: 11 color Green Red 12 key1 key2 13 a 1 2 1 14 2 8 4 15 b 1 14 7 16 2 20 10
使用DataFrame的列
將DataFrame的一個或多個列當做行索引來用,或將行索引變成Dataframe 的列。
1 frame=DataFrame({'a':range(7),'b':range(7,0,-1), 2 'c':['one','one','one','two','two','two','two'], 3 'd':[0,1,2,0,1,2,3]}) 4 5 frame 6 Out[32]: 7 a b c d 8 0 0 7 one 0 9 1 1 6 one 1 10 2 2 5 one 2 11 3 3 4 two 0 12 4 4 3 two 1 13 5 5 2 two 2 14 6 6 1 two 3
DataFrame的set_index函數會將其一個或多個列轉換為行索引,並創建一個新的DataFrame:
1 frame2=frame.set_index(['c','d']) 2 3 frame2 4 Out[34]: 5 a b 6 c d 7 one 0 0 7 8 1 1 6 9 2 2 5 10 two 0 3 4 11 1 4 3 12 2 5 2 13 3 6 1
默認情況下,那些列會從DataFrame中移除,但也可以將其保留下來:
1 frame.set_index(['c','d'],drop=False) 2 Out[35]: 3 a b c d 4 c d 5 one 0 0 7 one 0 6 1 1 6 one 1 7 2 2 5 one 2 8 two 0 3 4 two 0 9 1 4 3 two 1 10 2 5 2 two 2 11 3 6 1 two 3
reset_index的功能和set_index剛好相反,層次化索引的級別會被轉移到列里面:
1 frame2.reset_index() 2 Out[36]: 3 c d a b 4 0 one 0 0 7 5 1 one 1 1 6 6 2 one 2 2 5 7 3 two 0 3 4 8 4 two 1 4 3 9 5 two 2 5 2 10 6 two 3 6 1