pandas多级索引的骚操作!
![作者头像](https://ask.qcloudimg.com/http-save/yehe-2769421/724rcd6wiw.jpeg)
我们知道dataframe是一个二维的数据表结构,通常情况下行和列索引都只有一个。但当需要多维度分析时,我们就需要添加多层级索引了。在关系型数据库中也被叫做复合主键。
比如,下面这个数据是高考录取分数线,行索引是地区、学校,列索引是年份、专业,分别对应1级和2级索引,因此共有四个维度。
![](https://developer.qcloudimg.com/http-save/yehe-2769421/29be6cec5496abcf6f3cbb1c7de04493.png)
1、多层级索引创建
多级索引的创建分两种情况。一种是只有纯数据,索引需要新建立;另一种是索引可从数据中获取。
因为两种情况建立多级索引的方法不同,下面分情况来介绍。
01 新建多级索引
当只有数据没有索引时,我们需要指定索引值,比如下图。
df = pd.DataFrame(
[[601,582,611,591],
[605,575,616,597],
[591,574,589,575],
[586,565,584,561]])
print(df)
![](https://developer.qcloudimg.com/http-save/yehe-2769421/15b86210dd4e8f7103e3fabf9284704c.png)
有四种创建多级层级的方法:
MultiIndex.from_arrays
,
MultiIndex.from_product
,
MultiIndex.from_tuples
,
MultiIndex.from_frame
。
# 数组
# 每个数组对应着一个层级的索引值
arrays = [['北京','北京','上海','上海'],['北大','清华','上交','复旦']]
mindex = pd.MultiIndex.from_arrays(arrays, names=['城市','大学'])
# 每个元组是对应着一对多级索引
tuples = [('北京','北大'),('北京','清华'),('上海','上交'),('上海','复旦')]
mindex = pd.MultiIndex.from_tuples(tuples, names=['城市','大学'])
# dataframe
# 创建一个dataframe,方式与元组类似,每个元组对应一对多级索引值
frame = pd.DataFrame([('北京','北大'),('北京','清华'),('上海','上交'),('上海','复旦')])
mindex = pd.MultiIndex.from_frame(frame, names=['城市','大学'])
# 给df行索引赋值
df.index = mindex
通过以上三种方式均可为数据添加行索引值,索引值结果一样,如下图。
![](https://developer.qcloudimg.com/http-save/yehe-2769421/fb202ad29dd6d98975453cbda1704e12.png)
# product笛卡尔积
city = ['北京', '上海']
college = ['北大','清华','上交','复旦']
mindex1 = pd.MultiIndex.from_product([city,college], names=['城市','大学'])
mindex1
![](https://developer.qcloudimg.com/http-save/yehe-2769421/20646141c59215063343fdd6e7e9c8a5.png)
第四种方法是对两个序列生成
笛卡尔积,即两两组合
,结果如上。这种方式生成的索引和我们上面想要的形式不同,因此对行索引不适用,但是我们发现列索引column目前还没指定,此时是默认的1,2,3,4,进一步发现这里的列索引是符合笛卡尔积形式的,因此我们用
from_product
来生成column列索引。
# product生成column列索引
year = ['2022','2023']
pro = ['计算机','土木']
mcol = pd.MultiIndex.from_product([year,pro], names=['年份','专业'])
# 对df的行索引、列索引赋值
df.index = mindex
df.columns = mcol
display(df)
![](https://developer.qcloudimg.com/http-save/yehe-2769421/23570f93b860e6ce894c6211ae19ce12.png)
02 从数据中获取多级索引
第二种情况是我们既有数值数据又有维度数据,此时可以使用透视的方法比如
pivot_table
,
stack
,
unstack
来设置多层级索引。
![](https://developer.qcloudimg.com/http-save/yehe-2769421/5877ee7b0e9d552ccc9c64281a0c7dfc.png)
# pivot_table
pd.pivot_table(df1, index=['城市','大学'],columns=['年份','专业'])
# unstack将行索引最内层连续翻转两次
df1.set_index(['城市','大学','专业','年份']).unstack().unstack()
以上两种方式结果相同,均可从原数据中抽取列维度数据并设置为行列的多级索引。
2、多层级索引筛选
通过
MultiIndex
访问dataFrame的好处是,可以很容易地一次引用所有层次(可能会省略内部层次),语法简单方便。
这里通过
.loc
查询方法进行举例。
01列索引筛选
# 筛选列一级索引
df.loc[:,'2023']
df['2023']
# 同时筛选列一二级索引
df.loc[:,('2022','计算机')]
df['2022','计算机']
![](https://developer.qcloudimg.com/http-save/yehe-2769421/fe7fd2095a41eed0e5d2aa43c0cf4bd4.png)
02 行索引筛选
通过.loc可对行、列或单元格进行筛选。
# 同时筛选行一二级索引
df.loc['北京','北大']
# 筛选行一级索引
df.loc['上海']
# 同时筛选行和列一二级索引,得到元素
df.loc[('上海','复旦'),('2022','土木')]
![](https://developer.qcloudimg.com/http-save/yehe-2769421/eab7e16e87ecf355d5e4568b2cf7ed3d.png)
3、多层级索引操作
对于多层级索引来说,可以按照不同的level层级有多种的操作,包括了 查询、删除、修改、排序、互换、拼接、拆分 等。
这些操作对行(index)、列(columns)索引均适用。
01 按层级查询索引
get_level_values
可以对指定层级索引查询,level指定层级。
# 按层级获取索引
df.index.get_level_values(level=1) # 查找行的二级索引
df.index.get_level_values(level=0) # 查找行的一级索引
df.columns.get_level_values(level=1) # 查找列的二级索引
df.columns.get_level_values(level=0) # 查找列的一级索引
02 按层级删除索引
droplevel
可以对指定层级索引删除,level指定层级。
# 按层级删除索引
df.index.droplevel(level=0) # 删除行一级索引
df.index.droplevel(level=1) # 删除行二级索引
df.columns.droplevel(level=0) # 删除行一级索引
df.columns.droplevel(level=1) # 删除行二级索引
03 按层级修改索引
set_levels
可以对指定层级的索引重新设置覆盖原索引,level指定层级。
df.index.set_levels(['北方','南方'], level=0) # 修改行一级索引
df.index.set_levels(['北交','人大','同济','华东师范'], level=1) # 修改行二级索引
df.columns.set_levels(['2020','2021'], level=0) # 修改列一级索引
df.columns.set_levels(['机械','电子'], level=1) # 修改列二级索引
04 按层级排序索引
sortlevel
对索引的不同层级按升降序的方法排序,level指定层级,ascending指定是否升序。
df.index.sortlevel(level=0, ascending=False) # 对行一级索引倒序排序
df.index.sortlevel(level=1, ascending=False) # 对行二级索引倒序排序
df.columns.sortlevel(level=0, ascending=False) # 对列一级索引倒序排序
df.columns.sortlevel(level=1, ascending=False) # 对列二级索引倒序排序
05 索引层级互换
swaplevel
对指定的两个索引层级进行互换,比如将2和3互换,1和2互换等等。
df.index.swaplevel(i=0, j=1) # 对行索引层级互换
df.columns.swaplevel(i=0, j=1) # 对行索引层级互换
06 按层级重排索引
reorder_levels
函数可以按指定的顺序进行重新排序,order参数可以是整数的level层级或者字符串的索引名,用法如下。
df.index.reorder_levels(order=['大学','城市']) # 指定行索引名称name重排
df.index.reorder_levels(order=[1,0]) # 指定行索引层级level数字重排
df.columns.reorder_levels(order=['专业','年份']) # 指定列索引名称name重排
df.columns.reorder_levels(order=[1,0]) # 指定列索引层级level数字重排
![](https://developer.qcloudimg.com/http-save/yehe-2769421/05dda0448f464af13c1b74dd2e569b84.png)
索引有两个层级时,重排效果和互换一样,只有当索引有三个层级时,重排可以发挥出作用。
07 多级索引拼接
除此外,对于多层级索引而言,我们有时需要将多层级进行拼接,此时我们可以借助
to_flat_index
函数,它可以将多级索引放在一起(
相当于from_tuples的逆操作
)。
比如,对列索引进行此操作,得到了元组形式的一二级索引对。
df.columns.to_flat_index()
------