层次化索引是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
根据级别汇总统计
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的列
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