Python数据分析pandas之多层高维索引

Posted ShenLiang2025

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Python数据分析pandas之多层高维索引相关的知识,希望对你有一定的参考价值。

Python数据分析pandas之多层高维索引

DataFrame多层索引

多层索引简介

众所周知Pandas的Series和DataFrame存放的是一维和二维数组,那么想存放多维数组就得通过多层索引来实现。通常一维的索引能够满足我们的大部分需求,但如果我们想通过Pandas存储高维数据,那么就要用到多层索引,这里层即是层次(hierarchy)、级(Level)。

层(维)比较好理解的例子就是地理位置,如行政区划(国家、省、市、县等)。

初始化多层索引

通过from_tuples元组生成

多层索引通过元组方式创建,这种方式索引的key存放在元组内。多层索引由levels和codes构成。

注:

1 这里多维索引的levels是元组的元素的值。

2 这里多维索引的codes是对元组元素进行的编码,如0,1,2等。

#比如这里定义了关于学生年份、学习周期定义的多层(维)索引。
import pandas as pd  index=[(2010,'期中'),(2011,'期中'),(2012,'期中'),
(2010,'期末'),(2011,'期末'),(2012,'期末')]
index = pd.MultiIndex.from_tuples(index)
#查看索引
print(index)

name=["张三","张三","张三","李四","李四","李四"]
score=[100,60,80,55,45,35]
data = np.zeros(6, dtype={'names': ('name', 'score'),'formats': ('U10', 'i4')})
data['name']=name
data['score']=score
data=pd.DataFrame(data=data,index=index)
#查看多层索引下的数据
print(data)	

#结果
MultiIndex(levels=[[2010, 2011, 2012], ['期中', '期末']],
           codes=[[0, 1, 2, 0, 1, 2], [0, 0, 0, 1, 1, 1]])
        name  score
2010 期中   张三    100
2011 期中   张三     60
2012 期中   张三     80
2010 期末   李四     55
2011 期末   李四     45
2012 期末   李四     35

通过from_arrays数组生成

#from_arrays方式是在数组里分别定义每个层(维)下的索引值,索引值会自动一一匹配,形成多层索引。它的特点是同层(维)的索引值会重复。
import pandas as pd
index=[[2010,2011,2012,2010,2011,2012],['期中','期中','期中','期末','期末','期末']]
index = pd.MultiIndex.from_arrays(index)
print(index)

name=["张三","张三","张三","李四","李四","李四"]
score=[100,60,80,55,45,35]
data = np.zeros(6, dtype={'names': ('name', 'score'),'formats': ('U10', 'i4')})
data['name']=name
data['score']=score
data=pd.DataFrame(data=data,index=index)
print(data)
#结果
MultiIndex(levels=[[2010, 2011, 2012], ['期中', '期末']],
           codes=[[0, 1, 2, 0, 1, 2], [0, 0, 0, 1, 1, 1]])
        name  score
2010 期中   张三    100
2011 期中   张三     60
2012 期中   张三     80
2010 期末   李四     55
2011 期末   李四     45
2012 期末   李四     35

通过from_product生成

#from_product方式是在数组里分别定义各自维度下的索引,索引会通过笛卡尔积的形式自动形成多层索引。它的特点是同层(维)的索引值不会重复。

import pandas as pd
index=[['期中','期末'],[2010,2011,2012]] #注意index里数组元素的顺序。
index = pd.MultiIndex.from_product(index)
print(index)

name=["张三","张三","张三","李四","李四","李四"]
score=[100,60,80,55,45,35]
data = np.zeros(6, dtype={'names': ('name', 'score'),'formats': ('U10', 'i4')})
data['name']=name
data['score']=score
data=pd.DataFrame(data=data,index=index)
print(data)
#结果
MultiIndex(levels=[['期中', '期末'], [2010, 2011, 2012]],
           codes=[[0, 0, 0, 1, 1, 1], [0, 1, 2, 0, 1, 2]])
        name  score
期中 2010   张三    100
   2011   张三     60
   2012   张三     80
期末 2010   李四     55
   2011   李四     45
   2012   李四     35

访问多层索引

给索引命名

索引如果不指定名字,默认是None,我们可以通过dataframe的index.names给索引命名。

#通过index.names给索引赋值
import pandas as pd
index=[['期中','期末'],[2010,2011,2012]]
index = pd.MultiIndex.from_product(index)
print(index)

name=["张三","张三","张三","李四","李四","李四"]
score=[100,60,80,55,45,35]
data = np.zeros(6, dtype={'names': ('name', 'score'),'formats': ('U10', 'i4')})
data['name']=name
data['score']=score
data=pd.DataFrame(data=data,index=index)
print(data.index.names)
data.index.names=['period','year']
print(data.index.names)
#结果
[None, None]
['period', 'year']

通过loc检索切片多层索引对象

import pandas as pd
index=[['期中','期末'],[2010,2011,2012]]
index = pd.MultiIndex.from_product(index)

name=["张三","张三","张三","李四","李四","李四"]
score=[100,60,80,55,45,35]
data = np.zeros(6, dtype={'names': ('name', 'score'),'formats': ('U10', 'i4')})
data['name']=name
data['score']=score
data=pd.DataFrame(data=data,index=index)
print(data.loc['期中',2010])
#如下注释部分效果同上
# print(data.loc[('期中',2011),['score','name']])
#仅检索分数信息
print(data.loc['期中',2010]['score'])
print(data.loc['期中',2010].loc['score'])
#结果
name      张三
score    100
Name: (期中, 2010), dtype: object
100
100

通过xs访问多层索引对象的索引

#通过xs对多层索引对象的索引和列分别访问。
注:1这里的xs的参数axis='columns' 和axis=1等价,为列方向,axis='index' 和axis=0等价为索引方向。
2 xs在访问索引时需要指定要查询的具体key值,否则会报错。
3 xs在访问索引时需要指定对应的level,否则会报错。

#注意,当前多层索引为学期周期、年份、难度,学生数据(列)为姓名、分数。

#查询层年份(2011年)和等级(B)对应的数据。

import pandas as pd
index=[['期中','期末'],[2010,2011,2012],['A','B']]
index = pd.MultiIndex.from_product(index)

name=["张三","张三","张三","张三","张三","张三","李四","李四","李四","李四","李四","李四"]
score=[100,60,80,90,50,70,55,45,35,45,35,25]
data = np.zeros(12, dtype={'names': ('name', 'score'),'formats': ('U10', 'i4')})
data['name']=name
data['score']=score
data=pd.DataFrame(data=data,index=index)
data.index.name=['period','year','dgreee']
#查询2010年的数据,这里年份所在的level是第2个,所以这里level=1.
print(data.xs(2011,axis=0,level=1)) #axis='columns' axis=1
print("*******************************") #查询等级B对应的数据,这里的等级索引所在的level是第3个,所以这里level=2.
print(data.xs('B',axis=0,level=2)) #axis='columns' axis=1
#结果
     name  score
期中 A   张三     80
   B   张三     90
期末 A   李四     35
   B   李四     45
*******************************         
name  score 
期中 2010   张三     60    
     2011   张三     90    
    2012   张三     70 
期末 2010   李四     45    
     2011   李四     45    
     2012   李四     25

通过xs访问多层索引对象的列

类似xs对索引的检索,这里指定axis='columns' 或axis=1即可。

#查询分数列
import pandas as pd
index=[['期中','期末'],[2010,2011,2012],['A','B']]
index = pd.MultiIndex.from_product(index)

name=["张三","张三","张三","张三","张三","张三","李四","李四","李四","李四","李四","李四"]
score=[100,60,80,90,50,70,55,45,35,45,35,25]
data = np.zeros(12, dtype={'names': ('name', 'score'),'formats': ('U10', 'i4')})
data['name']=name
data['score']=score
data=pd.DataFrame(data=data,index=index)
data.index.name=['period','year','dgreee']
print(data.xs('score',axis='columns')) 
#等价于#axis='columns'
#print(data.xs('score',axis=1))
#结果
期中  2010  A    100
          B     60
    2011  A     80
          B     90
    2012  A     50
          B     70
期末  2010  A     55
          B     45
    2011  A     35
          B     45
    2012  A     35
          B     25

通过T对多层索引转置

#通过DataFrame的T方法对原有的多层索引进行转置,即原有的列为索引,索引合并为列。
index=[['期中','期末'],[2010,2011,2012]]
index = pd.MultiIndex.from_product(index)

name=["张三","张三","张三","李四","李四","李四"]
score=[100,60,80,55,45,35]
data = np.zeros(6, dtype={'names': ('name', 'score'),'formats': ('U10', 'i4')})
data['name']=name
data['score']=score
data=pd.DataFrame(data=data,index=index)
data.index.name=['period','year']
print(data.T)
#结果
        期中             期末          
      2010 2011 2012 2010 2011 2012
name    张三   张三   张三   李四   李四   李四
score  100   60   80   55   45   35

通过unstack将索引转换为列

#指定索引序号,通过unstack将该索引转换为列。
import pandas as pd
index=[['期中','期末'],[2010,2011,2012],['A','B']]
index = pd.MultiIndex.from_product(index)

name=["张三","张三","张三","张三","张三","张三","李四","李四","李四","李四","李四","李四"]
score=[100,60,80,90,50,70,55,45,35,45,35,25]
data = np.zeros(12, dtype={'names': ('name', 'score'),'formats': ('U10', 'i4')})

data['name']=name
data['score']=score
data=pd.DataFrame(data=data,index=index)
data.index.name=['period','year','dgreee']
#这里将第2个索即年份转换为了列。
print(data.unstack(level=1))
#结果
     name           score          
     2010 2011 2012  2010 2011 2012
期中 A   张三   张三   张三   100   80   50
   B   张三   张三   张三    60   90   70
期末 A   李四   李四   李四    55   35   35
   B   李四   李四   李四    45   45   25

通过stack将列转换为索引

#通过stack将列转回索引。
import pandas as pd
index=[['期中','期末'],[2010,2011,2012],['A','B']]
index = pd.MultiIndex.from_product(index)

name=["张三","张三","张三","张三","张三","张三","李四","李四","李四","李四","李四","李四"]
score=[100,60,80,90,50,70,55,45,35,45,35,25]
data = np.zeros(12, dtype={'names': ('name', 'score'),'formats': ('U10', 'i4')})

data['name']=name
data['score']=score
data=pd.DataFrame(data=data,index=index)
data.index.name=['period','year','dgreee']
#这里相当于还是data自身,因为做了索引转列,又还原回去。
print(data.unstack(level=1)) .stack())
#结果
             name  score 
期中 A 2010   张三    100      
       2011   张三     80      
	   2012   张三     50    
	 B 2010   张三     60      
	   2011   张三     90      
	   2012   张三     70 
期末 A 2010   李四     55      
       2011   李四     35      
	   2012   李四     35    
	 B 2010   李四     45      
	   2011   李四     45      
	   2012   李四     25

按照多层索引进行统计计算

#按照指定的多层索引进行列的汇总统计计算,当前以均值为例
import pandas as pd
index=[['期中','期末'],[2010,2011,2012],['A','B']]
index = pd.MultiIndex.from_product(index)

name=["张三","张三","张三","张三","张三","张三","李四","李四","李四","李四","李四","李四"]
score=[100,60,80,90,50,70,55,45,35,45,35,25]
data = np.zeros(12, dtype={'names': ('name', 'score'),'formats': ('U10', 'i4')})

data['name']=name
data['score']=score
data=pd.DataFrame(data=data,index=index)
data.index.name=['period','year','dgreee']
print(data)
#这里的level=1即对应year索引。
print(data.mean(level=1))
#结果,这里以2012年为例,计算明细为(50+70+35+25)/4=180/4=45.0
          name  score
期中 2010 A   张三    100
        B   张三     60
   2011 A   张三     80
        B   张三     90
   2012 A   张三     50
        B   张三     70
期末 2010 A   李四     55
        B   李四     45
   2011 A   李四     35
        B   李四     45
   2012 A   李四     35
        B   李四     25
      score
2010   65.0
2011   62.5
2012   45.0

以上是关于Python数据分析pandas之多层高维索引的主要内容,如果未能解决你的问题,请参考以下文章

Python学习教程:实战-用Pandas做多层级索引

Python数据分析之pandas学习

Python数据分析之pandas学习

数据分析—学会用pandas做多层索引

pandas层次化索引

使用 Python pandas 将具有逗号值的字符串转换为多层索引的单独行