「目录」
数据规整:聚合、合并和重塑
Data Wrangling: Join, Combine, and Reshape
8.1 => 层次化索引
8.2 => 合并数据集
8.3 => 重塑和轴向旋转
第七章终于结束了,来到了第八章,干杯!
我把原书第七章剩下一点正则化的部分跳过去了,因为正则化的东西其实有很多,但是原书只讲了一点,并没有着重去讲,因为作者认为不是数据分析的重点,那我也偷懒跳过去吧!
本篇笔记主要讲了层次化索引,涉及了下面几个新出现的方法:
DataFrame.swaplevel() DataFrame.sum() DataFrame.sort_index() DataFrame.reset_index()
层次化索引
层次化索引(hierarchical indexing)是pandas的一项重要功能,它使我们能在一个轴上拥有多个索引级别。
先来看一下层次化索引长什么样子吧:
In [1]: import pandas as pd
In [2]: import numpy as np
In [3]: 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 [4]: data
Out[4]:
a 1 0.740915
2 -1.604666
3 1.236358
b 1 0.307977
3 1.856143
c 1 -0.243549
2 -0.924816
d 2 -0.183851
3 -0.104385
dtype: float64复制
查看一下data的index属性,它会告诉你这是一个MultiIndex多重索引,levels里第一个是一级索引,第二个是二级索引,codes里的你观察看看。
In [5]: data.index
Out[5]:
MultiIndex(levels=[['a', 'b', 'c', 'd'], [1, 2, 3]],
codes=[[0, 0, 0, 1, 1, 2, 2, 3, 3], [0, 1, 2, 0, 2, 0, 1, 1, 2]])复制
选取索引为'b'的子集:
In [6]: data['b']
Out[6]:
1 0.307977
3 1.856143
dtype: float64复制
选取索引从'b'到'c'的这部分子集:
In [7]: data['b':'c']
Out[7]:
b 1 0.307977
3 1.856143
c 1 -0.243549
2 -0.924816
dtype: float64复制
选取索引为'b'和'd'的子集:
In [8]: data.loc[['b', 'd']]
Out[8]:
b 1 0.307977
3 1.856143
d 2 -0.183851
3 -0.104385
dtype: float64复制
还可以这么选,选取第二级索引为'2'的子集:
In [9]: data.loc[:, 2]
Out[9]:
a -1.604666
c -0.924816
d -0.183851
dtype: float64复制
如果对切片熟悉的话,上面那些选取子集的方法应该都不难理解。
对于DataFrame,每条轴都可以有分层索引:
In [13]: 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 [14]: frame
Out[14]:
Ohio Colorado
Green Red Green
a 1 0 1 2
2 3 4 5
b 1 6 7 8
2 9 10 11复制
我们可以给每一层都设置名字:
In [15]: frame.index.names = ['key1', 'key2']
In [16]: frame.columns.names = ['state', 'color']
In [17]: frame
Out[17]:
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 [18]: frame['Ohio']
Out[18]:
color Green Red
key1 key2
a 1 0 1
2 3 4
b 1 6 7
2 9 10
In [19]: frame['Ohio']['Red']
Out[19]:
key1 key2
a 1 1
2 4
b 1 7
2 10
Name: Red, dtype: int32
In [22]: frame['Ohio']['Red']['a']
Out[22]:
key2
1 1
2 4
Name: Red, dtype: int32
In [23]: frame['Ohio']['Red']['a'][1]
Out[23]: 1复制
用loc函数来选取:
In [24]: frame.loc['a', 'Ohio']
Out[24]:
color Green Red
key2
1 0 1
2 3 4
In [25]: frame.loc['a', ['Ohio', 'Colorado']]
Out[25]:
state Ohio Colorado
color Green Red Green
key2
1 0 1 2
2 3 4 5复制
swaplevel
有时我们需要重新调整某条轴上各级别的顺序,或根据指定级别上的值对数据进行排序。
swaplevel接受两个level级别编号或名称,并返回一个级别互换的新对象,但数据不会发生变化:
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级别的值对数据进行排序,比如下面对'key2'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复制
swaplevel可以和sort_index一起用,这样就可以在交换顺序后,在指定level下排序了:
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复制
sum汇总统计
之前的笔记中已经写过sum方法了,sum中还有一个level选项,用于指定对某条轴上的哪一个级别求和。
In [27]: frame
Out[27]:
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 [28]: frame.sum(level='key2')
Out[28]:
state Ohio Colorado
color Green Red Green
key2
1 6 8 10
2 12 14 16复制
在axis=1轴上,在level='color'这一级别上求和:
In [29]: frame.sum(level='color', axis=1)
Out[29]:
color Green Red
key1 key2
a 1 2 1
2 8 4
b 1 14 7
2 20 10复制
使用DataFrame的列进行索引
我们还可以把DataFrame的列当作行索引用。
先随便创一个DataFrame:
In [30]: 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 [31]: frame
Out[31]:
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 [32]: frame2 = frame.set_index(['c', 'd'])
In [33]: frame2
Out[33]:
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复制
默认情况,被转换为行索引的列会被移除,但通过drop=False可以将其保留下来:
In [34]: frame.set_index(['c', 'd'], drop=False)
Out[34]:
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 [35]: frame2.reset_index()
Out[35]:
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复制
好啦,这篇结束了。
BYE-BYE,下期见!!!
往期回顾



Stay hungry, stay foolish