You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
pqxin6emf/Part1/Chapter3/3.2 Pandas进阶/3.2.2多级索引的数据转换与累计方法.md

4.2 KiB

3.2.2:多级索引的数据转换与累计方法

多级索引行列转换

使用多级索引的关键是掌握有效数据转换的方法,Pandas提供了许多操作,可以让数据在内容保持不变的同时,按照需要进行行列转换。上一关我们用stack()unstack()演示过简单的行列转换,但其实还有许多合理控制层级行列索引的方法,让我们来一探究竟。

  1. 有序和无序的索引

如果MultiIndex不是有序的索引,那么大多数切片操作都会失败,如下例:

# 首先创建一个不按字典顺序排列的多级索引Series
index = pd.MultiIndex.from_product([['a', 'c', 'b'], [1, 2]]) 
data = pd.Series(np.random.rand(6), index=index) 
data.index.names = ['char', 'int']
data
Out:
char int 
 a    1    0.003001 
		2    0.164974 
 c    1    0.741650 
		2    0.569264 
 b    1    0.001693 
		2    0.526226 
 dtype:    float64
# 如果对该多级索引使用局部切片,就会报错
try: 
		data['a':'b'] 
except KeyError as e: 
		print(type(e)) 
		print(e)
Out
<class 'KeyError'> 
'Key length (1) was greater than MultiIndex lexsort depth (0)'

问题是出在MultiIndex无序排列上,局部切片和许多其他相似的操作都要求MultiIndex的各级索引是有序的。为此,Pandas提供了许多便捷的操作完成排序,如sort_index()sortlevel()方法。

data = data.sort_index()
data["a":"b"]
Out
char int 
a	1 	0.003001
		2 	0.164974 
b	1 	0.001693 
		2 	0.526226 
 dtype: float64
  1. 索引stack与unstack

上一节提过,我们可以将一个多级索引数据集转换成简单的二维形式,可以通过level参数设置转换的索引层级。

pop
Out:
state  	year
California 2000 	33871648 
			  2010 	37253956 
New York   2000 	18976457 
			  2010 	19378102 
Texas      2000 	20851820 
			  2010 	25145561 
dtype: int64
# level=0
pop.unstack(level=0)
Out
state California New York  Texas 
year 
2000  33871648   18976457  20851820 
2010  37253956   19378102  2514556
# level=1
pop.unstack(level=1)
Out
 year 	   2000      2010 
 state 
 California 33871648 37253956 
 New York   18976457 19378102 
 Texas 	 20851820 25145561

unstack()stack()的逆操作,同时使用这两种方法pop.unstack().stack()让数据保持不变。

  1. 索引的设置与重置

层级数据维度转换的另一种方法是行列标签转换,可以通过reset_index方法实现。也可以用数据的name属性为列设置名称:

pop_flat = pop.reset_index(name='population')
pop_flat
Out:
		 state  year population 
 0 California 2000 33871648 
 1 California 2010 37253956 
 2 New York   2000 18976457 
 3 New York   2010 19378102 
 4 Texas 	 2000 20851820 
 5 Texas 	 2010 25145561

在解决实际问题的时候,可以使用DataFrameset_index方法将类似这样的原始输入数据的列直接转换成MultiIndex,返回结果就会是一个带多级索引的DataFrame

pop_flat.set_index(['state', 'year'])
Out
					population 
 state 	 year 
 California 2000  33871648 
 			 2010  37253956 
 New York   2000  18976457 
 			 2010  19378102 
 Texas 	 2000  20851820 
 	 		2010  25145561

多级索引的数据累计方法

Pandas有一些自带的数据累计方法,比如mean()sum()max()。而对于层级索引数据,可以设置参数level实现对数据子集的累计操作。以体检数据为例:

health_data
Out
 subject 	Bob 	 Guido 	Sue 
 type 		HR Temp  HR  Temp  HR  Temp 
 year visit 
 2013 1 	31.0 38.7 32.0 36.7 35.0 37.2 
		2 	44.0 37.7 50.0 35.0 29.0 36.7 
 2014 1 	30.0 37.4 39.0 37.8 61.0 36.9 
		2 	47.0 37.8 48.0 37.3 51.0 36.5

如果你需要计算每一年各项指标的平均值,那么可以将参数level设置为索引year

data_mean = health_data.mean(level='year')
data_mean
Out
 subject Bob 	  Guido 	 Sue 
 type 	HR Temp  HR   Temp  HR   Temp 
 year 
 2013    37.5 38.2 41.0 35.85 32.0 36.95 
 2014    38.5 37.6 43.5 37.55 56.0 36.70

如果再设置axis参数,就可以对列索引进行类似的累计操作了:

data_mean.mean(axis=1, level='type')
Out
type 	  HR 	Temp 
 year 
 2013 36.833333 37.000000 
 2014 46.000000 37.283333