07_Pandas多层索引

概述

多层数据可以只有行上的多层,可以只有在列上为多层,也可以在两个方向都为多层,理论上层数是没有上限的。除了原生的数据为多层外,在数据分组聚合等操作时也会产生多层数据。

多层是一个低维的形式展示的多维数据,可以用这种形式处理高维数据。

通过分组产生多层索引

# 按团队分组,个团队中平均成绩及格的人数
df.groupby(['team',df.mean(1)>=60]).count()
#             name  Q1  Q2  Q3  Q4
# team                            
# A    False    14  14  14  14  14
#      True      3   3   3   3   3
# B    False    14  14  14  14  14
#      True      8   8   8   8   8
# C    False    17  17  17  17  17
#      True      5   5   5   5   5
# D    False    10  10  10  10  10
#      True      9   9   9   9   9
# E    False    15  15  15  15  15
#      True      5   5   5   5   5

创建多层索引

MultiIndex对象是Pandas标准Index的子类,由它来表示多层索引。可以将MultiIndex视为一个元组对序列,其中每个元组对都是唯一的。

# 序列数据 pd.MultiIndex.from_arrays
arrays=[[1,1,2,2],['A','B','A','B']] # 定义一个序列
index = pd.MultiIndex.from_arrays(arrays,names=('class','team'))
# 用这个多层索引生成对象DataFrame
pd.DataFrame({['Q1':60,'Q2':}],index=index)
# 由元组创建多层索引 pd.MultiIndex.from_tuples
# 定义一个两层的索引
arrays = [[1,1,2,2],['A','B','A','B']] 
# 转换为元组
tuples = list(zip(*arrays))
# 将元组转换为多层索引
index = pd.MultiIndex.from_tuples(tuples,names=['class','team'])
# 使用多层索引对象
pd.Series(np.random.randn(4),index=index)
# 通过笛卡儿积生成多层索引
# pd.MultiIndex.from_product(),将所有情况排列组合出来
_class = [1,2]
_team = ['A','B']
index = pd.MultiIndex.from_product([_class,_team],names=['class','team'])
pd.Series(np.random.randn(4),index=index
# 将DataFrame转为多层索引
# pd.MultiIndex.from_frame()可以将DataFrame转成多层索引对象
df_i = pd.DataFrame([['1','A'],['1','B'],
                    ['2','A'],['2','B']],columns=['class','team'])
index = pd.MultiIndex.from_frame(df_i)
pd.Series(np.random.randn(4),index=index

多层索引操作

# 索引
index_arrays = [[1,1,2,2],['男','女','男','女']]
# 列名
columns_arrays = [['2019','2019','2020','2020'],
                  ['上半年','下半年','上半年','下半年']]
# 索引转为多层
index = pd.MultiIndex.from_arrays(index_arrays,names=('班级','性别'))
columns = pd.MultiIndex.from_arrays(columns_arrays,names=('年份','学期'))
# 应用到DataFrame中
df = pd.DataFrame([(88,99,88,99),(77,88,97,98),
                  (76,89,54,78),(34,67,89,54)],
                 columns=columns,index=index)

## 索引信息

和普通索引一样,多层索引也可以查看行、列及行列的名称

df.index # 索引 是一个MultiIndex
df.columns # 列索引 也是一个MultiIndex
df.index.names # 查看行索引名称
df.columns #查看列索引名称

查看层级

多层索引由于层级较多,在数据分析时需要查看它共有多少个层级。

df.index.nlevels # 行层级数
df.index.levels # 行的层级
df.columns.nlevels # 列层级数
df.columns.levels # 列的层级

索引内容

可以取指定层级的索引内容,也可以按索引名去索引内容

# 获取索引第二层内容
df.index.get_level_values(1)
# 获取列索引的第一层数据
df.columns.get_level_values(0)

# 按索引名称获取索引内容
df.index.get_level_values('班级')
df.columns.get_level_values('年份')

排序

多层索引可以根据需要实现较为复杂的排序操作

# 使用索引名进行排序,可以指定具体的列
df.sort_values(by=['性别',('2020','下半年')])
df.index.reorder_levels([1,0]) # 等级顺序互换 返回一个多层索引对象
df.index.sortlevel(level=0,ascending=True) # 按指定级别排序 返回一个多层索引对象
df.index.reindex(df.index[::-1]) # 更换顺序,或者指定一个顺序 返回一个多层索引对象
# 其他操作
df.index.to_numpy() #生成一个笛卡儿积的元组对序列
df.index.remove_unused_levels() # 返回没有使用的层级
df.swaplevel(0,1) # 交换索引 返回一个DataFrame
df.index.droplevel(0) # 删除指定等级

数据查询

查询行

查询第一层级下的某个索引的所有内容,可以直接使用df.loc[]传入它的索引值:

df.loc[1] # 查询一班的数据

切片(如df.loc[1:2]查询1~2班的数据)也适用

如果我们要同时根据一二级索引查询,可以将需要查询的索引条件组成一个元组

df.loc[(1,'男')] # 查询1班男

查询列

查询列时,可以直接使用切片选择需要查询的列,使用元组指定相关的层级数据

df['2020'] #整个一级索引下
df[('2020','上半年')] # 指定二级索引
df['2020']['上半年'] #同上

行列查询

行列查询和单层索引一样,指定层级内容也用元组表示。slice(None)可以在元组中占位,表示本层所有内容

df.loc[(1,'男'),'2020'] # 只显示2020年1班男生

df.loc[:,(slice(None),'下半年')] #只看下半年
df.loc[(slice(None),'女'),:] #只看女生
df.loc[(1,slice(None)),:] #只看1班  
df.loc[1,:] #同上
df.loc[:,('2020',slice(None))] # 只看2020年数据

条件查询

按照一定的条件查询数据,和单层索引的数据查询一样,不过是在选择列上要按多层的规则。

# 2020 年上半年大于80的数据
df[df[('2020','上半年')]>80]

pd.IndexSlice索引数据

pd.IndeSlice 可以创建一个切片对象,轻松执行复杂的索引切片操作

idx = pd.IndexSlice
idx[0]               # 0
idx[:]               # slice(None,None,None) 
idx[0,'x']           # (0,x)
idx[0:3]             # slice(0,3,None)
idx[0:5,'x':'y']     # slice(0,5,None),slice('x','y',None)
idx = pd.IndexSlice
df.loc[idx[:,['男']],:] # 只显示男生 df.loc[idx[:,('男')],:]
df.loc[:,idx[:,['上半年']]] # 只显示上半年

df.xs()

使用df.xs()方法采用索引内容作为参数来选择多层索引数据中特定级别的数据

df.xs((1,'男'))      # 1班男生
df.xs('2020',axis=1) # 2020年
df.xs('男',level=1)   # 所有男生
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

白杆杆红伞伞

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值