暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

Pandas的层次化索引

漫谈大数据与数据分析 2020-04-20
395

层次化索引(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]: data
Out[10]:
a 1 -0.204708
2 0.478943
3 -0.519439
b 1 -0.555730
3 1.965781
c 1 1.393406
2 0.092908
d 2 0.281746
3 0.769023
dtype: float64


层次化索引的类型是MultiIndex

In [11]: data.index
Out[11]:
MultiIndex(levels=[['a', 'b', 'c', 'd'], [1, 2, 3]],
           labels=[[000112233], [012020112]])

对于一个层次化索引的对象,可以使用部分索引选取数据子集:

In [12]: data['b']
Out[12]:
1 -0.555730
3 1.965781
dtype: float64


In [13]: data['b':'c']
Out[13]:
b 1 -0.555730
3 1.965781
c 1 1.393406
2 0.092908
dtype: float64


In [14]: data.loc[['b', 'd']]
Out[14]:
b 1 -0.555730
3 1.965781
d 2 0.281746
3 0.769023
dtype: float64

也可以在“内层”中进行选取:

In [15]: data.loc[:, 2]
Out[15]:
a 0.478943
c 0.092908
d 0.281746
dtype: float64



stack与unstack

具有层次化索引的Series可以通过unstack方法转换成DataFrame:

In [16]: data.unstack()
Out[16]:
1 2 3
a -0.204708 0.478943 -0.519439
b -0.555730 NaN 1.965781
c 1.393406 0.092908 NaN
d NaN 0.281746 0.769023

unstack的逆运算stack则将DataFrame转换为具有层次化索引的Series:

In [17]: data.unstack().stack()
Out[17]:
a 1 -0.204708
2 0.478943
3 -0.519439
b 1 -0.555730
3 1.965781
c 1 1.393406
2 0.092908
d 2 0.281746
3 0.769023
dtype: float64



DataFrame的分层索引

对于一个DataFrame,每条轴都可以有分层索引:

In [18]: frame = pd.DataFrame(np.arange(12).reshape((43)),
   ....:                      index=[['a''a''b''b'], [1212]],
....: columns=[['Ohio', 'Ohio', 'Colorado'],
....: ['Green', 'Red', 'Green']])


In [19]: frame
Out[19]:
Ohio Colorado
Green Red Green
a 1 0 1 2
2 3 4 5
b 1 6 7 8
2 9 10 11

各层索引都可以有名字,如果指定了名称,它们就会显示在控制台输出中:

In [20]: frame.index.names = ['key1', 'key2']
In [21]: frame.columns.names = ['state', 'color']


In [22]: frame
Out[22]:
state Ohio Colorado
color Green Red Green
key1 key2
a 1 0 1 2
2 3 4 5
b 1 6 7 8
2 9 10 11

有了部分列索引,可以轻松选取列分组:

In [23]: frame['Ohio']
Out[23]:
color Green Red
key1 key2
a 1 0 1
2 3 4
b 1 6 7
2 9 10



可以单独创建MultiIndex然后复用。上面的DataFrame中的列(带有分级名称)可以这样创建:

MultiIndex.from_arrays([['Ohio', 'Ohio', 'Colorado'], ['Green', 'Red', 'Green']],
names=['state', 'color'])



重排与分级排序

有时需要重新调整某条轴上各级别的顺序,或根据指定级别上的值对数据进行排序。

swaplevel接受两个级别编号或名称,并返回一个互换了级别的新对象(但数据不会发生变化):

In [22]: frame
Out[22]:
state Ohio Colorado
color Green Red Green
key1 key2
a 1 0 1 2
2 3 4 5
b 1 6 7 8
2 9 10 11

In [24]: frame.swaplevel('key1', 'key2')
Out[24]:
state Ohio Colorado
color Green Red Green
key2 key1
1 a 0 1 2
2 a 3 4 5
1 b 6 7 8
2 b 9 10 11

而sort_index可指定
level参数根据单个级别中的值对数据进行排序:

In [25]: frame.sort_index(level=1)
Out[25]:
state Ohio Colorado
color Green Red Green
key1 key2
a 1 0 1 2
b 1 6 7 8
a 2 3 4 5
b 2 9 10 11

交换级别时,常常也会用到sort_index,这样最终结果就是按照指定顺序进行字母排序了(level=0也可以写为level='key2'):

In [26]: frame.swaplevel(0, 1).sort_index(level=0)
Out[26]:
state Ohio Colorado
color Green Red Green
key2 key1
1 a 0 1 2
b 6 7 8
2 a 3 4 5
b 9 10 11





根据指定级别汇总统计

DataFrame和Series的许多描述和汇总统计函数都有一个level选项,它用于指定在某条轴上求和的级别,可以根据行或列上的级别来进行求和

In [27]: frame.sum(level='key2')
Out[27]:
state Ohio Colorado
color Green Red Green
key2
1 6 8 10
2 12 14 16


In [28]: frame.sum(level='color', axis=1)
Out[28]:
color Green Red
key1 key2
a 1 2 1
2 8 4
b 1 14 7
2 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]: frame
Out[30]:
a b c d
0 0 7 one 0
1 1 6 one 1
2 2 5 one 2
3 3 4 two 0
4 4 3 two 1
5 5 2 two 2
6 6 1 two 3

DataFrame的set_index函数会将其一个或多个列转换为行索引,并创建一个新的DataFrame:

In [31]: frame2 = frame.set_index(['c', 'd'])
In [32]: frame2
Out[32]:
a b
c d
one 0 0 7
1 1 6
2 2 5
two 0 3 4
1 4 3
2 5 2
3 6 1

默认情况下,那些列会从DataFrame中移除,但也可以将其保留下来:

In [33]: frame.set_index(['c', 'd'], drop=False)
Out[33]:
a b c d
c d
one 0 0 7 one 0
1 1 6 one 1
2 2 5 one 2
two 0 3 4 two 0
1 4 3 two 1
2 5 2 two 2
3 6 1 two 3

reset_index的功能跟set_index刚好相反,层次化索引的级别会被转移到列里面:

In [34]: frame2.reset_index()
Out[34]:
c d a b
0 one 0 0 7
1 one 1 1 6
2 one 2 2 5
3 two 0 3 4
4 two 1 4 3
5 two 2 5 2
6 two 3 6 1




文章转载自漫谈大数据与数据分析,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论