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
|