pandas Multiindex 对层次化索引进行切片或索引

选取 DataFrame 使用正常的 loc 或 iloc 索引数据,但是对于 Multiindex 层次化索引该怎么索引数据呢?

一、准备工作

引入需要使用的包裹

in [1]:	import pandas as pd 
		import numpy as np

创建层次化索引,使用 from_tuples 方法创建层次化索引

in [2]:	arrays = [['bar', 'bar', 'baz', 'baz', 'foo', 'foo', 'qux', 'qux'],
		          ['one', 'two', 'one', 'two', 'one', 'two', 'one', 'two']]
		tuples = list(zip(*arrays))
		index = pd.MultiIndex.from_tuples(tuples, names=['first', 'second'])

新建数据,将层次化索引建为列标签

in [3]:	arrays = [np.array(['bar', 'bar', 'baz', 'baz', 'foo', 'foo', 'qux', 'qux']),np.array(['one', 'two', 'one', 'two', 'one', 'two', 'one', 'two'])]
		df = pd.DataFrame(np.random.randn(3, 8), index=['A', 'B', 'C'], columns=index)
in [4]:	df
out[4]:
first 	bar 					baz 					foo 					qux
second 	one 		two 		one 		two 		one 		two 		one 		two
	A 	0.778818 	2.521446 	0.415141 	0.384948 	0.094009 	-0.590066 	-0.703295 	0.983774
	B 	-0.237388 	-0.211130 	0.108585 	0.610035 	-1.844551 	-0.408197 	-0.398825 	-0.577074
	C 	0.239472 	0.208049 	-0.477733 	-0.295725 	-0.645410 	0.444975 	-1.565026 	1.211517
in [5]:	df.index
out[5]:	Index(['A', 'B', 'C'], dtype='object')
in [6]:	df.columns
out[6]:	MultiIndex(levels=[['bar', 'baz', 'foo', 'qux'], ['one', 'two']],
           codes=[[0, 0, 1, 1, 2, 2, 3, 3], [0, 1, 0, 1, 0, 1, 0, 1]],
           names=['first', 'second'])

可以看到行索引只是正常的索引,而列标签却是层次化索引

二、对列标签(层次化索引)进行正常索引操作

对于列标签来说,层次化索引跟正常索引的选取没有什么区别

in [7]:	df['bar']
out[7]:	second 	one 	two
	A 	0.778818 	2.521446
	B 	-0.237388 	-0.211130
	C 	0.239472 	0.208049
in [8]:	df['bar', 'one']
out[8]:
	A    0.778818
	B   -0.237388
	C    0.239472
	Name: (bar, one), dtype: float64

三、对行标签(层次化索引)进行索引

in [9]:	df = df.T
		df.loc[('bar', 'two')]
out[9]:
A    2.521446
B   -0.211130
C    0.208049
Name: (bar, two), dtype: float64

使用 T 转置数据,将层次化索引的列标签转置为层次化行索引

in [10]: df.loc[('bar', 'two'), 'A']
out[10]: 2.5214458248137617
in [11]: df.loc['baz':'foo']
out[11]:
 					A 			B 			C
first 	second 			
baz 	one 	0.415141 	0.108585 	-0.477733
two 			0.384948 	0.610035 	-0.295725
foo 	one 	0.094009 	-1.844551 	-0.645410
two 			-0.590066 	-0.408197 	0.444975

对于层次化行索引进行切片或索引数据会比较麻烦,可以使用 loc 并且使用元组索引数据

四、使用xs进行索引

pandans 提供了 xs 方法可以对 Multiindex 进行更为细腻的索引操作,可以直接指定层次化索引中元素和层级

in [12]: df.xs('one', level='second')
out[12]:
 			A 			B 			C
first 			
bar 	0.778818 	-0.237388 	0.239472
baz 	0.415141 	0.108585 	-0.477733
foo 	0.094009 	-1.844551 	-0.645410
qux 	-0.703295 	-0.398825 	-1.565026

另外可以使用 loc 和 slice 方法进行切片操作,其实使用slice 和直接使用元组是没有区别的。

in [13]: df.loc[(slice(None), 'one'), :]
out[13]:
 					A 			B 			C
first 	second 			
bar 	one 	0.778818 	-0.237388 	0.239472
baz 	one 	0.415141 	0.108585 	-0.477733
foo 	one 	0.094009 	-1.844551 	-0.645410
qux 	one 	-0.703295 	-0.398825 	-1.565026

对于列标签(层次化索引) 可以使用 axis=1 来指定轴

in [15]: df = df.T
in [16]: df.xs('one', level='second', axis=1)
out[16]:
first 	bar 	baz 		foo 		qux
A 	0.778818 	0.415141 	0.094009 	-0.703295
B 	-0.237388 	0.108585 	-1.844551 	-0.398825
C 	0.239472 	-0.477733 	-0.645410 	-1.565026

对于列标签(层次化索引)同样可以使用 slice 进行切片操作

in [17]: df.loc[:, (slice(None), 'one')]
out[17]: 
first 	bar 	baz 	foo 	qux
second 	one 	one 	one 	one
A 	0.778818 	0.415141 	0.094009 	-0.703295
B 	-0.237388 	0.108585 	-1.844551 	-0.398825
C 	0.239472 	-0.477733 	-0.645410 	-1.565026
in [18]: df.xs(('one', 'bar'), level=('second', 'first'), axis=1)
in [18]: 
first 	bar
second 	one
A 	0.778818
B 	-0.237388
C 	0.239472

还可以使用 drop_level 来指定是否显示所有的层次化索引

in [19]: df.xs('one', level='second', axis=1, drop_level=False)
out[19]:
first 	bar 	baz 	foo 	qux
second 	one 	one 	one 	one
A 	0.778818 	0.415141 	0.094009 	-0.703295
B 	-0.237388 	0.108585 	-1.844551 	-0.398825
C 	0.239472 	-0.477733 	-0.645410 	-1.565026
in [20]: df.xs('one', level='second', axis=1)
out[20]:
first 	bar 	baz 	foo 	qux
A 	0.778818 	0.415141 	0.094009 	-0.703295
B 	-0.237388 	0.108585 	-1.844551 	-0.398825
C 	0.239472 	-0.477733 	-0.645410 	-1.565026

更加详细的内容可以参考 MultiIndex,这里面详细的讲述了层次化索引的创建和使用方法。

  • 7
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值