多层索引MultiIndex

深入浅出Pandas读书笔记

C8 Pandas多层索引

使你在Series和DataFrame中存储和处理更高维度的数据

8.1 概述

8.1.1 什么是多层索引

8.1.2 通过分组产生多层索引

# 按团队分组, 各团队中平均成绩及格的人数
df.groupby(['team', df.select_dtypes('number').mean(1)>60]).count()
# 在列上产生多级索引
df.groupby('team').agg([min, max])

8.1.3 由序列创建多级索引

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

# 定义一个序列, 生成多级索引
arrays = [[1, 1, 2, 2], ['A', 'B']*2]
index = pd.MultiIndex.from_arrays(arrays, names=['class', 'team'])
index     
'''
MultiIndex([(1, 'A'),
            (1, 'B'),
            (2, 'A'),
            (2, 'B')],
           names=['class', 'team'])
'''

8.1.4 由元祖创建多层索引

使用pd.MultiIndex.from_tuples()将由元祖组成的序列转换为多层索引

arrays = [[1, 1, 2, 2], ['A', 'B']*2]
tuples = list(zip(*arrays))
index = pd.MultiIndex.from_tuples(tuples, name=['class', 'team'])
pd.Series(np.random.randn(4), index=index)
'''
class  team
1      A       1.013703
       B      -1.184143
2      A       0.870257
       B       0.893465
dtype: float64
'''

8.1.5 可迭代对象的笛卡尔积

pd.MultiIndex.from_product()可以做笛卡尔积计算

_class = [1, 2]
team = ['A', 'B']
index = pd.MultiIndex.from_product([_class, team], names=['class', 'team'])
index
'''
MultiIndex([(1, 'A'),
            (1, 'B'),
            (2, 'A'),
            (2, 'B')],
           names=['class', 'team'])
'''

8.1.6 将DataFrame转为多层索引对象

pd.MultiIndex.from_frame()可以将DataFrame的数据转为多层索引对象

df_i = pd.DataFrame([['1', 'A'], ['1', 'B'], ['2', 'B'], ['2', 'B']], columns=['class', 'name'])
index = pd.MultiIndex.from_frame(df_i)
index

8.2 多层索引操作

8.2.1 生成数据

index_arrays = [[1, 1, 2, 2,], ['男', '男', '女', '女']]
columns_arrays = [['2019', '2019', '2020', '2020'], ['上半年', '下半年']*2]
index = pd.MultiIndex.from_arrays(index_arrays, names=('班级', '性别'))
columns = pd.MultiIndex.from_arrays(columns_arrays, names=('年份', '学期'))
df = pd.DataFrame([[88, 99, 88, 99], [77, 88, 97, 98], [67, 89, 54, 78], [34, 67, 89, 54]],
                  columns=columns, index=index)
df
'''
	年份	2019	2020
学期	上半年	下半年	上半年	下半年
班级	性别				
1	男	88	99	88	99
男	77	88	97	98
2	女	67	89	54	78
女	34	67	89	54
'''

8.2.2 索引信息

df.index
'''
MultiIndex([(1, '男'),
            (1, '男'),
            (2, '女'),
            (2, '女')],
           names=['班级', '性别'])
'''
MultiIndex([(1, '男'),
            (1, '男'),
            (2, '女'),
            (2, '女')],
           names=['班级', '性别'])
'''
MultiIndex([('2019', '上半年'),
            ('2019', '下半年'),
            ('2020', '上半年'),
            ('2020', '下半年')],
           names=['年份', '学期'])
'''
df.index.names # FrozenList(['班级', '性别'])
df.columns.names # FrozenList(['年份', '学期'])

8.2.3 查看层级

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

8.2.4 索引内容

# 获取索引第二层内容
df.index.get_level_values(1)
# 获取列索引第一层内容
df.columns.get_level_values(0)
# 按索引名称取索引内容
df.index.get_level_values('班级')
df.columns.get_level_values('年份')

8.2.5 排序

df.sort_values(by=['性别', ('2020', '下半年')])
df.index.reorder_levels([1, 0]) # 等级顺序, 互换
df.swaplevel() # 等同于上面

8.2.6 其他操作

df.index.to_numpy() # 横撑一个笛卡尔积的元祖对序列
df.swaplevel()
df.index.droplevel(0) # 删除指定等级

8.3 数据查询

8.3.1 查询行

df.loc[1]
df.loc[(1, '男')]

8.3.2 查询列

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

8.3.3 行列查询

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

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

8.3.4 条件查询

df[df[('2020', '上半年')] > 80]

8.3.5 用pd.IndexSlice索引数据

8.3.6 df.xs()

若找的是level=0的数据, 不需要指定level, 找其他层需要传入level=第几层, 找columns, 需要指定axis=1

df.xs((1, '男')) # 1班男生
df.xs('2020', axis=1) # 2020年
df.xs('男', level=1) # 所有男生
df.xs(2) # 所有2班的数据
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值