【pandas教程】多重索引

多重索引

十分钟看完多重索引

# 如果不想用默认的稀疏化的索引显示形式,可以进行修改
with pd.option_context('display.multi_sparse', False):
    pass

# 新建一个多重索引DaraFrame:多重索引由MultiIndex创建,索引值至少有两个List,可以具有List数量个索引名
# 从元组创建MultiIndex.from_tuples()
tuples = list(zip(['bar','bar','baz','baz','foo','foo','qux','qux'],['one','two','one','two','one','two','one','two']))
index = pd.MultiIndex.from_tuples(tuples, names=['first', 'second'])

# 从多维数组创建MultiIndex.from_arrays()
arrays  = [['bar','bar','baz','baz','foo','foo','qux','qux'],['one','two','one','two','one','two','one','two']]
index = pd.MultiIndex.from_arrays(arrays, names = ['first', 'second'])

# 从两个列表的笛卡尔积创建MultiIndex.from_product()
iterable = [['bar', 'baz', 'foo', 'qux'], ['one', 'two']]
index = pd.MultiIndex.from_product(iterable , names=['first', 'second'])

# 从DataFrame创建MultiIndex.from_frame()
df = pd.DataFrame(np.arrays(['bar','one'],['bar','two'],['baz','one'],['baz','two'],['foo','one'],['foo','two'],['qux','one'],['qux','two']),columns=['first','second'])
index = pd.MultiIndex.from_frame(df)

# 从多维数组快速创建
index= [['bar','bar','baz','baz','foo','foo','qux','qux'],['one','two','one','two','one','two','one','two']]
df = pd.DataFrame(np.random.randn(8,2), index=index, columns=['A', 'B']])

# 获得不同层次的标签(索引值)
# 使用下标取值
index.get_level_values(0)

# 使用索引的name取值
index.get_level_values('first')

# 多层列索引下的取值(需使用[])
# DataFrame使用第一层列索引
df['bar']

# DataFrame使用第一层列索引后,第二层列索引会以列的形式排列,可以进一步对第二层索引取值(name属性为('bar', 'one'))
df['bar']['one']

# DataFrame直接使用第一层列索引、第二层列索引取值(name属性为'one')
df['bar', 'one']

# DataFrame选中多个同层列索引,列索引可重复
df[['bar','bar']]

# 多层行索引下的取值(需使用loc)
# DataFrame使用第一层行索引
df.loc['bar']

# DataFrame使用第一层行索引后,第二层行索引会以列的形式排列,可以进一步对第二层索引取值(name属性为('bar', 'one'))
df.loc['bar'].loc['one']

# DataFrame直接使用第一层行索引、第二层行索引取值(name属性为'one')
# 多重索引下选择数据,必需使用tuple打包多个索引值,例如,选择一层索引为bar,二层索引为one的值,必需使用tuple打包
df.loc[('bar', 'one')]

# DataFrame选中多个同层行索引,行索引不可重复
df.loc[['bar','baz']]

# 转置操作会互换行列索引
df = df.T

# 索引中的元组与列表
1.在索引时,一个元组被识别为一个多层级的索引值,元组中的各元素是递进关系,如(第一层索引值,第二层索引值)
2.在索引时,一个列表被识别为多个不同的索引值,列表中的各元素是并列关系,如[一个索引,另一个索引]

# 列表内嵌套元组,表示选中多个索引值
df.loc[[('A','a'), ('B','b')]] # 选中索引为(A, a)和(B, b)的值

# 元组内嵌套列表,表示不同层次索引可选的索引值
df.loc[(['A','B'], ['a','b'])] # 第一层索引可选A、B,第二层索引可选a、b

# 多层索引不能通过df[[label1, label2]]的形式进行选择,必须结合df.loc(axis=0),通过slice或pd.IndexSlice进行切片选择!!!
# 多层索引切片slice,若不指定则以None为占位符,以三级索引为例:
slice('A','B')相当于A:B
slice(None)相当于:
df.loc[(slice('A', 'B'), slice(None), slice('C1','C3'))] # 对行索引进行操作,第一层索引指定为['A', 'B'],第二层索引任意值,第三层索引指定为['C1','C3']
df.loc(axis=1)[(slice('A', 'B'), slice(None), slice('C1','C3'))] # 对列索引进行操作


# 多层索引切片pd.IndexSlice(),若不指定则以:为占位符,以三级索引为例:
df.loc[pd.IndexSlice[:, :, ['C1', 'C3']]] # 对行索引进行操作,第一层索引任意值,第二层索引任意值,第三层索引指定['C1','C3']
df.loc(axis=1)[pd.IndexSlice[:,:,['C1','C3']]] # 对列索引进行操作


# 交叉选择pd.xs(),行模式,假设二级行索引second存在'a'
df.xs('a', level='second') 等同于 df.xs('a', level=1, axis=0)

# 交叉选择pd.xs(),列模式,假设二级列索引second存在'a',指定axis=1
df = df.T
df.xs('a', level='second') 等同于 df.xs('a', level=1, axis=1)

# 交叉选择pd.xs(),混合模式,假设一级行索引存在'A',二级行索引second存在'a'
df.xs('a', level='second') 等同于 df.xs(['a','A'), level=(0,1), axis=0)

# 交叉选择pd.xs(),精简索引,选择索引后进行精简,drop_level
df.xs('a', level='second') 等同于 df.xs('a', level=1, dorp_level=True) # 第二层索引值a每个元素都有,因此可以剔除

# 交换层级swaplevel
df.swaplevel(0, 1, axis=0) # 将第一层行索引与第一层列索引互换

# 多层索引重排序reorder_levels
df.reorder_levels([1, 0], axis=0) # 第二层行索引优先排序

# 单层索引重排序sort_index
df.sort_index(level=1) # 对第二层索引排序
df.sort_index(level='second') # 传入第二层索引的name进行排序
df.sort_index(level=0,axis=1) # 对列索引进行排序

# 指定数据列为索引列set_index
df.set_index(['col1','col2'])

# 查看索引是否排序
df.index.is_lexsorted()

# 查看排序深度
df.index.lexsort_depth

# 索引重命名,行名重命名,列名重命名
df.rename(columns={0:'col0', 1:'col1'}) # 列名重命名
df.rename(index={'one':'1', 'two','2'}) # 行名重命名

# 索引层级重命名,对索引的names属性进行重命名
df.rename_axis(index=['abc', 'def'])
df.rename_axis(columns=['cols'])

# Series也可以使用索引功能
s = pd.Series(np.random.randn(8,2), index=index)
s['bar']

# 即使是索引的切片也可以获取所有被定义的索引层级
df.columns.levels # 返回所有被定义的索引
df[['foo','qux']].columns.levels # 同样返回所有被定义的索引,中括号里必需是同层索引

# 针对切片,删除未使用的索引remove_unused_levels()
new_df = df[['foo','qux']].columns.remove_unused_levels()

# 相同索引的不同对象之间的操作,会先按照索引进行对齐
s + s[:-2] # 倒数第一二行值为nan
s + s[::2] # 每隔一行的值为nan

# 如果想按照位置进行操作,切记操作前重置索引
s.reindex(index[:-2]) + s[:-2] # 在操作前,剔除左边df多出来的索引,避免nan值传播
s.reindex(index[::2]) + s[::2] # 在操作前,剔除左边df多出来的索引,避免nan值传播
s.reindex(index[:-2]) + s[:-2] 等同于 s[:-2] + s.reindex(index[:-2]) # s为引用,s.reindex()会同步修改所有s的索引
s.reindex(index[::2]) + s[::2] 等同于 s[::2] + s.reindex(index[::2]) # 同上
  • 2
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

鱼摆摆

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

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

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

打赏作者

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

抵扣说明:

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

余额充值